LLVM 22.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
14#include "Xtensa.h"
15#include "XtensaTargetMachine.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
43 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
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.
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 CurDAG->getContext()->diagnose(DiagnosticInfoUnsupported(
63 CurDAG->getMachineFunction().getFunction(),
64 "PIC relocations are not supported", Addr.getDebugLoc()));
65 }
66
67 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
69 return false;
70
71 // Addresses of the form FI+const
72 bool Valid = false;
73 if (CurDAG->isBaseWithConstantOffset(Addr)) {
75 int64_t OffsetVal = CN->getSExtValue();
76
77 Valid = Xtensa::isValidAddrOffset(Scale, OffsetVal);
78
79 if (Valid) {
80 // If the first operand is a FI, get the TargetFI Node.
81 if (FrameIndexSDNode *FIN =
83 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
84 else
85 Base = Addr.getOperand(0);
86
87 Offset =
88 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), ValTy);
89 return true;
90 }
91 }
92
93 // Last case
94 Base = Addr;
95 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType());
96 return true;
97 }
98
99 bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) {
100 return selectMemRegAddr(Addr, Base, Offset, 1);
101 }
102
103 bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) {
104 return selectMemRegAddr(Addr, Base, Offset, 2);
105 }
106
107 bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) {
108 return selectMemRegAddr(Addr, Base, Offset, 4);
109 }
110
111// Include the pieces autogenerated from the target description.
112#include "XtensaGenDAGISel.inc"
113}; // namespace
114
115class XtensaDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
116public:
117 static char ID;
118
119 XtensaDAGToDAGISelLegacy(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
121 ID, std::make_unique<XtensaDAGToDAGISel>(TM, OptLevel)) {}
122
123 StringRef getPassName() const override {
124 return "Xtensa DAG->DAG Pattern Instruction Selection";
125 }
126};
127} // end anonymous namespace
128
129char XtensaDAGToDAGISelLegacy::ID = 0;
130
132 CodeGenOptLevel OptLevel) {
133 return new XtensaDAGToDAGISelLegacy(TM, OptLevel);
134}
135
136void XtensaDAGToDAGISel::Select(SDNode *Node) {
137 SDLoc DL(Node);
138 EVT VT = Node->getValueType(0);
139
140 // If we have a custom node, we already have selected!
141 if (Node->isMachineOpcode()) {
142 Node->setNodeId(-1);
143 return;
144 }
145
146 switch (Node->getOpcode()) {
147 case ISD::SHL: {
148 SDValue N0 = Node->getOperand(0);
149 SDValue N1 = Node->getOperand(1);
150 auto *C = dyn_cast<ConstantSDNode>(N1);
151 // If C is constant in range [1..31] then we can generate SLLI
152 // instruction using pattern matching, otherwise generate SLL.
153 if (!C || C->isZero()) {
154 SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N1);
155 SDNode *SLL =
156 CurDAG->getMachineNode(Xtensa::SLL, DL, VT, N0, SDValue(SSL, 0));
157 ReplaceNode(Node, SLL);
158 return;
159 }
160 break;
161 }
162 case ISD::SRL: {
163 SDValue N0 = Node->getOperand(0);
164 SDValue N1 = Node->getOperand(1);
165 auto *C = dyn_cast<ConstantSDNode>(N1);
166
167 // If C is constant then we can generate SRLI
168 // instruction using pattern matching or EXTUI, otherwise generate SRL.
169 if (C) {
170 if (isUInt<4>(C->getZExtValue()))
171 break;
172 unsigned ShAmt = C->getZExtValue();
173 SDNode *EXTUI = CurDAG->getMachineNode(
174 Xtensa::EXTUI, DL, VT, N0, CurDAG->getTargetConstant(ShAmt, DL, VT),
175 CurDAG->getTargetConstant(32 - ShAmt, DL, VT));
176 ReplaceNode(Node, EXTUI);
177 return;
178 }
179
180 SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);
181 SDNode *SRL =
182 CurDAG->getMachineNode(Xtensa::SRL, DL, VT, N0, SDValue(SSR, 0));
183 ReplaceNode(Node, SRL);
184 return;
185 }
186 case ISD::SRA: {
187 SDValue N0 = Node->getOperand(0);
188 SDValue N1 = Node->getOperand(1);
189 auto *C = dyn_cast<ConstantSDNode>(N1);
190 // If C is constant then we can generate SRAI
191 // instruction using pattern matching, otherwise generate SRA.
192 if (!C) {
193 SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);
194 SDNode *SRA =
195 CurDAG->getMachineNode(Xtensa::SRA, DL, VT, N0, SDValue(SSR, 0));
196 ReplaceNode(Node, SRA);
197 return;
198 }
199 break;
200 }
201 case XtensaISD::SRCL: {
202 SDValue N0 = Node->getOperand(0);
203 SDValue N1 = Node->getOperand(1);
204 SDValue N2 = Node->getOperand(2);
205 SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N2);
206 SDNode *SRC =
207 CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSL, 0));
208 ReplaceNode(Node, SRC);
209 return;
210 }
211 case XtensaISD::SRCR: {
212 SDValue N0 = Node->getOperand(0);
213 SDValue N1 = Node->getOperand(1);
214 SDValue N2 = Node->getOperand(2);
215 SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N2);
216 SDNode *SRC =
217 CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSR, 0));
218 ReplaceNode(Node, SRC);
219 return;
220 }
221 }
222
223 SelectCode(Node);
224}
225
226bool XtensaDAGToDAGISel::SelectInlineAsmMemoryOperand(
227 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
228 std::vector<SDValue> &OutOps) {
229 switch (ConstraintID) {
230 default:
231 llvm_unreachable("Unexpected asm memory constraint");
232 case InlineAsm::ConstraintCode::m: {
234
235 selectMemRegAddr(Op, Base, Offset, 4);
236 OutOps.push_back(Base);
237 OutOps.push_back(Offset);
238
239 return false;
240 }
241 }
242 return false;
243}
return SDValue()
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
uint64_t getZExtValue() const
int64_t getSExtValue() const
Diagnostic information for unsupported feature in backend.
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
EVT getValueType() const
Return the ValueType of the referenced return value.
const DebugLoc & getDebugLoc() const
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ TargetExternalSymbol
Definition ISDOpcodes.h:185
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition ISDOpcodes.h:180
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:756
bool isValidAddrOffset(int Scale, int64_t OffsetVal)
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
FunctionPass * createXtensaISelDag(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:198
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:82
DWARFExpression::Operation Op
Extended Value Type.
Definition ValueTypes.h:35