1 //===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===//
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 VE target.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "VETargetMachine.h"
14 #include "llvm/CodeGen/MachineRegisterInfo.h"
15 #include "llvm/CodeGen/SelectionDAGISel.h"
16 #include "llvm/IR/Intrinsics.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
20 using namespace llvm;
21
22 //===----------------------------------------------------------------------===//
23 // Instruction Selector Implementation
24 //===----------------------------------------------------------------------===//
25
26 /// Convert a DAG integer condition code to a VE ICC condition.
intCondCode2Icc(ISD::CondCode CC)27 inline static VECC::CondCode intCondCode2Icc(ISD::CondCode CC) {
28 switch (CC) {
29 default:
30 llvm_unreachable("Unknown integer condition code!");
31 case ISD::SETEQ:
32 return VECC::CC_IEQ;
33 case ISD::SETNE:
34 return VECC::CC_INE;
35 case ISD::SETLT:
36 return VECC::CC_IL;
37 case ISD::SETGT:
38 return VECC::CC_IG;
39 case ISD::SETLE:
40 return VECC::CC_ILE;
41 case ISD::SETGE:
42 return VECC::CC_IGE;
43 case ISD::SETULT:
44 return VECC::CC_IL;
45 case ISD::SETULE:
46 return VECC::CC_ILE;
47 case ISD::SETUGT:
48 return VECC::CC_IG;
49 case ISD::SETUGE:
50 return VECC::CC_IGE;
51 }
52 }
53
54 /// Convert a DAG floating point condition code to a VE FCC condition.
fpCondCode2Fcc(ISD::CondCode CC)55 inline static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC) {
56 switch (CC) {
57 default:
58 llvm_unreachable("Unknown fp condition code!");
59 case ISD::SETFALSE:
60 return VECC::CC_AF;
61 case ISD::SETEQ:
62 case ISD::SETOEQ:
63 return VECC::CC_EQ;
64 case ISD::SETNE:
65 case ISD::SETONE:
66 return VECC::CC_NE;
67 case ISD::SETLT:
68 case ISD::SETOLT:
69 return VECC::CC_L;
70 case ISD::SETGT:
71 case ISD::SETOGT:
72 return VECC::CC_G;
73 case ISD::SETLE:
74 case ISD::SETOLE:
75 return VECC::CC_LE;
76 case ISD::SETGE:
77 case ISD::SETOGE:
78 return VECC::CC_GE;
79 case ISD::SETO:
80 return VECC::CC_NUM;
81 case ISD::SETUO:
82 return VECC::CC_NAN;
83 case ISD::SETUEQ:
84 return VECC::CC_EQNAN;
85 case ISD::SETUNE:
86 return VECC::CC_NENAN;
87 case ISD::SETULT:
88 return VECC::CC_LNAN;
89 case ISD::SETUGT:
90 return VECC::CC_GNAN;
91 case ISD::SETULE:
92 return VECC::CC_LENAN;
93 case ISD::SETUGE:
94 return VECC::CC_GENAN;
95 case ISD::SETTRUE:
96 return VECC::CC_AT;
97 }
98 }
99
100 /// getImmVal - get immediate representation of integer value
getImmVal(const ConstantSDNode * N)101 inline static uint64_t getImmVal(const ConstantSDNode *N) {
102 return N->getSExtValue();
103 }
104
105 /// getFpImmVal - get immediate representation of floating point value
getFpImmVal(const ConstantFPSDNode * N)106 inline static uint64_t getFpImmVal(const ConstantFPSDNode *N) {
107 const APInt &Imm = N->getValueAPF().bitcastToAPInt();
108 uint64_t Val = Imm.getZExtValue();
109 if (Imm.getBitWidth() == 32) {
110 // Immediate value of float place places at higher bits on VE.
111 Val <<= 32;
112 }
113 return Val;
114 }
115
116 /// convMImmVal - Convert a mimm integer immediate value to target immediate.
convMImmVal(uint64_t Val)117 inline static uint64_t convMImmVal(uint64_t Val) {
118 if (Val == 0)
119 return 0; // (0)1
120 if (Val & (1UL << 63))
121 return countLeadingOnes(Val); // (m)1
122 return countLeadingZeros(Val) | 0x40; // (m)0
123 }
124
125 //===--------------------------------------------------------------------===//
126 /// VEDAGToDAGISel - VE specific code to select VE machine
127 /// instructions for SelectionDAG operations.
128 ///
129 namespace {
130 class VEDAGToDAGISel : public SelectionDAGISel {
131 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can
132 /// make the right decision when generating code for different targets.
133 const VESubtarget *Subtarget;
134
135 public:
VEDAGToDAGISel(VETargetMachine & tm)136 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}
137
runOnMachineFunction(MachineFunction & MF)138 bool runOnMachineFunction(MachineFunction &MF) override {
139 Subtarget = &MF.getSubtarget<VESubtarget>();
140 return SelectionDAGISel::runOnMachineFunction(MF);
141 }
142
143 void Select(SDNode *N) override;
144
145 // Complex Pattern Selectors.
146 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
147 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
148 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
149 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
150 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
151
getPassName() const152 StringRef getPassName() const override {
153 return "VE DAG->DAG Pattern Instruction Selection";
154 }
155
156 // Include the pieces autogenerated from the target description.
157 #include "VEGenDAGISel.inc"
158
159 private:
160 SDNode *getGlobalBaseReg();
161
162 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);
163 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);
164 };
165 } // end anonymous namespace
166
selectADDRrri(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Offset)167 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,
168 SDValue &Offset) {
169 if (Addr.getOpcode() == ISD::FrameIndex)
170 return false;
171 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
172 Addr.getOpcode() == ISD::TargetGlobalAddress ||
173 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
174 return false; // direct calls.
175
176 SDValue LHS, RHS;
177 if (matchADDRri(Addr, LHS, RHS)) {
178 if (matchADDRrr(LHS, Base, Index)) {
179 Offset = RHS;
180 return true;
181 }
182 // Return false to try selectADDRrii.
183 return false;
184 }
185 if (matchADDRrr(Addr, LHS, RHS)) {
186 if (matchADDRri(RHS, Index, Offset)) {
187 Base = LHS;
188 return true;
189 }
190 if (matchADDRri(LHS, Base, Offset)) {
191 Index = RHS;
192 return true;
193 }
194 Base = LHS;
195 Index = RHS;
196 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
197 return true;
198 }
199 return false; // Let the reg+imm(=0) pattern catch this!
200 }
201
selectADDRrii(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Offset)202 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,
203 SDValue &Offset) {
204 if (matchADDRri(Addr, Base, Offset)) {
205 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
206 return true;
207 }
208
209 Base = Addr;
210 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
211 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
212 return true;
213 }
214
selectADDRzri(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Offset)215 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,
216 SDValue &Offset) {
217 // Prefer ADDRrii.
218 return false;
219 }
220
selectADDRzii(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Offset)221 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,
222 SDValue &Offset) {
223 if (dyn_cast<FrameIndexSDNode>(Addr)) {
224 return false;
225 }
226 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
227 Addr.getOpcode() == ISD::TargetGlobalAddress ||
228 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
229 return false; // direct calls.
230
231 if (ConstantSDNode *CN = cast<ConstantSDNode>(Addr)) {
232 if (isInt<32>(CN->getSExtValue())) {
233 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
234 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
235 Offset =
236 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
237 return true;
238 }
239 }
240 return false;
241 }
242
selectADDRri(SDValue Addr,SDValue & Base,SDValue & Offset)243 bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,
244 SDValue &Offset) {
245 if (matchADDRri(Addr, Base, Offset))
246 return true;
247
248 Base = Addr;
249 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
250 return true;
251 }
252
matchADDRrr(SDValue Addr,SDValue & Base,SDValue & Index)253 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {
254 if (dyn_cast<FrameIndexSDNode>(Addr))
255 return false;
256 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
257 Addr.getOpcode() == ISD::TargetGlobalAddress ||
258 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
259 return false; // direct calls.
260
261 if (Addr.getOpcode() == ISD::ADD) {
262 ; // Nothing to do here.
263 } else if (Addr.getOpcode() == ISD::OR) {
264 // We want to look through a transform in InstCombine and DAGCombiner that
265 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
266 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))
267 return false;
268 } else {
269 return false;
270 }
271
272 if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
273 Addr.getOperand(1).getOpcode() == VEISD::Lo)
274 return false; // Let the LEASL patterns catch this!
275
276 Base = Addr.getOperand(0);
277 Index = Addr.getOperand(1);
278 return true;
279 }
280
matchADDRri(SDValue Addr,SDValue & Base,SDValue & Offset)281 bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {
282 auto AddrTy = Addr->getValueType(0);
283 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
284 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
285 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
286 return true;
287 }
288 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
289 Addr.getOpcode() == ISD::TargetGlobalAddress ||
290 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
291 return false; // direct calls.
292
293 if (CurDAG->isBaseWithConstantOffset(Addr)) {
294 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
295 if (isInt<32>(CN->getSExtValue())) {
296 if (FrameIndexSDNode *FIN =
297 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
298 // Constant offset from frame ref.
299 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
300 } else {
301 Base = Addr.getOperand(0);
302 }
303 Offset =
304 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
305 return true;
306 }
307 }
308 return false;
309 }
310
Select(SDNode * N)311 void VEDAGToDAGISel::Select(SDNode *N) {
312 SDLoc dl(N);
313 if (N->isMachineOpcode()) {
314 N->setNodeId(-1);
315 return; // Already selected.
316 }
317
318 switch (N->getOpcode()) {
319 case VEISD::GLOBAL_BASE_REG:
320 ReplaceNode(N, getGlobalBaseReg());
321 return;
322 }
323
324 SelectCode(N);
325 }
326
getGlobalBaseReg()327 SDNode *VEDAGToDAGISel::getGlobalBaseReg() {
328 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
329 return CurDAG
330 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))
331 .getNode();
332 }
333
334 /// createVEISelDag - This pass converts a legalized DAG into a
335 /// VE-specific DAG, ready for instruction scheduling.
336 ///
createVEISelDag(VETargetMachine & TM)337 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) {
338 return new VEDAGToDAGISel(TM);
339 }
340