LLVM 20.0.0git
XtensaISelDAGToDAG.cpp
Go to the documentation of this file.
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"
20#include "llvm/Support/Debug.h"
22
23using namespace llvm;
24
25#define DEBUG_TYPE "xtensa-isel"
26
27namespace {
28
29class XtensaDAGToDAGISel : public SelectionDAGISel {
30 const XtensaSubtarget *Subtarget = nullptr;
31
32public:
33 explicit XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
34 : SelectionDAGISel(TM, OptLevel) {}
35
36 bool runOnMachineFunction(MachineFunction &MF) override {
37 Subtarget = &MF.getSubtarget<XtensaSubtarget>();
39 }
40
41 void Select(SDNode *Node) override;
42
44 InlineAsm::ConstraintCode ConstraintID,
45 std::vector<SDValue> &OutOps) override;
46
47 // For load/store instructions generate (base+offset) pair from
48 // memory address. The offset must be a multiple of scale argument.
49 bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset,
50 int Scale) {
51 EVT ValTy = Addr.getValueType();
52
53 // if Address is FI, get the TargetFrameIndex.
54 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
55 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
56 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy);
57
58 return true;
59 }
60
61 if (TM.isPositionIndependent()) {
62 DiagnosticInfoUnsupported Diag(CurDAG->getMachineFunction().getFunction(),
63 "PIC relocations are not supported ",
64 Addr.getDebugLoc());
65 CurDAG->getContext()->diagnose(Diag);
66 }
67
68 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
69 Addr.getOpcode() == ISD::TargetGlobalAddress))
70 return false;
71
72 // Addresses of the form FI+const
73 bool Valid = false;
74 if (CurDAG->isBaseWithConstantOffset(Addr)) {
75 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
76 int64_t OffsetVal = CN->getSExtValue();
77
78 Valid = isValidAddrOffset(Scale, OffsetVal);
79
80 if (Valid) {
81 // If the first operand is a FI, get the TargetFI Node.
82 if (FrameIndexSDNode *FIN =
83 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
84 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
85 else
86 Base = Addr.getOperand(0);
87
88 Offset =
89 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), ValTy);
90 return true;
91 }
92 }
93
94 // Last case
95 Base = Addr;
96 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType());
97 return true;
98 }
99
100 bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) {
101 return selectMemRegAddr(Addr, Base, Offset, 1);
102 }
103
104 bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) {
105 return selectMemRegAddr(Addr, Base, Offset, 2);
106 }
107
108 bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) {
109 return selectMemRegAddr(Addr, Base, Offset, 4);
110 }
111
112// Include the pieces autogenerated from the target description.
113#include "XtensaGenDAGISel.inc"
114}; // namespace
115
116class XtensaDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
117public:
118 static char ID;
119
120 XtensaDAGToDAGISelLegacy(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
122 ID, std::make_unique<XtensaDAGToDAGISel>(TM, OptLevel)) {}
123
124 StringRef getPassName() const override {
125 return "Xtensa DAG->DAG Pattern Instruction Selection";
126 }
127};
128} // end anonymous namespace
129
130char XtensaDAGToDAGISelLegacy::ID = 0;
131
133 CodeGenOptLevel OptLevel) {
134 return new XtensaDAGToDAGISelLegacy(TM, OptLevel);
135}
136
137void XtensaDAGToDAGISel::Select(SDNode *Node) {
138 SDLoc DL(Node);
139 EVT VT = Node->getValueType(0);
140
141 // If we have a custom node, we already have selected!
142 if (Node->isMachineOpcode()) {
143 Node->setNodeId(-1);
144 return;
145 }
146
147 switch (Node->getOpcode()) {
148 case ISD::SHL: {
149 SDValue N0 = Node->getOperand(0);
150 SDValue N1 = Node->getOperand(1);
151 auto *C = dyn_cast<ConstantSDNode>(N1);
152 // If C is constant in range [1..31] then we can generate SLLI
153 // instruction using pattern matching, otherwise generate SLL.
154 if (!C || C->isZero()) {
155 SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N1);
156 SDNode *SLL =
157 CurDAG->getMachineNode(Xtensa::SLL, DL, VT, N0, SDValue(SSL, 0));
158 ReplaceNode(Node, SLL);
159 return;
160 }
161 break;
162 }
163 case ISD::SRL: {
164 SDValue N0 = Node->getOperand(0);
165 SDValue N1 = Node->getOperand(1);
166 auto *C = dyn_cast<ConstantSDNode>(N1);
167
168 // If C is constant then we can generate SRLI
169 // instruction using pattern matching or EXTUI, otherwise generate SRL.
170 if (C) {
171 if (isUInt<4>(C->getZExtValue()))
172 break;
173 unsigned ShAmt = C->getZExtValue();
174 SDNode *EXTUI = CurDAG->getMachineNode(
175 Xtensa::EXTUI, DL, VT, N0, CurDAG->getTargetConstant(ShAmt, DL, VT),
176 CurDAG->getTargetConstant(32 - ShAmt, DL, VT));
177 ReplaceNode(Node, EXTUI);
178 return;
179 }
180
181 SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);
182 SDNode *SRL =
183 CurDAG->getMachineNode(Xtensa::SRL, DL, VT, N0, SDValue(SSR, 0));
184 ReplaceNode(Node, SRL);
185 return;
186 }
187 case ISD::SRA: {
188 SDValue N0 = Node->getOperand(0);
189 SDValue N1 = Node->getOperand(1);
190 auto *C = dyn_cast<ConstantSDNode>(N1);
191 // If C is constant then we can generate SRAI
192 // instruction using pattern matching, otherwise generate SRA.
193 if (!C) {
194 SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);
195 SDNode *SRA =
196 CurDAG->getMachineNode(Xtensa::SRA, DL, VT, N0, SDValue(SSR, 0));
197 ReplaceNode(Node, SRA);
198 return;
199 }
200 break;
201 }
202 case XtensaISD::SRCL: {
203 SDValue N0 = Node->getOperand(0);
204 SDValue N1 = Node->getOperand(1);
205 SDValue N2 = Node->getOperand(2);
206 SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N2);
207 SDNode *SRC =
208 CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSL, 0));
209 ReplaceNode(Node, SRC);
210 return;
211 }
212 case XtensaISD::SRCR: {
213 SDValue N0 = Node->getOperand(0);
214 SDValue N1 = Node->getOperand(1);
215 SDValue N2 = Node->getOperand(2);
216 SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N2);
217 SDNode *SRC =
218 CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSR, 0));
219 ReplaceNode(Node, SRC);
220 return;
221 }
222 }
223
224 SelectCode(Node);
225}
226
227bool XtensaDAGToDAGISel::SelectInlineAsmMemoryOperand(
228 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
229 std::vector<SDValue> &OutOps) {
230 switch (ConstraintID) {
231 default:
232 llvm_unreachable("Unexpected asm memory constraint");
233 case InlineAsm::ConstraintCode::m: {
235
236 selectMemRegAddr(Op, Base, Offset, 4);
237 OutOps.push_back(Base);
238 OutOps.push_back(Offset);
239
240 return false;
241 }
242 }
243 return false;
244}
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
uint64_t Addr
uint64_t getZExtValue() const
int64_t getSExtValue() const
This class represents an Operation in the Expression.
Diagnostic information for unsupported feature in backend.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
virtual bool runOnMachineFunction(MachineFunction &mf)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ TargetExternalSymbol
Definition: ISDOpcodes.h:175
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:170
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:735
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
FunctionPass * createXtensaISelDag(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
bool isValidAddrOffset(int Scale, int64_t OffsetVal)
Definition: XtensaUtils.cpp:17
Extended Value Type.
Definition: ValueTypes.h:35