1 | //===- XtensaISelDAGToDAG.cpp - A dag to dag inst selector for Xtensa -----===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines an instruction selector for the Xtensa target. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "Xtensa.h" |
14 | #include "XtensaTargetMachine.h" |
15 | #include "XtensaUtils.h" |
16 | #include "llvm/CodeGen/MachineFunction.h" |
17 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
18 | #include "llvm/CodeGen/SelectionDAGISel.h" |
19 | #include "llvm/IR/DiagnosticInfo.h" |
20 | #include "llvm/Support/Debug.h" |
21 | #include "llvm/Support/raw_ostream.h" |
22 | |
23 | using namespace llvm; |
24 | |
25 | #define DEBUG_TYPE "xtensa-isel" |
26 | |
27 | namespace { |
28 | |
29 | class XtensaDAGToDAGISel : public SelectionDAGISel { |
30 | public: |
31 | static char ID; |
32 | |
33 | XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel) |
34 | : SelectionDAGISel(ID, TM, OptLevel) {} |
35 | |
36 | StringRef getPassName() const override { |
37 | return "Xtensa DAG->DAG Pattern Instruction Selection" ; |
38 | } |
39 | |
40 | void Select(SDNode *Node) override; |
41 | |
42 | // For load/store instructions generate (base+offset) pair from |
43 | // memory address. The offset must be a multiple of scale argument. |
44 | bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset, |
45 | int Scale) { |
46 | EVT ValTy = Addr.getValueType(); |
47 | |
48 | // if Address is FI, get the TargetFrameIndex. |
49 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
50 | Base = CurDAG->getTargetFrameIndex(FI: FIN->getIndex(), VT: ValTy); |
51 | Offset = CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Addr), VT: ValTy); |
52 | |
53 | return true; |
54 | } |
55 | |
56 | if (TM.isPositionIndependent()) { |
57 | DiagnosticInfoUnsupported Diag(CurDAG->getMachineFunction().getFunction(), |
58 | "PIC relocations are not supported " , |
59 | Addr.getDebugLoc()); |
60 | CurDAG->getContext()->diagnose(DI: Diag); |
61 | } |
62 | |
63 | if ((Addr.getOpcode() == ISD::TargetExternalSymbol || |
64 | Addr.getOpcode() == ISD::TargetGlobalAddress)) |
65 | return false; |
66 | |
67 | // Addresses of the form FI+const |
68 | bool Valid = false; |
69 | if (CurDAG->isBaseWithConstantOffset(Op: Addr)) { |
70 | ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(i: 1)); |
71 | int64_t OffsetVal = CN->getSExtValue(); |
72 | |
73 | Valid = isValidAddrOffset(Scale, OffsetVal); |
74 | |
75 | if (Valid) { |
76 | // If the first operand is a FI, get the TargetFI Node |
77 | if (FrameIndexSDNode *FIN = |
78 | dyn_cast<FrameIndexSDNode>(Addr.getOperand(i: 0))) |
79 | Base = CurDAG->getTargetFrameIndex(FI: FIN->getIndex(), VT: ValTy); |
80 | else |
81 | Base = Addr.getOperand(i: 0); |
82 | |
83 | Offset = |
84 | CurDAG->getTargetConstant(Val: CN->getZExtValue(), DL: SDLoc(Addr), VT: ValTy); |
85 | return true; |
86 | } |
87 | } |
88 | |
89 | // Last case |
90 | Base = Addr; |
91 | Offset = CurDAG->getTargetConstant(Val: 0, DL: SDLoc(Addr), VT: Addr.getValueType()); |
92 | return true; |
93 | } |
94 | |
95 | bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) { |
96 | return selectMemRegAddr(Addr, Base, Offset, Scale: 1); |
97 | } |
98 | |
99 | bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) { |
100 | return selectMemRegAddr(Addr, Base, Offset, Scale: 2); |
101 | } |
102 | |
103 | bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) { |
104 | return selectMemRegAddr(Addr, Base, Offset, Scale: 4); |
105 | } |
106 | |
107 | // Include the pieces autogenerated from the target description. |
108 | #include "XtensaGenDAGISel.inc" |
109 | }; // namespace |
110 | } // end anonymous namespace |
111 | |
112 | char XtensaDAGToDAGISel::ID = 0; |
113 | |
114 | FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM, |
115 | CodeGenOptLevel OptLevel) { |
116 | return new XtensaDAGToDAGISel(TM, OptLevel); |
117 | } |
118 | |
119 | void XtensaDAGToDAGISel::Select(SDNode *Node) { |
120 | SDLoc DL(Node); |
121 | |
122 | // If we have a custom node, we already have selected! |
123 | if (Node->isMachineOpcode()) { |
124 | Node->setNodeId(-1); |
125 | return; |
126 | } |
127 | |
128 | SelectCode(Node); |
129 | } |
130 | |