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 "VE.h"
14 #include "VETargetMachine.h"
15 #include "llvm/CodeGen/MachineRegisterInfo.h"
16 #include "llvm/CodeGen/SelectionDAGISel.h"
17 #include "llvm/IR/Intrinsics.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/raw_ostream.h"
21 using namespace llvm;
22
23 //===----------------------------------------------------------------------===//
24 // Instruction Selector Implementation
25 //===----------------------------------------------------------------------===//
26
27 /// Convert a DAG integer condition code to a VE ICC condition.
intCondCode2Icc(ISD::CondCode CC)28 inline static VECC::CondCode intCondCode2Icc(ISD::CondCode CC) {
29 switch (CC) {
30 default:
31 llvm_unreachable("Unknown integer condition code!");
32 case ISD::SETEQ:
33 return VECC::CC_IEQ;
34 case ISD::SETNE:
35 return VECC::CC_INE;
36 case ISD::SETLT:
37 return VECC::CC_IL;
38 case ISD::SETGT:
39 return VECC::CC_IG;
40 case ISD::SETLE:
41 return VECC::CC_ILE;
42 case ISD::SETGE:
43 return VECC::CC_IGE;
44 case ISD::SETULT:
45 return VECC::CC_IL;
46 case ISD::SETULE:
47 return VECC::CC_ILE;
48 case ISD::SETUGT:
49 return VECC::CC_IG;
50 case ISD::SETUGE:
51 return VECC::CC_IGE;
52 }
53 }
54
55 /// Convert a DAG floating point condition code to a VE FCC condition.
fpCondCode2Fcc(ISD::CondCode CC)56 inline static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC) {
57 switch (CC) {
58 default:
59 llvm_unreachable("Unknown fp condition code!");
60 case ISD::SETFALSE:
61 return VECC::CC_AF;
62 case ISD::SETEQ:
63 case ISD::SETOEQ:
64 return VECC::CC_EQ;
65 case ISD::SETNE:
66 case ISD::SETONE:
67 return VECC::CC_NE;
68 case ISD::SETLT:
69 case ISD::SETOLT:
70 return VECC::CC_L;
71 case ISD::SETGT:
72 case ISD::SETOGT:
73 return VECC::CC_G;
74 case ISD::SETLE:
75 case ISD::SETOLE:
76 return VECC::CC_LE;
77 case ISD::SETGE:
78 case ISD::SETOGE:
79 return VECC::CC_GE;
80 case ISD::SETO:
81 return VECC::CC_NUM;
82 case ISD::SETUO:
83 return VECC::CC_NAN;
84 case ISD::SETUEQ:
85 return VECC::CC_EQNAN;
86 case ISD::SETUNE:
87 return VECC::CC_NENAN;
88 case ISD::SETULT:
89 return VECC::CC_LNAN;
90 case ISD::SETUGT:
91 return VECC::CC_GNAN;
92 case ISD::SETULE:
93 return VECC::CC_LENAN;
94 case ISD::SETUGE:
95 return VECC::CC_GENAN;
96 case ISD::SETTRUE:
97 return VECC::CC_AT;
98 }
99 }
100
101 /// getImmVal - get immediate representation of integer value
getImmVal(const ConstantSDNode * N)102 inline static uint64_t getImmVal(const ConstantSDNode *N) {
103 return N->getSExtValue();
104 }
105
106 /// getFpImmVal - get immediate representation of floating point value
getFpImmVal(const ConstantFPSDNode * N)107 inline static uint64_t getFpImmVal(const ConstantFPSDNode *N) {
108 const APInt &Imm = N->getValueAPF().bitcastToAPInt();
109 uint64_t Val = Imm.getZExtValue();
110 if (Imm.getBitWidth() == 32) {
111 // Immediate value of float place places at higher bits on VE.
112 Val <<= 32;
113 }
114 return Val;
115 }
116
117 //===--------------------------------------------------------------------===//
118 /// VEDAGToDAGISel - VE specific code to select VE machine
119 /// instructions for SelectionDAG operations.
120 ///
121 namespace {
122 class VEDAGToDAGISel : public SelectionDAGISel {
123 /// Subtarget - Keep a pointer to the VE Subtarget around so that we can
124 /// make the right decision when generating code for different targets.
125 const VESubtarget *Subtarget;
126
127 public:
VEDAGToDAGISel(VETargetMachine & tm)128 explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}
129
runOnMachineFunction(MachineFunction & MF)130 bool runOnMachineFunction(MachineFunction &MF) override {
131 Subtarget = &MF.getSubtarget<VESubtarget>();
132 return SelectionDAGISel::runOnMachineFunction(MF);
133 }
134
135 void Select(SDNode *N) override;
136
137 // Complex Pattern Selectors.
138 bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
139 bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
140 bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
141 bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
142 bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
143 bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset);
144
getPassName() const145 StringRef getPassName() const override {
146 return "VE DAG->DAG Pattern Instruction Selection";
147 }
148
149 // Include the pieces autogenerated from the target description.
150 #include "VEGenDAGISel.inc"
151
152 private:
153 SDNode *getGlobalBaseReg();
154
155 bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);
156 bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);
157 };
158 } // end anonymous namespace
159
selectADDRrri(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Offset)160 bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,
161 SDValue &Offset) {
162 if (Addr.getOpcode() == ISD::FrameIndex)
163 return false;
164 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
165 Addr.getOpcode() == ISD::TargetGlobalAddress ||
166 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
167 return false; // direct calls.
168
169 SDValue LHS, RHS;
170 if (matchADDRri(Addr, LHS, RHS)) {
171 if (matchADDRrr(LHS, Base, Index)) {
172 Offset = RHS;
173 return true;
174 }
175 // Return false to try selectADDRrii.
176 return false;
177 }
178 if (matchADDRrr(Addr, LHS, RHS)) {
179 // If the input is a pair of a frame-index and a register, move a
180 // frame-index to LHS. This generates MI with following operands.
181 // %dest, #FI, %reg, offset
182 // In the eliminateFrameIndex, above MI is converted to the following.
183 // %dest, %fp, %reg, fi_offset + offset
184 if (isa<FrameIndexSDNode>(RHS))
185 std::swap(LHS, RHS);
186
187 if (matchADDRri(RHS, Index, Offset)) {
188 Base = LHS;
189 return true;
190 }
191 if (matchADDRri(LHS, Base, Offset)) {
192 Index = RHS;
193 return true;
194 }
195 Base = LHS;
196 Index = RHS;
197 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
198 return true;
199 }
200 return false; // Let the reg+imm(=0) pattern catch this!
201 }
202
selectADDRrii(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Offset)203 bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,
204 SDValue &Offset) {
205 if (matchADDRri(Addr, Base, Offset)) {
206 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
207 return true;
208 }
209
210 Base = Addr;
211 Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
212 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
213 return true;
214 }
215
selectADDRzri(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Offset)216 bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,
217 SDValue &Offset) {
218 // Prefer ADDRrii.
219 return false;
220 }
221
selectADDRzii(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Offset)222 bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,
223 SDValue &Offset) {
224 if (isa<FrameIndexSDNode>(Addr))
225 return false;
226 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
227 Addr.getOpcode() == ISD::TargetGlobalAddress ||
228 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
229 return false; // direct calls.
230
231 if (auto *CN = dyn_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
selectADDRzi(SDValue Addr,SDValue & Base,SDValue & Offset)253 bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base,
254 SDValue &Offset) {
255 if (isa<FrameIndexSDNode>(Addr))
256 return false;
257 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
258 Addr.getOpcode() == ISD::TargetGlobalAddress ||
259 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
260 return false; // direct calls.
261
262 if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
263 if (isInt<32>(CN->getSExtValue())) {
264 Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
265 Offset =
266 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
267 return true;
268 }
269 }
270 return false;
271 }
272
matchADDRrr(SDValue Addr,SDValue & Base,SDValue & Index)273 bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {
274 if (isa<FrameIndexSDNode>(Addr))
275 return false;
276 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
277 Addr.getOpcode() == ISD::TargetGlobalAddress ||
278 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
279 return false; // direct calls.
280
281 if (Addr.getOpcode() == ISD::ADD) {
282 ; // Nothing to do here.
283 } else if (Addr.getOpcode() == ISD::OR) {
284 // We want to look through a transform in InstCombine and DAGCombiner that
285 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
286 if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))
287 return false;
288 } else {
289 return false;
290 }
291
292 if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
293 Addr.getOperand(1).getOpcode() == VEISD::Lo)
294 return false; // Let the LEASL patterns catch this!
295
296 Base = Addr.getOperand(0);
297 Index = Addr.getOperand(1);
298 return true;
299 }
300
matchADDRri(SDValue Addr,SDValue & Base,SDValue & Offset)301 bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {
302 auto AddrTy = Addr->getValueType(0);
303 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
304 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
305 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
306 return true;
307 }
308 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
309 Addr.getOpcode() == ISD::TargetGlobalAddress ||
310 Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
311 return false; // direct calls.
312
313 if (CurDAG->isBaseWithConstantOffset(Addr)) {
314 ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
315 if (isInt<32>(CN->getSExtValue())) {
316 if (FrameIndexSDNode *FIN =
317 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
318 // Constant offset from frame ref.
319 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
320 } else {
321 Base = Addr.getOperand(0);
322 }
323 Offset =
324 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
325 return true;
326 }
327 }
328 return false;
329 }
330
Select(SDNode * N)331 void VEDAGToDAGISel::Select(SDNode *N) {
332 SDLoc dl(N);
333 if (N->isMachineOpcode()) {
334 N->setNodeId(-1);
335 return; // Already selected.
336 }
337
338 switch (N->getOpcode()) {
339
340 // Late eliminate the LEGALAVL wrapper
341 case VEISD::LEGALAVL:
342 ReplaceNode(N, N->getOperand(0).getNode());
343 return;
344
345 // Lower (broadcast 1) and (broadcast 0) to VM[P]0
346 case VEISD::VEC_BROADCAST: {
347 MVT SplatResTy = N->getSimpleValueType(0);
348 if (SplatResTy.getVectorElementType() != MVT::i1)
349 break;
350
351 // Constant non-zero broadcast.
352 auto BConst = dyn_cast<ConstantSDNode>(N->getOperand(0));
353 if (!BConst)
354 break;
355 bool BCTrueMask = (BConst->getSExtValue() != 0);
356 if (!BCTrueMask)
357 break;
358
359 // Packed or non-packed.
360 SDValue New;
361 if (SplatResTy.getVectorNumElements() == StandardVectorWidth) {
362 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VM0,
363 MVT::v256i1);
364 } else if (SplatResTy.getVectorNumElements() == PackedVectorWidth) {
365 New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VMP0,
366 MVT::v512i1);
367 } else
368 break;
369
370 // Replace.
371 ReplaceNode(N, New.getNode());
372 return;
373 }
374
375 case VEISD::GLOBAL_BASE_REG:
376 ReplaceNode(N, getGlobalBaseReg());
377 return;
378 }
379
380 SelectCode(N);
381 }
382
getGlobalBaseReg()383 SDNode *VEDAGToDAGISel::getGlobalBaseReg() {
384 Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
385 return CurDAG
386 ->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))
387 .getNode();
388 }
389
390 /// createVEISelDag - This pass converts a legalized DAG into a
391 /// VE-specific DAG, ready for instruction scheduling.
392 ///
createVEISelDag(VETargetMachine & TM)393 FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) {
394 return new VEDAGToDAGISel(TM);
395 }
396