File: | llvm/include/llvm/CodeGen/SelectionDAGNodes.h |
Warning: | line 1114, column 10 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- AArch64ISelDAGToDAG.cpp - A dag to dag inst selector for AArch64 --===// | ||||
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 AArch64 target. | ||||
10 | // | ||||
11 | //===----------------------------------------------------------------------===// | ||||
12 | |||||
13 | #include "AArch64MachineFunctionInfo.h" | ||||
14 | #include "AArch64TargetMachine.h" | ||||
15 | #include "MCTargetDesc/AArch64AddressingModes.h" | ||||
16 | #include "llvm/ADT/APSInt.h" | ||||
17 | #include "llvm/CodeGen/SelectionDAGISel.h" | ||||
18 | #include "llvm/IR/Function.h" // To access function attributes. | ||||
19 | #include "llvm/IR/GlobalValue.h" | ||||
20 | #include "llvm/IR/Intrinsics.h" | ||||
21 | #include "llvm/IR/IntrinsicsAArch64.h" | ||||
22 | #include "llvm/Support/Debug.h" | ||||
23 | #include "llvm/Support/ErrorHandling.h" | ||||
24 | #include "llvm/Support/KnownBits.h" | ||||
25 | #include "llvm/Support/MathExtras.h" | ||||
26 | #include "llvm/Support/raw_ostream.h" | ||||
27 | |||||
28 | using namespace llvm; | ||||
29 | |||||
30 | #define DEBUG_TYPE"aarch64-isel" "aarch64-isel" | ||||
31 | |||||
32 | //===--------------------------------------------------------------------===// | ||||
33 | /// AArch64DAGToDAGISel - AArch64 specific code to select AArch64 machine | ||||
34 | /// instructions for SelectionDAG operations. | ||||
35 | /// | ||||
36 | namespace { | ||||
37 | |||||
38 | class AArch64DAGToDAGISel : public SelectionDAGISel { | ||||
39 | |||||
40 | /// Subtarget - Keep a pointer to the AArch64Subtarget around so that we can | ||||
41 | /// make the right decision when generating code for different targets. | ||||
42 | const AArch64Subtarget *Subtarget; | ||||
43 | |||||
44 | public: | ||||
45 | explicit AArch64DAGToDAGISel(AArch64TargetMachine &tm, | ||||
46 | CodeGenOpt::Level OptLevel) | ||||
47 | : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr) {} | ||||
48 | |||||
49 | StringRef getPassName() const override { | ||||
50 | return "AArch64 Instruction Selection"; | ||||
51 | } | ||||
52 | |||||
53 | bool runOnMachineFunction(MachineFunction &MF) override { | ||||
54 | Subtarget = &MF.getSubtarget<AArch64Subtarget>(); | ||||
55 | return SelectionDAGISel::runOnMachineFunction(MF); | ||||
56 | } | ||||
57 | |||||
58 | void Select(SDNode *Node) override; | ||||
59 | |||||
60 | /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for | ||||
61 | /// inline asm expressions. | ||||
62 | bool SelectInlineAsmMemoryOperand(const SDValue &Op, | ||||
63 | unsigned ConstraintID, | ||||
64 | std::vector<SDValue> &OutOps) override; | ||||
65 | |||||
66 | template <signed Low, signed High, signed Scale> | ||||
67 | bool SelectRDVLImm(SDValue N, SDValue &Imm); | ||||
68 | |||||
69 | bool tryMLAV64LaneV128(SDNode *N); | ||||
70 | bool tryMULLV64LaneV128(unsigned IntNo, SDNode *N); | ||||
71 | bool SelectArithExtendedRegister(SDValue N, SDValue &Reg, SDValue &Shift); | ||||
72 | bool SelectArithImmed(SDValue N, SDValue &Val, SDValue &Shift); | ||||
73 | bool SelectNegArithImmed(SDValue N, SDValue &Val, SDValue &Shift); | ||||
74 | bool SelectArithShiftedRegister(SDValue N, SDValue &Reg, SDValue &Shift) { | ||||
75 | return SelectShiftedRegister(N, false, Reg, Shift); | ||||
76 | } | ||||
77 | bool SelectLogicalShiftedRegister(SDValue N, SDValue &Reg, SDValue &Shift) { | ||||
78 | return SelectShiftedRegister(N, true, Reg, Shift); | ||||
79 | } | ||||
80 | bool SelectAddrModeIndexed7S8(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
81 | return SelectAddrModeIndexed7S(N, 1, Base, OffImm); | ||||
82 | } | ||||
83 | bool SelectAddrModeIndexed7S16(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
84 | return SelectAddrModeIndexed7S(N, 2, Base, OffImm); | ||||
85 | } | ||||
86 | bool SelectAddrModeIndexed7S32(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
87 | return SelectAddrModeIndexed7S(N, 4, Base, OffImm); | ||||
88 | } | ||||
89 | bool SelectAddrModeIndexed7S64(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
90 | return SelectAddrModeIndexed7S(N, 8, Base, OffImm); | ||||
91 | } | ||||
92 | bool SelectAddrModeIndexed7S128(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
93 | return SelectAddrModeIndexed7S(N, 16, Base, OffImm); | ||||
94 | } | ||||
95 | bool SelectAddrModeIndexedS9S128(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
96 | return SelectAddrModeIndexedBitWidth(N, true, 9, 16, Base, OffImm); | ||||
97 | } | ||||
98 | bool SelectAddrModeIndexedU6S128(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
99 | return SelectAddrModeIndexedBitWidth(N, false, 6, 16, Base, OffImm); | ||||
100 | } | ||||
101 | bool SelectAddrModeIndexed8(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
102 | return SelectAddrModeIndexed(N, 1, Base, OffImm); | ||||
103 | } | ||||
104 | bool SelectAddrModeIndexed16(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
105 | return SelectAddrModeIndexed(N, 2, Base, OffImm); | ||||
106 | } | ||||
107 | bool SelectAddrModeIndexed32(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
108 | return SelectAddrModeIndexed(N, 4, Base, OffImm); | ||||
109 | } | ||||
110 | bool SelectAddrModeIndexed64(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
111 | return SelectAddrModeIndexed(N, 8, Base, OffImm); | ||||
112 | } | ||||
113 | bool SelectAddrModeIndexed128(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
114 | return SelectAddrModeIndexed(N, 16, Base, OffImm); | ||||
115 | } | ||||
116 | bool SelectAddrModeUnscaled8(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
117 | return SelectAddrModeUnscaled(N, 1, Base, OffImm); | ||||
118 | } | ||||
119 | bool SelectAddrModeUnscaled16(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
120 | return SelectAddrModeUnscaled(N, 2, Base, OffImm); | ||||
121 | } | ||||
122 | bool SelectAddrModeUnscaled32(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
123 | return SelectAddrModeUnscaled(N, 4, Base, OffImm); | ||||
124 | } | ||||
125 | bool SelectAddrModeUnscaled64(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
126 | return SelectAddrModeUnscaled(N, 8, Base, OffImm); | ||||
127 | } | ||||
128 | bool SelectAddrModeUnscaled128(SDValue N, SDValue &Base, SDValue &OffImm) { | ||||
129 | return SelectAddrModeUnscaled(N, 16, Base, OffImm); | ||||
130 | } | ||||
131 | |||||
132 | template<int Width> | ||||
133 | bool SelectAddrModeWRO(SDValue N, SDValue &Base, SDValue &Offset, | ||||
134 | SDValue &SignExtend, SDValue &DoShift) { | ||||
135 | return SelectAddrModeWRO(N, Width / 8, Base, Offset, SignExtend, DoShift); | ||||
136 | } | ||||
137 | |||||
138 | template<int Width> | ||||
139 | bool SelectAddrModeXRO(SDValue N, SDValue &Base, SDValue &Offset, | ||||
140 | SDValue &SignExtend, SDValue &DoShift) { | ||||
141 | return SelectAddrModeXRO(N, Width / 8, Base, Offset, SignExtend, DoShift); | ||||
142 | } | ||||
143 | |||||
144 | bool SelectDupZeroOrUndef(SDValue N) { | ||||
145 | switch(N->getOpcode()) { | ||||
146 | case ISD::UNDEF: | ||||
147 | return true; | ||||
148 | case AArch64ISD::DUP: | ||||
149 | case ISD::SPLAT_VECTOR: { | ||||
150 | auto Opnd0 = N->getOperand(0); | ||||
151 | if (auto CN = dyn_cast<ConstantSDNode>(Opnd0)) | ||||
152 | if (CN->isNullValue()) | ||||
153 | return true; | ||||
154 | if (auto CN = dyn_cast<ConstantFPSDNode>(Opnd0)) | ||||
155 | if (CN->isZero()) | ||||
156 | return true; | ||||
157 | break; | ||||
158 | } | ||||
159 | default: | ||||
160 | break; | ||||
161 | } | ||||
162 | |||||
163 | return false; | ||||
164 | } | ||||
165 | |||||
166 | bool SelectDupZero(SDValue N) { | ||||
167 | switch(N->getOpcode()) { | ||||
168 | case AArch64ISD::DUP: | ||||
169 | case ISD::SPLAT_VECTOR: { | ||||
170 | auto Opnd0 = N->getOperand(0); | ||||
171 | if (auto CN = dyn_cast<ConstantSDNode>(Opnd0)) | ||||
172 | if (CN->isNullValue()) | ||||
173 | return true; | ||||
174 | if (auto CN = dyn_cast<ConstantFPSDNode>(Opnd0)) | ||||
175 | if (CN->isZero()) | ||||
176 | return true; | ||||
177 | break; | ||||
178 | } | ||||
179 | } | ||||
180 | |||||
181 | return false; | ||||
182 | } | ||||
183 | |||||
184 | template<MVT::SimpleValueType VT> | ||||
185 | bool SelectSVEAddSubImm(SDValue N, SDValue &Imm, SDValue &Shift) { | ||||
186 | return SelectSVEAddSubImm(N, VT, Imm, Shift); | ||||
187 | } | ||||
188 | |||||
189 | template<MVT::SimpleValueType VT> | ||||
190 | bool SelectSVELogicalImm(SDValue N, SDValue &Imm) { | ||||
191 | return SelectSVELogicalImm(N, VT, Imm); | ||||
192 | } | ||||
193 | |||||
194 | template <MVT::SimpleValueType VT> | ||||
195 | bool SelectSVEArithImm(SDValue N, SDValue &Imm) { | ||||
196 | return SelectSVEArithImm(N, VT, Imm); | ||||
197 | } | ||||
198 | |||||
199 | template <unsigned Low, unsigned High, bool AllowSaturation = false> | ||||
200 | bool SelectSVEShiftImm(SDValue N, SDValue &Imm) { | ||||
201 | return SelectSVEShiftImm(N, Low, High, AllowSaturation, Imm); | ||||
202 | } | ||||
203 | |||||
204 | // Returns a suitable CNT/INC/DEC/RDVL multiplier to calculate VSCALE*N. | ||||
205 | template<signed Min, signed Max, signed Scale, bool Shift> | ||||
206 | bool SelectCntImm(SDValue N, SDValue &Imm) { | ||||
207 | if (!isa<ConstantSDNode>(N)) | ||||
208 | return false; | ||||
209 | |||||
210 | int64_t MulImm = cast<ConstantSDNode>(N)->getSExtValue(); | ||||
211 | if (Shift) | ||||
212 | MulImm = 1LL << MulImm; | ||||
213 | |||||
214 | if ((MulImm % std::abs(Scale)) != 0) | ||||
215 | return false; | ||||
216 | |||||
217 | MulImm /= Scale; | ||||
218 | if ((MulImm >= Min) && (MulImm <= Max)) { | ||||
219 | Imm = CurDAG->getTargetConstant(MulImm, SDLoc(N), MVT::i32); | ||||
220 | return true; | ||||
221 | } | ||||
222 | |||||
223 | return false; | ||||
224 | } | ||||
225 | |||||
226 | /// Form sequences of consecutive 64/128-bit registers for use in NEON | ||||
227 | /// instructions making use of a vector-list (e.g. ldN, tbl). Vecs must have | ||||
228 | /// between 1 and 4 elements. If it contains a single element that is returned | ||||
229 | /// unchanged; otherwise a REG_SEQUENCE value is returned. | ||||
230 | SDValue createDTuple(ArrayRef<SDValue> Vecs); | ||||
231 | SDValue createQTuple(ArrayRef<SDValue> Vecs); | ||||
232 | // Form a sequence of SVE registers for instructions using list of vectors, | ||||
233 | // e.g. structured loads and stores (ldN, stN). | ||||
234 | SDValue createZTuple(ArrayRef<SDValue> Vecs); | ||||
235 | |||||
236 | /// Generic helper for the createDTuple/createQTuple | ||||
237 | /// functions. Those should almost always be called instead. | ||||
238 | SDValue createTuple(ArrayRef<SDValue> Vecs, const unsigned RegClassIDs[], | ||||
239 | const unsigned SubRegs[]); | ||||
240 | |||||
241 | void SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc, bool isExt); | ||||
242 | |||||
243 | bool tryIndexedLoad(SDNode *N); | ||||
244 | |||||
245 | bool trySelectStackSlotTagP(SDNode *N); | ||||
246 | void SelectTagP(SDNode *N); | ||||
247 | |||||
248 | void SelectLoad(SDNode *N, unsigned NumVecs, unsigned Opc, | ||||
249 | unsigned SubRegIdx); | ||||
250 | void SelectPostLoad(SDNode *N, unsigned NumVecs, unsigned Opc, | ||||
251 | unsigned SubRegIdx); | ||||
252 | void SelectLoadLane(SDNode *N, unsigned NumVecs, unsigned Opc); | ||||
253 | void SelectPostLoadLane(SDNode *N, unsigned NumVecs, unsigned Opc); | ||||
254 | void SelectPredicatedLoad(SDNode *N, unsigned NumVecs, unsigned Scale, | ||||
255 | unsigned Opc_rr, unsigned Opc_ri); | ||||
256 | |||||
257 | bool SelectAddrModeFrameIndexSVE(SDValue N, SDValue &Base, SDValue &OffImm); | ||||
258 | /// SVE Reg+Imm addressing mode. | ||||
259 | template <int64_t Min, int64_t Max> | ||||
260 | bool SelectAddrModeIndexedSVE(SDNode *Root, SDValue N, SDValue &Base, | ||||
261 | SDValue &OffImm); | ||||
262 | /// SVE Reg+Reg address mode. | ||||
263 | template <unsigned Scale> | ||||
264 | bool SelectSVERegRegAddrMode(SDValue N, SDValue &Base, SDValue &Offset) { | ||||
265 | return SelectSVERegRegAddrMode(N, Scale, Base, Offset); | ||||
266 | } | ||||
267 | |||||
268 | void SelectStore(SDNode *N, unsigned NumVecs, unsigned Opc); | ||||
269 | void SelectPostStore(SDNode *N, unsigned NumVecs, unsigned Opc); | ||||
270 | void SelectStoreLane(SDNode *N, unsigned NumVecs, unsigned Opc); | ||||
271 | void SelectPostStoreLane(SDNode *N, unsigned NumVecs, unsigned Opc); | ||||
272 | void SelectPredicatedStore(SDNode *N, unsigned NumVecs, unsigned Scale, | ||||
273 | unsigned Opc_rr, unsigned Opc_ri); | ||||
274 | std::tuple<unsigned, SDValue, SDValue> | ||||
275 | findAddrModeSVELoadStore(SDNode *N, unsigned Opc_rr, unsigned Opc_ri, | ||||
276 | const SDValue &OldBase, const SDValue &OldOffset, | ||||
277 | unsigned Scale); | ||||
278 | |||||
279 | bool tryBitfieldExtractOp(SDNode *N); | ||||
280 | bool tryBitfieldExtractOpFromSExt(SDNode *N); | ||||
281 | bool tryBitfieldInsertOp(SDNode *N); | ||||
282 | bool tryBitfieldInsertInZeroOp(SDNode *N); | ||||
283 | bool tryShiftAmountMod(SDNode *N); | ||||
284 | bool tryHighFPExt(SDNode *N); | ||||
285 | |||||
286 | bool tryReadRegister(SDNode *N); | ||||
287 | bool tryWriteRegister(SDNode *N); | ||||
288 | |||||
289 | // Include the pieces autogenerated from the target description. | ||||
290 | #include "AArch64GenDAGISel.inc" | ||||
291 | |||||
292 | private: | ||||
293 | bool SelectShiftedRegister(SDValue N, bool AllowROR, SDValue &Reg, | ||||
294 | SDValue &Shift); | ||||
295 | bool SelectAddrModeIndexed7S(SDValue N, unsigned Size, SDValue &Base, | ||||
296 | SDValue &OffImm) { | ||||
297 | return SelectAddrModeIndexedBitWidth(N, true, 7, Size, Base, OffImm); | ||||
298 | } | ||||
299 | bool SelectAddrModeIndexedBitWidth(SDValue N, bool IsSignedImm, unsigned BW, | ||||
300 | unsigned Size, SDValue &Base, | ||||
301 | SDValue &OffImm); | ||||
302 | bool SelectAddrModeIndexed(SDValue N, unsigned Size, SDValue &Base, | ||||
303 | SDValue &OffImm); | ||||
304 | bool SelectAddrModeUnscaled(SDValue N, unsigned Size, SDValue &Base, | ||||
305 | SDValue &OffImm); | ||||
306 | bool SelectAddrModeWRO(SDValue N, unsigned Size, SDValue &Base, | ||||
307 | SDValue &Offset, SDValue &SignExtend, | ||||
308 | SDValue &DoShift); | ||||
309 | bool SelectAddrModeXRO(SDValue N, unsigned Size, SDValue &Base, | ||||
310 | SDValue &Offset, SDValue &SignExtend, | ||||
311 | SDValue &DoShift); | ||||
312 | bool isWorthFolding(SDValue V) const; | ||||
313 | bool SelectExtendedSHL(SDValue N, unsigned Size, bool WantExtend, | ||||
314 | SDValue &Offset, SDValue &SignExtend); | ||||
315 | |||||
316 | template<unsigned RegWidth> | ||||
317 | bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos) { | ||||
318 | return SelectCVTFixedPosOperand(N, FixedPos, RegWidth); | ||||
319 | } | ||||
320 | |||||
321 | bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos, unsigned Width); | ||||
322 | |||||
323 | bool SelectCMP_SWAP(SDNode *N); | ||||
324 | |||||
325 | bool SelectSVE8BitLslImm(SDValue N, SDValue &Imm, SDValue &Shift); | ||||
326 | |||||
327 | bool SelectSVEAddSubImm(SDValue N, MVT VT, SDValue &Imm, SDValue &Shift); | ||||
328 | |||||
329 | bool SelectSVELogicalImm(SDValue N, MVT VT, SDValue &Imm); | ||||
330 | |||||
331 | bool SelectSVESignedArithImm(SDValue N, SDValue &Imm); | ||||
332 | bool SelectSVEShiftImm(SDValue N, uint64_t Low, uint64_t High, | ||||
333 | bool AllowSaturation, SDValue &Imm); | ||||
334 | |||||
335 | bool SelectSVEArithImm(SDValue N, MVT VT, SDValue &Imm); | ||||
336 | bool SelectSVERegRegAddrMode(SDValue N, unsigned Scale, SDValue &Base, | ||||
337 | SDValue &Offset); | ||||
338 | }; | ||||
339 | } // end anonymous namespace | ||||
340 | |||||
341 | /// isIntImmediate - This method tests to see if the node is a constant | ||||
342 | /// operand. If so Imm will receive the 32-bit value. | ||||
343 | static bool isIntImmediate(const SDNode *N, uint64_t &Imm) { | ||||
344 | if (const ConstantSDNode *C = dyn_cast<const ConstantSDNode>(N)) { | ||||
345 | Imm = C->getZExtValue(); | ||||
346 | return true; | ||||
347 | } | ||||
348 | return false; | ||||
349 | } | ||||
350 | |||||
351 | // isIntImmediate - This method tests to see if a constant operand. | ||||
352 | // If so Imm will receive the value. | ||||
353 | static bool isIntImmediate(SDValue N, uint64_t &Imm) { | ||||
354 | return isIntImmediate(N.getNode(), Imm); | ||||
355 | } | ||||
356 | |||||
357 | // isOpcWithIntImmediate - This method tests to see if the node is a specific | ||||
358 | // opcode and that it has a immediate integer right operand. | ||||
359 | // If so Imm will receive the 32 bit value. | ||||
360 | static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, | ||||
361 | uint64_t &Imm) { | ||||
362 | return N->getOpcode() == Opc && | ||||
363 | isIntImmediate(N->getOperand(1).getNode(), Imm); | ||||
364 | } | ||||
365 | |||||
366 | bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand( | ||||
367 | const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { | ||||
368 | switch(ConstraintID) { | ||||
369 | default: | ||||
370 | llvm_unreachable("Unexpected asm memory constraint")::llvm::llvm_unreachable_internal("Unexpected asm memory constraint" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 370); | ||||
371 | case InlineAsm::Constraint_m: | ||||
372 | case InlineAsm::Constraint_Q: | ||||
373 | // We need to make sure that this one operand does not end up in XZR, thus | ||||
374 | // require the address to be in a PointerRegClass register. | ||||
375 | const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); | ||||
376 | const TargetRegisterClass *TRC = TRI->getPointerRegClass(*MF); | ||||
377 | SDLoc dl(Op); | ||||
378 | SDValue RC = CurDAG->getTargetConstant(TRC->getID(), dl, MVT::i64); | ||||
379 | SDValue NewOp = | ||||
380 | SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, | ||||
381 | dl, Op.getValueType(), | ||||
382 | Op, RC), 0); | ||||
383 | OutOps.push_back(NewOp); | ||||
384 | return false; | ||||
385 | } | ||||
386 | return true; | ||||
387 | } | ||||
388 | |||||
389 | /// SelectArithImmed - Select an immediate value that can be represented as | ||||
390 | /// a 12-bit value shifted left by either 0 or 12. If so, return true with | ||||
391 | /// Val set to the 12-bit value and Shift set to the shifter operand. | ||||
392 | bool AArch64DAGToDAGISel::SelectArithImmed(SDValue N, SDValue &Val, | ||||
393 | SDValue &Shift) { | ||||
394 | // This function is called from the addsub_shifted_imm ComplexPattern, | ||||
395 | // which lists [imm] as the list of opcode it's interested in, however | ||||
396 | // we still need to check whether the operand is actually an immediate | ||||
397 | // here because the ComplexPattern opcode list is only used in | ||||
398 | // root-level opcode matching. | ||||
399 | if (!isa<ConstantSDNode>(N.getNode())) | ||||
400 | return false; | ||||
401 | |||||
402 | uint64_t Immed = cast<ConstantSDNode>(N.getNode())->getZExtValue(); | ||||
403 | unsigned ShiftAmt; | ||||
404 | |||||
405 | if (Immed >> 12 == 0) { | ||||
406 | ShiftAmt = 0; | ||||
407 | } else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) { | ||||
408 | ShiftAmt = 12; | ||||
409 | Immed = Immed >> 12; | ||||
410 | } else | ||||
411 | return false; | ||||
412 | |||||
413 | unsigned ShVal = AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt); | ||||
414 | SDLoc dl(N); | ||||
415 | Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32); | ||||
416 | Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32); | ||||
417 | return true; | ||||
418 | } | ||||
419 | |||||
420 | /// SelectNegArithImmed - As above, but negates the value before trying to | ||||
421 | /// select it. | ||||
422 | bool AArch64DAGToDAGISel::SelectNegArithImmed(SDValue N, SDValue &Val, | ||||
423 | SDValue &Shift) { | ||||
424 | // This function is called from the addsub_shifted_imm ComplexPattern, | ||||
425 | // which lists [imm] as the list of opcode it's interested in, however | ||||
426 | // we still need to check whether the operand is actually an immediate | ||||
427 | // here because the ComplexPattern opcode list is only used in | ||||
428 | // root-level opcode matching. | ||||
429 | if (!isa<ConstantSDNode>(N.getNode())) | ||||
430 | return false; | ||||
431 | |||||
432 | // The immediate operand must be a 24-bit zero-extended immediate. | ||||
433 | uint64_t Immed = cast<ConstantSDNode>(N.getNode())->getZExtValue(); | ||||
434 | |||||
435 | // This negation is almost always valid, but "cmp wN, #0" and "cmn wN, #0" | ||||
436 | // have the opposite effect on the C flag, so this pattern mustn't match under | ||||
437 | // those circumstances. | ||||
438 | if (Immed == 0) | ||||
439 | return false; | ||||
440 | |||||
441 | if (N.getValueType() == MVT::i32) | ||||
442 | Immed = ~((uint32_t)Immed) + 1; | ||||
443 | else | ||||
444 | Immed = ~Immed + 1ULL; | ||||
445 | if (Immed & 0xFFFFFFFFFF000000ULL) | ||||
446 | return false; | ||||
447 | |||||
448 | Immed &= 0xFFFFFFULL; | ||||
449 | return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(N), MVT::i32), Val, | ||||
450 | Shift); | ||||
451 | } | ||||
452 | |||||
453 | /// getShiftTypeForNode - Translate a shift node to the corresponding | ||||
454 | /// ShiftType value. | ||||
455 | static AArch64_AM::ShiftExtendType getShiftTypeForNode(SDValue N) { | ||||
456 | switch (N.getOpcode()) { | ||||
457 | default: | ||||
458 | return AArch64_AM::InvalidShiftExtend; | ||||
459 | case ISD::SHL: | ||||
460 | return AArch64_AM::LSL; | ||||
461 | case ISD::SRL: | ||||
462 | return AArch64_AM::LSR; | ||||
463 | case ISD::SRA: | ||||
464 | return AArch64_AM::ASR; | ||||
465 | case ISD::ROTR: | ||||
466 | return AArch64_AM::ROR; | ||||
467 | } | ||||
468 | } | ||||
469 | |||||
470 | /// Determine whether it is worth it to fold SHL into the addressing | ||||
471 | /// mode. | ||||
472 | static bool isWorthFoldingSHL(SDValue V) { | ||||
473 | assert(V.getOpcode() == ISD::SHL && "invalid opcode")((V.getOpcode() == ISD::SHL && "invalid opcode") ? static_cast <void> (0) : __assert_fail ("V.getOpcode() == ISD::SHL && \"invalid opcode\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 473, __PRETTY_FUNCTION__)); | ||||
474 | // It is worth folding logical shift of up to three places. | ||||
475 | auto *CSD = dyn_cast<ConstantSDNode>(V.getOperand(1)); | ||||
476 | if (!CSD) | ||||
477 | return false; | ||||
478 | unsigned ShiftVal = CSD->getZExtValue(); | ||||
479 | if (ShiftVal > 3) | ||||
480 | return false; | ||||
481 | |||||
482 | // Check if this particular node is reused in any non-memory related | ||||
483 | // operation. If yes, do not try to fold this node into the address | ||||
484 | // computation, since the computation will be kept. | ||||
485 | const SDNode *Node = V.getNode(); | ||||
486 | for (SDNode *UI : Node->uses()) | ||||
487 | if (!isa<MemSDNode>(*UI)) | ||||
488 | for (SDNode *UII : UI->uses()) | ||||
489 | if (!isa<MemSDNode>(*UII)) | ||||
490 | return false; | ||||
491 | return true; | ||||
492 | } | ||||
493 | |||||
494 | /// Determine whether it is worth to fold V into an extended register. | ||||
495 | bool AArch64DAGToDAGISel::isWorthFolding(SDValue V) const { | ||||
496 | // Trivial if we are optimizing for code size or if there is only | ||||
497 | // one use of the value. | ||||
498 | if (CurDAG->shouldOptForSize() || V.hasOneUse()) | ||||
499 | return true; | ||||
500 | // If a subtarget has a fastpath LSL we can fold a logical shift into | ||||
501 | // the addressing mode and save a cycle. | ||||
502 | if (Subtarget->hasLSLFast() && V.getOpcode() == ISD::SHL && | ||||
503 | isWorthFoldingSHL(V)) | ||||
504 | return true; | ||||
505 | if (Subtarget->hasLSLFast() && V.getOpcode() == ISD::ADD) { | ||||
506 | const SDValue LHS = V.getOperand(0); | ||||
507 | const SDValue RHS = V.getOperand(1); | ||||
508 | if (LHS.getOpcode() == ISD::SHL && isWorthFoldingSHL(LHS)) | ||||
509 | return true; | ||||
510 | if (RHS.getOpcode() == ISD::SHL && isWorthFoldingSHL(RHS)) | ||||
511 | return true; | ||||
512 | } | ||||
513 | |||||
514 | // It hurts otherwise, since the value will be reused. | ||||
515 | return false; | ||||
516 | } | ||||
517 | |||||
518 | /// SelectShiftedRegister - Select a "shifted register" operand. If the value | ||||
519 | /// is not shifted, set the Shift operand to default of "LSL 0". The logical | ||||
520 | /// instructions allow the shifted register to be rotated, but the arithmetic | ||||
521 | /// instructions do not. The AllowROR parameter specifies whether ROR is | ||||
522 | /// supported. | ||||
523 | bool AArch64DAGToDAGISel::SelectShiftedRegister(SDValue N, bool AllowROR, | ||||
524 | SDValue &Reg, SDValue &Shift) { | ||||
525 | AArch64_AM::ShiftExtendType ShType = getShiftTypeForNode(N); | ||||
526 | if (ShType == AArch64_AM::InvalidShiftExtend) | ||||
527 | return false; | ||||
528 | if (!AllowROR && ShType == AArch64_AM::ROR) | ||||
529 | return false; | ||||
530 | |||||
531 | if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { | ||||
532 | unsigned BitSize = N.getValueSizeInBits(); | ||||
533 | unsigned Val = RHS->getZExtValue() & (BitSize - 1); | ||||
534 | unsigned ShVal = AArch64_AM::getShifterImm(ShType, Val); | ||||
535 | |||||
536 | Reg = N.getOperand(0); | ||||
537 | Shift = CurDAG->getTargetConstant(ShVal, SDLoc(N), MVT::i32); | ||||
538 | return isWorthFolding(N); | ||||
539 | } | ||||
540 | |||||
541 | return false; | ||||
542 | } | ||||
543 | |||||
544 | /// getExtendTypeForNode - Translate an extend node to the corresponding | ||||
545 | /// ExtendType value. | ||||
546 | static AArch64_AM::ShiftExtendType | ||||
547 | getExtendTypeForNode(SDValue N, bool IsLoadStore = false) { | ||||
548 | if (N.getOpcode() == ISD::SIGN_EXTEND || | ||||
549 | N.getOpcode() == ISD::SIGN_EXTEND_INREG) { | ||||
550 | EVT SrcVT; | ||||
551 | if (N.getOpcode() == ISD::SIGN_EXTEND_INREG) | ||||
552 | SrcVT = cast<VTSDNode>(N.getOperand(1))->getVT(); | ||||
553 | else | ||||
554 | SrcVT = N.getOperand(0).getValueType(); | ||||
555 | |||||
556 | if (!IsLoadStore && SrcVT == MVT::i8) | ||||
557 | return AArch64_AM::SXTB; | ||||
558 | else if (!IsLoadStore && SrcVT == MVT::i16) | ||||
559 | return AArch64_AM::SXTH; | ||||
560 | else if (SrcVT == MVT::i32) | ||||
561 | return AArch64_AM::SXTW; | ||||
562 | assert(SrcVT != MVT::i64 && "extend from 64-bits?")((SrcVT != MVT::i64 && "extend from 64-bits?") ? static_cast <void> (0) : __assert_fail ("SrcVT != MVT::i64 && \"extend from 64-bits?\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 562, __PRETTY_FUNCTION__)); | ||||
563 | |||||
564 | return AArch64_AM::InvalidShiftExtend; | ||||
565 | } else if (N.getOpcode() == ISD::ZERO_EXTEND || | ||||
566 | N.getOpcode() == ISD::ANY_EXTEND) { | ||||
567 | EVT SrcVT = N.getOperand(0).getValueType(); | ||||
568 | if (!IsLoadStore && SrcVT == MVT::i8) | ||||
569 | return AArch64_AM::UXTB; | ||||
570 | else if (!IsLoadStore && SrcVT == MVT::i16) | ||||
571 | return AArch64_AM::UXTH; | ||||
572 | else if (SrcVT == MVT::i32) | ||||
573 | return AArch64_AM::UXTW; | ||||
574 | assert(SrcVT != MVT::i64 && "extend from 64-bits?")((SrcVT != MVT::i64 && "extend from 64-bits?") ? static_cast <void> (0) : __assert_fail ("SrcVT != MVT::i64 && \"extend from 64-bits?\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 574, __PRETTY_FUNCTION__)); | ||||
575 | |||||
576 | return AArch64_AM::InvalidShiftExtend; | ||||
577 | } else if (N.getOpcode() == ISD::AND) { | ||||
578 | ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1)); | ||||
579 | if (!CSD) | ||||
580 | return AArch64_AM::InvalidShiftExtend; | ||||
581 | uint64_t AndMask = CSD->getZExtValue(); | ||||
582 | |||||
583 | switch (AndMask) { | ||||
584 | default: | ||||
585 | return AArch64_AM::InvalidShiftExtend; | ||||
586 | case 0xFF: | ||||
587 | return !IsLoadStore ? AArch64_AM::UXTB : AArch64_AM::InvalidShiftExtend; | ||||
588 | case 0xFFFF: | ||||
589 | return !IsLoadStore ? AArch64_AM::UXTH : AArch64_AM::InvalidShiftExtend; | ||||
590 | case 0xFFFFFFFF: | ||||
591 | return AArch64_AM::UXTW; | ||||
592 | } | ||||
593 | } | ||||
594 | |||||
595 | return AArch64_AM::InvalidShiftExtend; | ||||
596 | } | ||||
597 | |||||
598 | // Helper for SelectMLAV64LaneV128 - Recognize high lane extracts. | ||||
599 | static bool checkHighLaneIndex(SDNode *DL, SDValue &LaneOp, int &LaneIdx) { | ||||
600 | if (DL->getOpcode() != AArch64ISD::DUPLANE16 && | ||||
601 | DL->getOpcode() != AArch64ISD::DUPLANE32) | ||||
602 | return false; | ||||
603 | |||||
604 | SDValue SV = DL->getOperand(0); | ||||
605 | if (SV.getOpcode() != ISD::INSERT_SUBVECTOR) | ||||
606 | return false; | ||||
607 | |||||
608 | SDValue EV = SV.getOperand(1); | ||||
609 | if (EV.getOpcode() != ISD::EXTRACT_SUBVECTOR) | ||||
610 | return false; | ||||
611 | |||||
612 | ConstantSDNode *DLidx = cast<ConstantSDNode>(DL->getOperand(1).getNode()); | ||||
613 | ConstantSDNode *EVidx = cast<ConstantSDNode>(EV.getOperand(1).getNode()); | ||||
614 | LaneIdx = DLidx->getSExtValue() + EVidx->getSExtValue(); | ||||
615 | LaneOp = EV.getOperand(0); | ||||
616 | |||||
617 | return true; | ||||
618 | } | ||||
619 | |||||
620 | // Helper for SelectOpcV64LaneV128 - Recognize operations where one operand is a | ||||
621 | // high lane extract. | ||||
622 | static bool checkV64LaneV128(SDValue Op0, SDValue Op1, SDValue &StdOp, | ||||
623 | SDValue &LaneOp, int &LaneIdx) { | ||||
624 | |||||
625 | if (!checkHighLaneIndex(Op0.getNode(), LaneOp, LaneIdx)) { | ||||
626 | std::swap(Op0, Op1); | ||||
627 | if (!checkHighLaneIndex(Op0.getNode(), LaneOp, LaneIdx)) | ||||
628 | return false; | ||||
629 | } | ||||
630 | StdOp = Op1; | ||||
631 | return true; | ||||
632 | } | ||||
633 | |||||
634 | /// SelectMLAV64LaneV128 - AArch64 supports vector MLAs where one multiplicand | ||||
635 | /// is a lane in the upper half of a 128-bit vector. Recognize and select this | ||||
636 | /// so that we don't emit unnecessary lane extracts. | ||||
637 | bool AArch64DAGToDAGISel::tryMLAV64LaneV128(SDNode *N) { | ||||
638 | SDLoc dl(N); | ||||
639 | SDValue Op0 = N->getOperand(0); | ||||
640 | SDValue Op1 = N->getOperand(1); | ||||
641 | SDValue MLAOp1; // Will hold ordinary multiplicand for MLA. | ||||
642 | SDValue MLAOp2; // Will hold lane-accessed multiplicand for MLA. | ||||
643 | int LaneIdx = -1; // Will hold the lane index. | ||||
644 | |||||
645 | if (Op1.getOpcode() != ISD::MUL || | ||||
646 | !checkV64LaneV128(Op1.getOperand(0), Op1.getOperand(1), MLAOp1, MLAOp2, | ||||
647 | LaneIdx)) { | ||||
648 | std::swap(Op0, Op1); | ||||
649 | if (Op1.getOpcode() != ISD::MUL || | ||||
650 | !checkV64LaneV128(Op1.getOperand(0), Op1.getOperand(1), MLAOp1, MLAOp2, | ||||
651 | LaneIdx)) | ||||
652 | return false; | ||||
653 | } | ||||
654 | |||||
655 | SDValue LaneIdxVal = CurDAG->getTargetConstant(LaneIdx, dl, MVT::i64); | ||||
656 | |||||
657 | SDValue Ops[] = { Op0, MLAOp1, MLAOp2, LaneIdxVal }; | ||||
658 | |||||
659 | unsigned MLAOpc = ~0U; | ||||
660 | |||||
661 | switch (N->getSimpleValueType(0).SimpleTy) { | ||||
662 | default: | ||||
663 | llvm_unreachable("Unrecognized MLA.")::llvm::llvm_unreachable_internal("Unrecognized MLA.", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 663); | ||||
664 | case MVT::v4i16: | ||||
665 | MLAOpc = AArch64::MLAv4i16_indexed; | ||||
666 | break; | ||||
667 | case MVT::v8i16: | ||||
668 | MLAOpc = AArch64::MLAv8i16_indexed; | ||||
669 | break; | ||||
670 | case MVT::v2i32: | ||||
671 | MLAOpc = AArch64::MLAv2i32_indexed; | ||||
672 | break; | ||||
673 | case MVT::v4i32: | ||||
674 | MLAOpc = AArch64::MLAv4i32_indexed; | ||||
675 | break; | ||||
676 | } | ||||
677 | |||||
678 | ReplaceNode(N, CurDAG->getMachineNode(MLAOpc, dl, N->getValueType(0), Ops)); | ||||
679 | return true; | ||||
680 | } | ||||
681 | |||||
682 | bool AArch64DAGToDAGISel::tryMULLV64LaneV128(unsigned IntNo, SDNode *N) { | ||||
683 | SDLoc dl(N); | ||||
684 | SDValue SMULLOp0; | ||||
685 | SDValue SMULLOp1; | ||||
686 | int LaneIdx; | ||||
687 | |||||
688 | if (!checkV64LaneV128(N->getOperand(1), N->getOperand(2), SMULLOp0, SMULLOp1, | ||||
689 | LaneIdx)) | ||||
690 | return false; | ||||
691 | |||||
692 | SDValue LaneIdxVal = CurDAG->getTargetConstant(LaneIdx, dl, MVT::i64); | ||||
693 | |||||
694 | SDValue Ops[] = { SMULLOp0, SMULLOp1, LaneIdxVal }; | ||||
695 | |||||
696 | unsigned SMULLOpc = ~0U; | ||||
697 | |||||
698 | if (IntNo == Intrinsic::aarch64_neon_smull) { | ||||
699 | switch (N->getSimpleValueType(0).SimpleTy) { | ||||
700 | default: | ||||
701 | llvm_unreachable("Unrecognized SMULL.")::llvm::llvm_unreachable_internal("Unrecognized SMULL.", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 701); | ||||
702 | case MVT::v4i32: | ||||
703 | SMULLOpc = AArch64::SMULLv4i16_indexed; | ||||
704 | break; | ||||
705 | case MVT::v2i64: | ||||
706 | SMULLOpc = AArch64::SMULLv2i32_indexed; | ||||
707 | break; | ||||
708 | } | ||||
709 | } else if (IntNo == Intrinsic::aarch64_neon_umull) { | ||||
710 | switch (N->getSimpleValueType(0).SimpleTy) { | ||||
711 | default: | ||||
712 | llvm_unreachable("Unrecognized SMULL.")::llvm::llvm_unreachable_internal("Unrecognized SMULL.", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 712); | ||||
713 | case MVT::v4i32: | ||||
714 | SMULLOpc = AArch64::UMULLv4i16_indexed; | ||||
715 | break; | ||||
716 | case MVT::v2i64: | ||||
717 | SMULLOpc = AArch64::UMULLv2i32_indexed; | ||||
718 | break; | ||||
719 | } | ||||
720 | } else | ||||
721 | llvm_unreachable("Unrecognized intrinsic.")::llvm::llvm_unreachable_internal("Unrecognized intrinsic.", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 721); | ||||
722 | |||||
723 | ReplaceNode(N, CurDAG->getMachineNode(SMULLOpc, dl, N->getValueType(0), Ops)); | ||||
724 | return true; | ||||
725 | } | ||||
726 | |||||
727 | /// Instructions that accept extend modifiers like UXTW expect the register | ||||
728 | /// being extended to be a GPR32, but the incoming DAG might be acting on a | ||||
729 | /// GPR64 (either via SEXT_INREG or AND). Extract the appropriate low bits if | ||||
730 | /// this is the case. | ||||
731 | static SDValue narrowIfNeeded(SelectionDAG *CurDAG, SDValue N) { | ||||
732 | if (N.getValueType() == MVT::i32) | ||||
733 | return N; | ||||
734 | |||||
735 | SDLoc dl(N); | ||||
736 | SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32); | ||||
737 | MachineSDNode *Node = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, | ||||
738 | dl, MVT::i32, N, SubReg); | ||||
739 | return SDValue(Node, 0); | ||||
740 | } | ||||
741 | |||||
742 | // Returns a suitable CNT/INC/DEC/RDVL multiplier to calculate VSCALE*N. | ||||
743 | template<signed Low, signed High, signed Scale> | ||||
744 | bool AArch64DAGToDAGISel::SelectRDVLImm(SDValue N, SDValue &Imm) { | ||||
745 | if (!isa<ConstantSDNode>(N)) | ||||
746 | return false; | ||||
747 | |||||
748 | int64_t MulImm = cast<ConstantSDNode>(N)->getSExtValue(); | ||||
749 | if ((MulImm % std::abs(Scale)) == 0) { | ||||
750 | int64_t RDVLImm = MulImm / Scale; | ||||
751 | if ((RDVLImm >= Low) && (RDVLImm <= High)) { | ||||
752 | Imm = CurDAG->getTargetConstant(RDVLImm, SDLoc(N), MVT::i32); | ||||
753 | return true; | ||||
754 | } | ||||
755 | } | ||||
756 | |||||
757 | return false; | ||||
758 | } | ||||
759 | |||||
760 | /// SelectArithExtendedRegister - Select a "extended register" operand. This | ||||
761 | /// operand folds in an extend followed by an optional left shift. | ||||
762 | bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue N, SDValue &Reg, | ||||
763 | SDValue &Shift) { | ||||
764 | unsigned ShiftVal = 0; | ||||
765 | AArch64_AM::ShiftExtendType Ext; | ||||
766 | |||||
767 | if (N.getOpcode() == ISD::SHL) { | ||||
768 | ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1)); | ||||
769 | if (!CSD) | ||||
770 | return false; | ||||
771 | ShiftVal = CSD->getZExtValue(); | ||||
772 | if (ShiftVal > 4) | ||||
773 | return false; | ||||
774 | |||||
775 | Ext = getExtendTypeForNode(N.getOperand(0)); | ||||
776 | if (Ext == AArch64_AM::InvalidShiftExtend) | ||||
777 | return false; | ||||
778 | |||||
779 | Reg = N.getOperand(0).getOperand(0); | ||||
780 | } else { | ||||
781 | Ext = getExtendTypeForNode(N); | ||||
782 | if (Ext == AArch64_AM::InvalidShiftExtend) | ||||
783 | return false; | ||||
784 | |||||
785 | Reg = N.getOperand(0); | ||||
786 | |||||
787 | // Don't match if free 32-bit -> 64-bit zext can be used instead. | ||||
788 | if (Ext == AArch64_AM::UXTW && | ||||
789 | Reg->getValueType(0).getSizeInBits() == 32 && isDef32(*Reg.getNode())) | ||||
790 | return false; | ||||
791 | } | ||||
792 | |||||
793 | // AArch64 mandates that the RHS of the operation must use the smallest | ||||
794 | // register class that could contain the size being extended from. Thus, | ||||
795 | // if we're folding a (sext i8), we need the RHS to be a GPR32, even though | ||||
796 | // there might not be an actual 32-bit value in the program. We can | ||||
797 | // (harmlessly) synthesize one by injected an EXTRACT_SUBREG here. | ||||
798 | assert(Ext != AArch64_AM::UXTX && Ext != AArch64_AM::SXTX)((Ext != AArch64_AM::UXTX && Ext != AArch64_AM::SXTX) ? static_cast<void> (0) : __assert_fail ("Ext != AArch64_AM::UXTX && Ext != AArch64_AM::SXTX" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 798, __PRETTY_FUNCTION__)); | ||||
799 | Reg = narrowIfNeeded(CurDAG, Reg); | ||||
800 | Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(N), | ||||
801 | MVT::i32); | ||||
802 | return isWorthFolding(N); | ||||
803 | } | ||||
804 | |||||
805 | /// If there's a use of this ADDlow that's not itself a load/store then we'll | ||||
806 | /// need to create a real ADD instruction from it anyway and there's no point in | ||||
807 | /// folding it into the mem op. Theoretically, it shouldn't matter, but there's | ||||
808 | /// a single pseudo-instruction for an ADRP/ADD pair so over-aggressive folding | ||||
809 | /// leads to duplicated ADRP instructions. | ||||
810 | static bool isWorthFoldingADDlow(SDValue N) { | ||||
811 | for (auto Use : N->uses()) { | ||||
812 | if (Use->getOpcode() != ISD::LOAD && Use->getOpcode() != ISD::STORE && | ||||
813 | Use->getOpcode() != ISD::ATOMIC_LOAD && | ||||
814 | Use->getOpcode() != ISD::ATOMIC_STORE) | ||||
815 | return false; | ||||
816 | |||||
817 | // ldar and stlr have much more restrictive addressing modes (just a | ||||
818 | // register). | ||||
819 | if (isStrongerThanMonotonic(cast<MemSDNode>(Use)->getOrdering())) | ||||
820 | return false; | ||||
821 | } | ||||
822 | |||||
823 | return true; | ||||
824 | } | ||||
825 | |||||
826 | /// SelectAddrModeIndexedBitWidth - Select a "register plus scaled (un)signed BW-bit | ||||
827 | /// immediate" address. The "Size" argument is the size in bytes of the memory | ||||
828 | /// reference, which determines the scale. | ||||
829 | bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(SDValue N, bool IsSignedImm, | ||||
830 | unsigned BW, unsigned Size, | ||||
831 | SDValue &Base, | ||||
832 | SDValue &OffImm) { | ||||
833 | SDLoc dl(N); | ||||
834 | const DataLayout &DL = CurDAG->getDataLayout(); | ||||
835 | const TargetLowering *TLI = getTargetLowering(); | ||||
836 | if (N.getOpcode() == ISD::FrameIndex) { | ||||
837 | int FI = cast<FrameIndexSDNode>(N)->getIndex(); | ||||
838 | Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); | ||||
839 | OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64); | ||||
840 | return true; | ||||
841 | } | ||||
842 | |||||
843 | // As opposed to the (12-bit) Indexed addressing mode below, the 7/9-bit signed | ||||
844 | // selected here doesn't support labels/immediates, only base+offset. | ||||
845 | if (CurDAG->isBaseWithConstantOffset(N)) { | ||||
846 | if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { | ||||
847 | if (IsSignedImm) { | ||||
848 | int64_t RHSC = RHS->getSExtValue(); | ||||
849 | unsigned Scale = Log2_32(Size); | ||||
850 | int64_t Range = 0x1LL << (BW - 1); | ||||
851 | |||||
852 | if ((RHSC & (Size - 1)) == 0 && RHSC >= -(Range << Scale) && | ||||
853 | RHSC < (Range << Scale)) { | ||||
854 | Base = N.getOperand(0); | ||||
855 | if (Base.getOpcode() == ISD::FrameIndex) { | ||||
856 | int FI = cast<FrameIndexSDNode>(Base)->getIndex(); | ||||
857 | Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); | ||||
858 | } | ||||
859 | OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64); | ||||
860 | return true; | ||||
861 | } | ||||
862 | } else { | ||||
863 | // unsigned Immediate | ||||
864 | uint64_t RHSC = RHS->getZExtValue(); | ||||
865 | unsigned Scale = Log2_32(Size); | ||||
866 | uint64_t Range = 0x1ULL << BW; | ||||
867 | |||||
868 | if ((RHSC & (Size - 1)) == 0 && RHSC < (Range << Scale)) { | ||||
869 | Base = N.getOperand(0); | ||||
870 | if (Base.getOpcode() == ISD::FrameIndex) { | ||||
871 | int FI = cast<FrameIndexSDNode>(Base)->getIndex(); | ||||
872 | Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); | ||||
873 | } | ||||
874 | OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64); | ||||
875 | return true; | ||||
876 | } | ||||
877 | } | ||||
878 | } | ||||
879 | } | ||||
880 | // Base only. The address will be materialized into a register before | ||||
881 | // the memory is accessed. | ||||
882 | // add x0, Xbase, #offset | ||||
883 | // stp x1, x2, [x0] | ||||
884 | Base = N; | ||||
885 | OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64); | ||||
886 | return true; | ||||
887 | } | ||||
888 | |||||
889 | /// SelectAddrModeIndexed - Select a "register plus scaled unsigned 12-bit | ||||
890 | /// immediate" address. The "Size" argument is the size in bytes of the memory | ||||
891 | /// reference, which determines the scale. | ||||
892 | bool AArch64DAGToDAGISel::SelectAddrModeIndexed(SDValue N, unsigned Size, | ||||
893 | SDValue &Base, SDValue &OffImm) { | ||||
894 | SDLoc dl(N); | ||||
895 | const DataLayout &DL = CurDAG->getDataLayout(); | ||||
896 | const TargetLowering *TLI = getTargetLowering(); | ||||
897 | if (N.getOpcode() == ISD::FrameIndex) { | ||||
898 | int FI = cast<FrameIndexSDNode>(N)->getIndex(); | ||||
899 | Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); | ||||
900 | OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64); | ||||
901 | return true; | ||||
902 | } | ||||
903 | |||||
904 | if (N.getOpcode() == AArch64ISD::ADDlow && isWorthFoldingADDlow(N)) { | ||||
905 | GlobalAddressSDNode *GAN = | ||||
906 | dyn_cast<GlobalAddressSDNode>(N.getOperand(1).getNode()); | ||||
907 | Base = N.getOperand(0); | ||||
908 | OffImm = N.getOperand(1); | ||||
909 | if (!GAN) | ||||
910 | return true; | ||||
911 | |||||
912 | if (GAN->getOffset() % Size == 0 && | ||||
913 | GAN->getGlobal()->getPointerAlignment(DL) >= Size) | ||||
914 | return true; | ||||
915 | } | ||||
916 | |||||
917 | if (CurDAG->isBaseWithConstantOffset(N)) { | ||||
918 | if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { | ||||
919 | int64_t RHSC = (int64_t)RHS->getZExtValue(); | ||||
920 | unsigned Scale = Log2_32(Size); | ||||
921 | if ((RHSC & (Size - 1)) == 0 && RHSC >= 0 && RHSC < (0x1000 << Scale)) { | ||||
922 | Base = N.getOperand(0); | ||||
923 | if (Base.getOpcode() == ISD::FrameIndex) { | ||||
924 | int FI = cast<FrameIndexSDNode>(Base)->getIndex(); | ||||
925 | Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); | ||||
926 | } | ||||
927 | OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64); | ||||
928 | return true; | ||||
929 | } | ||||
930 | } | ||||
931 | } | ||||
932 | |||||
933 | // Before falling back to our general case, check if the unscaled | ||||
934 | // instructions can handle this. If so, that's preferable. | ||||
935 | if (SelectAddrModeUnscaled(N, Size, Base, OffImm)) | ||||
936 | return false; | ||||
937 | |||||
938 | // Base only. The address will be materialized into a register before | ||||
939 | // the memory is accessed. | ||||
940 | // add x0, Xbase, #offset | ||||
941 | // ldr x0, [x0] | ||||
942 | Base = N; | ||||
943 | OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64); | ||||
944 | return true; | ||||
945 | } | ||||
946 | |||||
947 | /// SelectAddrModeUnscaled - Select a "register plus unscaled signed 9-bit | ||||
948 | /// immediate" address. This should only match when there is an offset that | ||||
949 | /// is not valid for a scaled immediate addressing mode. The "Size" argument | ||||
950 | /// is the size in bytes of the memory reference, which is needed here to know | ||||
951 | /// what is valid for a scaled immediate. | ||||
952 | bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(SDValue N, unsigned Size, | ||||
953 | SDValue &Base, | ||||
954 | SDValue &OffImm) { | ||||
955 | if (!CurDAG->isBaseWithConstantOffset(N)) | ||||
956 | return false; | ||||
957 | if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { | ||||
958 | int64_t RHSC = RHS->getSExtValue(); | ||||
959 | // If the offset is valid as a scaled immediate, don't match here. | ||||
960 | if ((RHSC & (Size - 1)) == 0 && RHSC >= 0 && | ||||
961 | RHSC < (0x1000 << Log2_32(Size))) | ||||
962 | return false; | ||||
963 | if (RHSC >= -256 && RHSC < 256) { | ||||
964 | Base = N.getOperand(0); | ||||
965 | if (Base.getOpcode() == ISD::FrameIndex) { | ||||
966 | int FI = cast<FrameIndexSDNode>(Base)->getIndex(); | ||||
967 | const TargetLowering *TLI = getTargetLowering(); | ||||
968 | Base = CurDAG->getTargetFrameIndex( | ||||
969 | FI, TLI->getPointerTy(CurDAG->getDataLayout())); | ||||
970 | } | ||||
971 | OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i64); | ||||
972 | return true; | ||||
973 | } | ||||
974 | } | ||||
975 | return false; | ||||
976 | } | ||||
977 | |||||
978 | static SDValue Widen(SelectionDAG *CurDAG, SDValue N) { | ||||
979 | SDLoc dl(N); | ||||
980 | SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32); | ||||
981 | SDValue ImpDef = SDValue( | ||||
982 | CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0); | ||||
983 | MachineSDNode *Node = CurDAG->getMachineNode( | ||||
984 | TargetOpcode::INSERT_SUBREG, dl, MVT::i64, ImpDef, N, SubReg); | ||||
985 | return SDValue(Node, 0); | ||||
986 | } | ||||
987 | |||||
988 | /// Check if the given SHL node (\p N), can be used to form an | ||||
989 | /// extended register for an addressing mode. | ||||
990 | bool AArch64DAGToDAGISel::SelectExtendedSHL(SDValue N, unsigned Size, | ||||
991 | bool WantExtend, SDValue &Offset, | ||||
992 | SDValue &SignExtend) { | ||||
993 | assert(N.getOpcode() == ISD::SHL && "Invalid opcode.")((N.getOpcode() == ISD::SHL && "Invalid opcode.") ? static_cast <void> (0) : __assert_fail ("N.getOpcode() == ISD::SHL && \"Invalid opcode.\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 993, __PRETTY_FUNCTION__)); | ||||
994 | ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1)); | ||||
995 | if (!CSD || (CSD->getZExtValue() & 0x7) != CSD->getZExtValue()) | ||||
996 | return false; | ||||
997 | |||||
998 | SDLoc dl(N); | ||||
999 | if (WantExtend) { | ||||
1000 | AArch64_AM::ShiftExtendType Ext = | ||||
1001 | getExtendTypeForNode(N.getOperand(0), true); | ||||
1002 | if (Ext == AArch64_AM::InvalidShiftExtend) | ||||
1003 | return false; | ||||
1004 | |||||
1005 | Offset = narrowIfNeeded(CurDAG, N.getOperand(0).getOperand(0)); | ||||
1006 | SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl, | ||||
1007 | MVT::i32); | ||||
1008 | } else { | ||||
1009 | Offset = N.getOperand(0); | ||||
1010 | SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32); | ||||
1011 | } | ||||
1012 | |||||
1013 | unsigned LegalShiftVal = Log2_32(Size); | ||||
1014 | unsigned ShiftVal = CSD->getZExtValue(); | ||||
1015 | |||||
1016 | if (ShiftVal != 0 && ShiftVal != LegalShiftVal) | ||||
1017 | return false; | ||||
1018 | |||||
1019 | return isWorthFolding(N); | ||||
1020 | } | ||||
1021 | |||||
1022 | bool AArch64DAGToDAGISel::SelectAddrModeWRO(SDValue N, unsigned Size, | ||||
1023 | SDValue &Base, SDValue &Offset, | ||||
1024 | SDValue &SignExtend, | ||||
1025 | SDValue &DoShift) { | ||||
1026 | if (N.getOpcode() != ISD::ADD) | ||||
1027 | return false; | ||||
1028 | SDValue LHS = N.getOperand(0); | ||||
1029 | SDValue RHS = N.getOperand(1); | ||||
1030 | SDLoc dl(N); | ||||
1031 | |||||
1032 | // We don't want to match immediate adds here, because they are better lowered | ||||
1033 | // to the register-immediate addressing modes. | ||||
1034 | if (isa<ConstantSDNode>(LHS) || isa<ConstantSDNode>(RHS)) | ||||
1035 | return false; | ||||
1036 | |||||
1037 | // Check if this particular node is reused in any non-memory related | ||||
1038 | // operation. If yes, do not try to fold this node into the address | ||||
1039 | // computation, since the computation will be kept. | ||||
1040 | const SDNode *Node = N.getNode(); | ||||
1041 | for (SDNode *UI : Node->uses()) { | ||||
1042 | if (!isa<MemSDNode>(*UI)) | ||||
1043 | return false; | ||||
1044 | } | ||||
1045 | |||||
1046 | // Remember if it is worth folding N when it produces extended register. | ||||
1047 | bool IsExtendedRegisterWorthFolding = isWorthFolding(N); | ||||
1048 | |||||
1049 | // Try to match a shifted extend on the RHS. | ||||
1050 | if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL && | ||||
1051 | SelectExtendedSHL(RHS, Size, true, Offset, SignExtend)) { | ||||
1052 | Base = LHS; | ||||
1053 | DoShift = CurDAG->getTargetConstant(true, dl, MVT::i32); | ||||
1054 | return true; | ||||
1055 | } | ||||
1056 | |||||
1057 | // Try to match a shifted extend on the LHS. | ||||
1058 | if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL && | ||||
1059 | SelectExtendedSHL(LHS, Size, true, Offset, SignExtend)) { | ||||
1060 | Base = RHS; | ||||
1061 | DoShift = CurDAG->getTargetConstant(true, dl, MVT::i32); | ||||
1062 | return true; | ||||
1063 | } | ||||
1064 | |||||
1065 | // There was no shift, whatever else we find. | ||||
1066 | DoShift = CurDAG->getTargetConstant(false, dl, MVT::i32); | ||||
1067 | |||||
1068 | AArch64_AM::ShiftExtendType Ext = AArch64_AM::InvalidShiftExtend; | ||||
1069 | // Try to match an unshifted extend on the LHS. | ||||
1070 | if (IsExtendedRegisterWorthFolding && | ||||
1071 | (Ext = getExtendTypeForNode(LHS, true)) != | ||||
1072 | AArch64_AM::InvalidShiftExtend) { | ||||
1073 | Base = RHS; | ||||
1074 | Offset = narrowIfNeeded(CurDAG, LHS.getOperand(0)); | ||||
1075 | SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl, | ||||
1076 | MVT::i32); | ||||
1077 | if (isWorthFolding(LHS)) | ||||
1078 | return true; | ||||
1079 | } | ||||
1080 | |||||
1081 | // Try to match an unshifted extend on the RHS. | ||||
1082 | if (IsExtendedRegisterWorthFolding && | ||||
1083 | (Ext = getExtendTypeForNode(RHS, true)) != | ||||
1084 | AArch64_AM::InvalidShiftExtend) { | ||||
1085 | Base = LHS; | ||||
1086 | Offset = narrowIfNeeded(CurDAG, RHS.getOperand(0)); | ||||
1087 | SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl, | ||||
1088 | MVT::i32); | ||||
1089 | if (isWorthFolding(RHS)) | ||||
1090 | return true; | ||||
1091 | } | ||||
1092 | |||||
1093 | return false; | ||||
1094 | } | ||||
1095 | |||||
1096 | // Check if the given immediate is preferred by ADD. If an immediate can be | ||||
1097 | // encoded in an ADD, or it can be encoded in an "ADD LSL #12" and can not be | ||||
1098 | // encoded by one MOVZ, return true. | ||||
1099 | static bool isPreferredADD(int64_t ImmOff) { | ||||
1100 | // Constant in [0x0, 0xfff] can be encoded in ADD. | ||||
1101 | if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL) | ||||
1102 | return true; | ||||
1103 | // Check if it can be encoded in an "ADD LSL #12". | ||||
1104 | if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL) | ||||
1105 | // As a single MOVZ is faster than a "ADD of LSL #12", ignore such constant. | ||||
1106 | return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL && | ||||
1107 | (ImmOff & 0xffffffffffff0fffLL) != 0x0LL; | ||||
1108 | return false; | ||||
1109 | } | ||||
1110 | |||||
1111 | bool AArch64DAGToDAGISel::SelectAddrModeXRO(SDValue N, unsigned Size, | ||||
1112 | SDValue &Base, SDValue &Offset, | ||||
1113 | SDValue &SignExtend, | ||||
1114 | SDValue &DoShift) { | ||||
1115 | if (N.getOpcode() != ISD::ADD) | ||||
1116 | return false; | ||||
1117 | SDValue LHS = N.getOperand(0); | ||||
1118 | SDValue RHS = N.getOperand(1); | ||||
1119 | SDLoc DL(N); | ||||
1120 | |||||
1121 | // Check if this particular node is reused in any non-memory related | ||||
1122 | // operation. If yes, do not try to fold this node into the address | ||||
1123 | // computation, since the computation will be kept. | ||||
1124 | const SDNode *Node = N.getNode(); | ||||
1125 | for (SDNode *UI : Node->uses()) { | ||||
1126 | if (!isa<MemSDNode>(*UI)) | ||||
1127 | return false; | ||||
1128 | } | ||||
1129 | |||||
1130 | // Watch out if RHS is a wide immediate, it can not be selected into | ||||
1131 | // [BaseReg+Imm] addressing mode. Also it may not be able to be encoded into | ||||
1132 | // ADD/SUB. Instead it will use [BaseReg + 0] address mode and generate | ||||
1133 | // instructions like: | ||||
1134 | // MOV X0, WideImmediate | ||||
1135 | // ADD X1, BaseReg, X0 | ||||
1136 | // LDR X2, [X1, 0] | ||||
1137 | // For such situation, using [BaseReg, XReg] addressing mode can save one | ||||
1138 | // ADD/SUB: | ||||
1139 | // MOV X0, WideImmediate | ||||
1140 | // LDR X2, [BaseReg, X0] | ||||
1141 | if (isa<ConstantSDNode>(RHS)) { | ||||
1142 | int64_t ImmOff = (int64_t)cast<ConstantSDNode>(RHS)->getZExtValue(); | ||||
1143 | unsigned Scale = Log2_32(Size); | ||||
1144 | // Skip the immediate can be selected by load/store addressing mode. | ||||
1145 | // Also skip the immediate can be encoded by a single ADD (SUB is also | ||||
1146 | // checked by using -ImmOff). | ||||
1147 | if ((ImmOff % Size == 0 && ImmOff >= 0 && ImmOff < (0x1000 << Scale)) || | ||||
1148 | isPreferredADD(ImmOff) || isPreferredADD(-ImmOff)) | ||||
1149 | return false; | ||||
1150 | |||||
1151 | SDValue Ops[] = { RHS }; | ||||
1152 | SDNode *MOVI = | ||||
1153 | CurDAG->getMachineNode(AArch64::MOVi64imm, DL, MVT::i64, Ops); | ||||
1154 | SDValue MOVIV = SDValue(MOVI, 0); | ||||
1155 | // This ADD of two X register will be selected into [Reg+Reg] mode. | ||||
1156 | N = CurDAG->getNode(ISD::ADD, DL, MVT::i64, LHS, MOVIV); | ||||
1157 | } | ||||
1158 | |||||
1159 | // Remember if it is worth folding N when it produces extended register. | ||||
1160 | bool IsExtendedRegisterWorthFolding = isWorthFolding(N); | ||||
1161 | |||||
1162 | // Try to match a shifted extend on the RHS. | ||||
1163 | if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL && | ||||
1164 | SelectExtendedSHL(RHS, Size, false, Offset, SignExtend)) { | ||||
1165 | Base = LHS; | ||||
1166 | DoShift = CurDAG->getTargetConstant(true, DL, MVT::i32); | ||||
1167 | return true; | ||||
1168 | } | ||||
1169 | |||||
1170 | // Try to match a shifted extend on the LHS. | ||||
1171 | if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL && | ||||
1172 | SelectExtendedSHL(LHS, Size, false, Offset, SignExtend)) { | ||||
1173 | Base = RHS; | ||||
1174 | DoShift = CurDAG->getTargetConstant(true, DL, MVT::i32); | ||||
1175 | return true; | ||||
1176 | } | ||||
1177 | |||||
1178 | // Match any non-shifted, non-extend, non-immediate add expression. | ||||
1179 | Base = LHS; | ||||
1180 | Offset = RHS; | ||||
1181 | SignExtend = CurDAG->getTargetConstant(false, DL, MVT::i32); | ||||
1182 | DoShift = CurDAG->getTargetConstant(false, DL, MVT::i32); | ||||
1183 | // Reg1 + Reg2 is free: no check needed. | ||||
1184 | return true; | ||||
1185 | } | ||||
1186 | |||||
1187 | SDValue AArch64DAGToDAGISel::createDTuple(ArrayRef<SDValue> Regs) { | ||||
1188 | static const unsigned RegClassIDs[] = { | ||||
1189 | AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID}; | ||||
1190 | static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1, | ||||
1191 | AArch64::dsub2, AArch64::dsub3}; | ||||
1192 | |||||
1193 | return createTuple(Regs, RegClassIDs, SubRegs); | ||||
1194 | } | ||||
1195 | |||||
1196 | SDValue AArch64DAGToDAGISel::createQTuple(ArrayRef<SDValue> Regs) { | ||||
1197 | static const unsigned RegClassIDs[] = { | ||||
1198 | AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID}; | ||||
1199 | static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1, | ||||
1200 | AArch64::qsub2, AArch64::qsub3}; | ||||
1201 | |||||
1202 | return createTuple(Regs, RegClassIDs, SubRegs); | ||||
1203 | } | ||||
1204 | |||||
1205 | SDValue AArch64DAGToDAGISel::createZTuple(ArrayRef<SDValue> Regs) { | ||||
1206 | static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID, | ||||
1207 | AArch64::ZPR3RegClassID, | ||||
1208 | AArch64::ZPR4RegClassID}; | ||||
1209 | static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1, | ||||
1210 | AArch64::zsub2, AArch64::zsub3}; | ||||
1211 | |||||
1212 | return createTuple(Regs, RegClassIDs, SubRegs); | ||||
1213 | } | ||||
1214 | |||||
1215 | SDValue AArch64DAGToDAGISel::createTuple(ArrayRef<SDValue> Regs, | ||||
1216 | const unsigned RegClassIDs[], | ||||
1217 | const unsigned SubRegs[]) { | ||||
1218 | // There's no special register-class for a vector-list of 1 element: it's just | ||||
1219 | // a vector. | ||||
1220 | if (Regs.size() == 1) | ||||
1221 | return Regs[0]; | ||||
1222 | |||||
1223 | assert(Regs.size() >= 2 && Regs.size() <= 4)((Regs.size() >= 2 && Regs.size() <= 4) ? static_cast <void> (0) : __assert_fail ("Regs.size() >= 2 && Regs.size() <= 4" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1223, __PRETTY_FUNCTION__)); | ||||
1224 | |||||
1225 | SDLoc DL(Regs[0]); | ||||
1226 | |||||
1227 | SmallVector<SDValue, 4> Ops; | ||||
1228 | |||||
1229 | // First operand of REG_SEQUENCE is the desired RegClass. | ||||
1230 | Ops.push_back( | ||||
1231 | CurDAG->getTargetConstant(RegClassIDs[Regs.size() - 2], DL, MVT::i32)); | ||||
1232 | |||||
1233 | // Then we get pairs of source & subregister-position for the components. | ||||
1234 | for (unsigned i = 0; i < Regs.size(); ++i) { | ||||
1235 | Ops.push_back(Regs[i]); | ||||
1236 | Ops.push_back(CurDAG->getTargetConstant(SubRegs[i], DL, MVT::i32)); | ||||
1237 | } | ||||
1238 | |||||
1239 | SDNode *N = | ||||
1240 | CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, MVT::Untyped, Ops); | ||||
1241 | return SDValue(N, 0); | ||||
1242 | } | ||||
1243 | |||||
1244 | void AArch64DAGToDAGISel::SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc, | ||||
1245 | bool isExt) { | ||||
1246 | SDLoc dl(N); | ||||
1247 | EVT VT = N->getValueType(0); | ||||
1248 | |||||
1249 | unsigned ExtOff = isExt; | ||||
1250 | |||||
1251 | // Form a REG_SEQUENCE to force register allocation. | ||||
1252 | unsigned Vec0Off = ExtOff + 1; | ||||
1253 | SmallVector<SDValue, 4> Regs(N->op_begin() + Vec0Off, | ||||
1254 | N->op_begin() + Vec0Off + NumVecs); | ||||
1255 | SDValue RegSeq = createQTuple(Regs); | ||||
1256 | |||||
1257 | SmallVector<SDValue, 6> Ops; | ||||
1258 | if (isExt) | ||||
1259 | Ops.push_back(N->getOperand(1)); | ||||
1260 | Ops.push_back(RegSeq); | ||||
1261 | Ops.push_back(N->getOperand(NumVecs + ExtOff + 1)); | ||||
1262 | ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops)); | ||||
1263 | } | ||||
1264 | |||||
1265 | bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *N) { | ||||
1266 | LoadSDNode *LD = cast<LoadSDNode>(N); | ||||
1267 | if (LD->isUnindexed()) | ||||
1268 | return false; | ||||
1269 | EVT VT = LD->getMemoryVT(); | ||||
1270 | EVT DstVT = N->getValueType(0); | ||||
1271 | ISD::MemIndexedMode AM = LD->getAddressingMode(); | ||||
1272 | bool IsPre = AM == ISD::PRE_INC || AM == ISD::PRE_DEC; | ||||
1273 | |||||
1274 | // We're not doing validity checking here. That was done when checking | ||||
1275 | // if we should mark the load as indexed or not. We're just selecting | ||||
1276 | // the right instruction. | ||||
1277 | unsigned Opcode = 0; | ||||
1278 | |||||
1279 | ISD::LoadExtType ExtType = LD->getExtensionType(); | ||||
1280 | bool InsertTo64 = false; | ||||
1281 | if (VT == MVT::i64) | ||||
1282 | Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost; | ||||
1283 | else if (VT == MVT::i32) { | ||||
1284 | if (ExtType == ISD::NON_EXTLOAD) | ||||
1285 | Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost; | ||||
1286 | else if (ExtType == ISD::SEXTLOAD) | ||||
1287 | Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost; | ||||
1288 | else { | ||||
1289 | Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost; | ||||
1290 | InsertTo64 = true; | ||||
1291 | // The result of the load is only i32. It's the subreg_to_reg that makes | ||||
1292 | // it into an i64. | ||||
1293 | DstVT = MVT::i32; | ||||
1294 | } | ||||
1295 | } else if (VT == MVT::i16) { | ||||
1296 | if (ExtType == ISD::SEXTLOAD) { | ||||
1297 | if (DstVT == MVT::i64) | ||||
1298 | Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost; | ||||
1299 | else | ||||
1300 | Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost; | ||||
1301 | } else { | ||||
1302 | Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost; | ||||
1303 | InsertTo64 = DstVT == MVT::i64; | ||||
1304 | // The result of the load is only i32. It's the subreg_to_reg that makes | ||||
1305 | // it into an i64. | ||||
1306 | DstVT = MVT::i32; | ||||
1307 | } | ||||
1308 | } else if (VT == MVT::i8) { | ||||
1309 | if (ExtType == ISD::SEXTLOAD) { | ||||
1310 | if (DstVT == MVT::i64) | ||||
1311 | Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost; | ||||
1312 | else | ||||
1313 | Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost; | ||||
1314 | } else { | ||||
1315 | Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost; | ||||
1316 | InsertTo64 = DstVT == MVT::i64; | ||||
1317 | // The result of the load is only i32. It's the subreg_to_reg that makes | ||||
1318 | // it into an i64. | ||||
1319 | DstVT = MVT::i32; | ||||
1320 | } | ||||
1321 | } else if (VT == MVT::f16) { | ||||
1322 | Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost; | ||||
1323 | } else if (VT == MVT::bf16) { | ||||
1324 | Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost; | ||||
1325 | } else if (VT == MVT::f32) { | ||||
1326 | Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost; | ||||
1327 | } else if (VT == MVT::f64 || VT.is64BitVector()) { | ||||
1328 | Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost; | ||||
1329 | } else if (VT.is128BitVector()) { | ||||
1330 | Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost; | ||||
1331 | } else | ||||
1332 | return false; | ||||
1333 | SDValue Chain = LD->getChain(); | ||||
1334 | SDValue Base = LD->getBasePtr(); | ||||
1335 | ConstantSDNode *OffsetOp = cast<ConstantSDNode>(LD->getOffset()); | ||||
1336 | int OffsetVal = (int)OffsetOp->getZExtValue(); | ||||
1337 | SDLoc dl(N); | ||||
1338 | SDValue Offset = CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64); | ||||
1339 | SDValue Ops[] = { Base, Offset, Chain }; | ||||
1340 | SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT, | ||||
1341 | MVT::Other, Ops); | ||||
1342 | |||||
1343 | // Transfer memoperands. | ||||
1344 | MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand(); | ||||
1345 | CurDAG->setNodeMemRefs(cast<MachineSDNode>(Res), {MemOp}); | ||||
1346 | |||||
1347 | // Either way, we're replacing the node, so tell the caller that. | ||||
1348 | SDValue LoadedVal = SDValue(Res, 1); | ||||
1349 | if (InsertTo64) { | ||||
1350 | SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32); | ||||
1351 | LoadedVal = | ||||
1352 | SDValue(CurDAG->getMachineNode( | ||||
1353 | AArch64::SUBREG_TO_REG, dl, MVT::i64, | ||||
1354 | CurDAG->getTargetConstant(0, dl, MVT::i64), LoadedVal, | ||||
1355 | SubReg), | ||||
1356 | 0); | ||||
1357 | } | ||||
1358 | |||||
1359 | ReplaceUses(SDValue(N, 0), LoadedVal); | ||||
1360 | ReplaceUses(SDValue(N, 1), SDValue(Res, 0)); | ||||
1361 | ReplaceUses(SDValue(N, 2), SDValue(Res, 2)); | ||||
1362 | CurDAG->RemoveDeadNode(N); | ||||
1363 | return true; | ||||
1364 | } | ||||
1365 | |||||
1366 | void AArch64DAGToDAGISel::SelectLoad(SDNode *N, unsigned NumVecs, unsigned Opc, | ||||
1367 | unsigned SubRegIdx) { | ||||
1368 | SDLoc dl(N); | ||||
1369 | EVT VT = N->getValueType(0); | ||||
1370 | SDValue Chain = N->getOperand(0); | ||||
1371 | |||||
1372 | SDValue Ops[] = {N->getOperand(2), // Mem operand; | ||||
1373 | Chain}; | ||||
1374 | |||||
1375 | const EVT ResTys[] = {MVT::Untyped, MVT::Other}; | ||||
1376 | |||||
1377 | SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); | ||||
1378 | SDValue SuperReg = SDValue(Ld, 0); | ||||
1379 | for (unsigned i = 0; i < NumVecs; ++i) | ||||
1380 | ReplaceUses(SDValue(N, i), | ||||
1381 | CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg)); | ||||
1382 | |||||
1383 | ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 1)); | ||||
1384 | |||||
1385 | // Transfer memoperands. In the case of AArch64::LD64B, there won't be one, | ||||
1386 | // because it's too simple to have needed special treatment during lowering. | ||||
1387 | if (auto *MemIntr = dyn_cast<MemIntrinsicSDNode>(N)) { | ||||
1388 | MachineMemOperand *MemOp = MemIntr->getMemOperand(); | ||||
1389 | CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {MemOp}); | ||||
1390 | } | ||||
1391 | |||||
1392 | CurDAG->RemoveDeadNode(N); | ||||
1393 | } | ||||
1394 | |||||
1395 | void AArch64DAGToDAGISel::SelectPostLoad(SDNode *N, unsigned NumVecs, | ||||
1396 | unsigned Opc, unsigned SubRegIdx) { | ||||
1397 | SDLoc dl(N); | ||||
1398 | EVT VT = N->getValueType(0); | ||||
1399 | SDValue Chain = N->getOperand(0); | ||||
1400 | |||||
1401 | SDValue Ops[] = {N->getOperand(1), // Mem operand | ||||
1402 | N->getOperand(2), // Incremental | ||||
1403 | Chain}; | ||||
1404 | |||||
1405 | const EVT ResTys[] = {MVT::i64, // Type of the write back register | ||||
1406 | MVT::Untyped, MVT::Other}; | ||||
1407 | |||||
1408 | SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); | ||||
1409 | |||||
1410 | // Update uses of write back register | ||||
1411 | ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 0)); | ||||
1412 | |||||
1413 | // Update uses of vector list | ||||
1414 | SDValue SuperReg = SDValue(Ld, 1); | ||||
1415 | if (NumVecs == 1) | ||||
1416 | ReplaceUses(SDValue(N, 0), SuperReg); | ||||
1417 | else | ||||
1418 | for (unsigned i = 0; i < NumVecs; ++i) | ||||
1419 | ReplaceUses(SDValue(N, i), | ||||
1420 | CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg)); | ||||
1421 | |||||
1422 | // Update the chain | ||||
1423 | ReplaceUses(SDValue(N, NumVecs + 1), SDValue(Ld, 2)); | ||||
1424 | CurDAG->RemoveDeadNode(N); | ||||
1425 | } | ||||
1426 | |||||
1427 | /// Optimize \param OldBase and \param OldOffset selecting the best addressing | ||||
1428 | /// mode. Returns a tuple consisting of an Opcode, an SDValue representing the | ||||
1429 | /// new Base and an SDValue representing the new offset. | ||||
1430 | std::tuple<unsigned, SDValue, SDValue> | ||||
1431 | AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *N, unsigned Opc_rr, | ||||
1432 | unsigned Opc_ri, | ||||
1433 | const SDValue &OldBase, | ||||
1434 | const SDValue &OldOffset, | ||||
1435 | unsigned Scale) { | ||||
1436 | SDValue NewBase = OldBase; | ||||
1437 | SDValue NewOffset = OldOffset; | ||||
1438 | // Detect a possible Reg+Imm addressing mode. | ||||
1439 | const bool IsRegImm = SelectAddrModeIndexedSVE</*Min=*/-8, /*Max=*/7>( | ||||
1440 | N, OldBase, NewBase, NewOffset); | ||||
1441 | |||||
1442 | // Detect a possible reg+reg addressing mode, but only if we haven't already | ||||
1443 | // detected a Reg+Imm one. | ||||
1444 | const bool IsRegReg = | ||||
1445 | !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset); | ||||
1446 | |||||
1447 | // Select the instruction. | ||||
1448 | return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset); | ||||
1449 | } | ||||
1450 | |||||
1451 | void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *N, unsigned NumVecs, | ||||
1452 | unsigned Scale, unsigned Opc_ri, | ||||
1453 | unsigned Opc_rr) { | ||||
1454 | assert(Scale < 4 && "Invalid scaling value.")((Scale < 4 && "Invalid scaling value.") ? static_cast <void> (0) : __assert_fail ("Scale < 4 && \"Invalid scaling value.\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1454, __PRETTY_FUNCTION__)); | ||||
1455 | SDLoc DL(N); | ||||
1456 | EVT VT = N->getValueType(0); | ||||
1457 | SDValue Chain = N->getOperand(0); | ||||
1458 | |||||
1459 | // Optimize addressing mode. | ||||
1460 | SDValue Base, Offset; | ||||
1461 | unsigned Opc; | ||||
1462 | std::tie(Opc, Base, Offset) = findAddrModeSVELoadStore( | ||||
1463 | N, Opc_rr, Opc_ri, N->getOperand(2), | ||||
1464 | CurDAG->getTargetConstant(0, DL, MVT::i64), Scale); | ||||
1465 | |||||
1466 | SDValue Ops[] = {N->getOperand(1), // Predicate | ||||
1467 | Base, // Memory operand | ||||
1468 | Offset, Chain}; | ||||
1469 | |||||
1470 | const EVT ResTys[] = {MVT::Untyped, MVT::Other}; | ||||
1471 | |||||
1472 | SDNode *Load = CurDAG->getMachineNode(Opc, DL, ResTys, Ops); | ||||
1473 | SDValue SuperReg = SDValue(Load, 0); | ||||
1474 | for (unsigned i = 0; i < NumVecs; ++i) | ||||
1475 | ReplaceUses(SDValue(N, i), CurDAG->getTargetExtractSubreg( | ||||
1476 | AArch64::zsub0 + i, DL, VT, SuperReg)); | ||||
1477 | |||||
1478 | // Copy chain | ||||
1479 | unsigned ChainIdx = NumVecs; | ||||
1480 | ReplaceUses(SDValue(N, ChainIdx), SDValue(Load, 1)); | ||||
1481 | CurDAG->RemoveDeadNode(N); | ||||
1482 | } | ||||
1483 | |||||
1484 | void AArch64DAGToDAGISel::SelectStore(SDNode *N, unsigned NumVecs, | ||||
1485 | unsigned Opc) { | ||||
1486 | SDLoc dl(N); | ||||
1487 | EVT VT = N->getOperand(2)->getValueType(0); | ||||
1488 | |||||
1489 | // Form a REG_SEQUENCE to force register allocation. | ||||
1490 | bool Is128Bit = VT.getSizeInBits() == 128; | ||||
1491 | SmallVector<SDValue, 4> Regs(N->op_begin() + 2, N->op_begin() + 2 + NumVecs); | ||||
1492 | SDValue RegSeq = Is128Bit ? createQTuple(Regs) : createDTuple(Regs); | ||||
1493 | |||||
1494 | SDValue Ops[] = {RegSeq, N->getOperand(NumVecs + 2), N->getOperand(0)}; | ||||
1495 | SDNode *St = CurDAG->getMachineNode(Opc, dl, N->getValueType(0), Ops); | ||||
1496 | |||||
1497 | // Transfer memoperands. | ||||
1498 | MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); | ||||
1499 | CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp}); | ||||
1500 | |||||
1501 | ReplaceNode(N, St); | ||||
1502 | } | ||||
1503 | |||||
1504 | void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *N, unsigned NumVecs, | ||||
1505 | unsigned Scale, unsigned Opc_rr, | ||||
1506 | unsigned Opc_ri) { | ||||
1507 | SDLoc dl(N); | ||||
1508 | |||||
1509 | // Form a REG_SEQUENCE to force register allocation. | ||||
1510 | SmallVector<SDValue, 4> Regs(N->op_begin() + 2, N->op_begin() + 2 + NumVecs); | ||||
1511 | SDValue RegSeq = createZTuple(Regs); | ||||
1512 | |||||
1513 | // Optimize addressing mode. | ||||
1514 | unsigned Opc; | ||||
1515 | SDValue Offset, Base; | ||||
1516 | std::tie(Opc, Base, Offset) = findAddrModeSVELoadStore( | ||||
1517 | N, Opc_rr, Opc_ri, N->getOperand(NumVecs + 3), | ||||
1518 | CurDAG->getTargetConstant(0, dl, MVT::i64), Scale); | ||||
1519 | |||||
1520 | SDValue Ops[] = {RegSeq, N->getOperand(NumVecs + 2), // predicate | ||||
1521 | Base, // address | ||||
1522 | Offset, // offset | ||||
1523 | N->getOperand(0)}; // chain | ||||
1524 | SDNode *St = CurDAG->getMachineNode(Opc, dl, N->getValueType(0), Ops); | ||||
1525 | |||||
1526 | ReplaceNode(N, St); | ||||
1527 | } | ||||
1528 | |||||
1529 | bool AArch64DAGToDAGISel::SelectAddrModeFrameIndexSVE(SDValue N, SDValue &Base, | ||||
1530 | SDValue &OffImm) { | ||||
1531 | SDLoc dl(N); | ||||
1532 | const DataLayout &DL = CurDAG->getDataLayout(); | ||||
1533 | const TargetLowering *TLI = getTargetLowering(); | ||||
1534 | |||||
1535 | // Try to match it for the frame address | ||||
1536 | if (auto FINode = dyn_cast<FrameIndexSDNode>(N)) { | ||||
1537 | int FI = FINode->getIndex(); | ||||
1538 | Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); | ||||
1539 | OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64); | ||||
1540 | return true; | ||||
1541 | } | ||||
1542 | |||||
1543 | return false; | ||||
1544 | } | ||||
1545 | |||||
1546 | void AArch64DAGToDAGISel::SelectPostStore(SDNode *N, unsigned NumVecs, | ||||
1547 | unsigned Opc) { | ||||
1548 | SDLoc dl(N); | ||||
1549 | EVT VT = N->getOperand(2)->getValueType(0); | ||||
1550 | const EVT ResTys[] = {MVT::i64, // Type of the write back register | ||||
1551 | MVT::Other}; // Type for the Chain | ||||
1552 | |||||
1553 | // Form a REG_SEQUENCE to force register allocation. | ||||
1554 | bool Is128Bit = VT.getSizeInBits() == 128; | ||||
1555 | SmallVector<SDValue, 4> Regs(N->op_begin() + 1, N->op_begin() + 1 + NumVecs); | ||||
1556 | SDValue RegSeq = Is128Bit ? createQTuple(Regs) : createDTuple(Regs); | ||||
1557 | |||||
1558 | SDValue Ops[] = {RegSeq, | ||||
1559 | N->getOperand(NumVecs + 1), // base register | ||||
1560 | N->getOperand(NumVecs + 2), // Incremental | ||||
1561 | N->getOperand(0)}; // Chain | ||||
1562 | SDNode *St = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); | ||||
1563 | |||||
1564 | ReplaceNode(N, St); | ||||
1565 | } | ||||
1566 | |||||
1567 | namespace { | ||||
1568 | /// WidenVector - Given a value in the V64 register class, produce the | ||||
1569 | /// equivalent value in the V128 register class. | ||||
1570 | class WidenVector { | ||||
1571 | SelectionDAG &DAG; | ||||
1572 | |||||
1573 | public: | ||||
1574 | WidenVector(SelectionDAG &DAG) : DAG(DAG) {} | ||||
1575 | |||||
1576 | SDValue operator()(SDValue V64Reg) { | ||||
1577 | EVT VT = V64Reg.getValueType(); | ||||
1578 | unsigned NarrowSize = VT.getVectorNumElements(); | ||||
1579 | MVT EltTy = VT.getVectorElementType().getSimpleVT(); | ||||
1580 | MVT WideTy = MVT::getVectorVT(EltTy, 2 * NarrowSize); | ||||
1581 | SDLoc DL(V64Reg); | ||||
1582 | |||||
1583 | SDValue Undef = | ||||
1584 | SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, WideTy), 0); | ||||
1585 | return DAG.getTargetInsertSubreg(AArch64::dsub, DL, WideTy, Undef, V64Reg); | ||||
1586 | } | ||||
1587 | }; | ||||
1588 | } // namespace | ||||
1589 | |||||
1590 | /// NarrowVector - Given a value in the V128 register class, produce the | ||||
1591 | /// equivalent value in the V64 register class. | ||||
1592 | static SDValue NarrowVector(SDValue V128Reg, SelectionDAG &DAG) { | ||||
1593 | EVT VT = V128Reg.getValueType(); | ||||
1594 | unsigned WideSize = VT.getVectorNumElements(); | ||||
1595 | MVT EltTy = VT.getVectorElementType().getSimpleVT(); | ||||
1596 | MVT NarrowTy = MVT::getVectorVT(EltTy, WideSize / 2); | ||||
1597 | |||||
1598 | return DAG.getTargetExtractSubreg(AArch64::dsub, SDLoc(V128Reg), NarrowTy, | ||||
1599 | V128Reg); | ||||
1600 | } | ||||
1601 | |||||
1602 | void AArch64DAGToDAGISel::SelectLoadLane(SDNode *N, unsigned NumVecs, | ||||
1603 | unsigned Opc) { | ||||
1604 | SDLoc dl(N); | ||||
1605 | EVT VT = N->getValueType(0); | ||||
1606 | bool Narrow = VT.getSizeInBits() == 64; | ||||
1607 | |||||
1608 | // Form a REG_SEQUENCE to force register allocation. | ||||
1609 | SmallVector<SDValue, 4> Regs(N->op_begin() + 2, N->op_begin() + 2 + NumVecs); | ||||
1610 | |||||
1611 | if (Narrow) | ||||
1612 | transform(Regs, Regs.begin(), | ||||
1613 | WidenVector(*CurDAG)); | ||||
1614 | |||||
1615 | SDValue RegSeq = createQTuple(Regs); | ||||
1616 | |||||
1617 | const EVT ResTys[] = {MVT::Untyped, MVT::Other}; | ||||
1618 | |||||
1619 | unsigned LaneNo = | ||||
1620 | cast<ConstantSDNode>(N->getOperand(NumVecs + 2))->getZExtValue(); | ||||
1621 | |||||
1622 | SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64), | ||||
1623 | N->getOperand(NumVecs + 3), N->getOperand(0)}; | ||||
1624 | SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); | ||||
1625 | SDValue SuperReg = SDValue(Ld, 0); | ||||
1626 | |||||
1627 | EVT WideVT = RegSeq.getOperand(1)->getValueType(0); | ||||
1628 | static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1, | ||||
1629 | AArch64::qsub2, AArch64::qsub3 }; | ||||
1630 | for (unsigned i = 0; i < NumVecs; ++i) { | ||||
1631 | SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg); | ||||
1632 | if (Narrow) | ||||
1633 | NV = NarrowVector(NV, *CurDAG); | ||||
1634 | ReplaceUses(SDValue(N, i), NV); | ||||
1635 | } | ||||
1636 | |||||
1637 | ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 1)); | ||||
1638 | CurDAG->RemoveDeadNode(N); | ||||
1639 | } | ||||
1640 | |||||
1641 | void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *N, unsigned NumVecs, | ||||
1642 | unsigned Opc) { | ||||
1643 | SDLoc dl(N); | ||||
1644 | EVT VT = N->getValueType(0); | ||||
1645 | bool Narrow = VT.getSizeInBits() == 64; | ||||
| |||||
1646 | |||||
1647 | // Form a REG_SEQUENCE to force register allocation. | ||||
1648 | SmallVector<SDValue, 4> Regs(N->op_begin() + 1, N->op_begin() + 1 + NumVecs); | ||||
1649 | |||||
1650 | if (Narrow
| ||||
1651 | transform(Regs, Regs.begin(), | ||||
1652 | WidenVector(*CurDAG)); | ||||
1653 | |||||
1654 | SDValue RegSeq = createQTuple(Regs); | ||||
1655 | |||||
1656 | const EVT ResTys[] = {MVT::i64, // Type of the write back register | ||||
1657 | RegSeq->getValueType(0), MVT::Other}; | ||||
1658 | |||||
1659 | unsigned LaneNo = | ||||
1660 | cast<ConstantSDNode>(N->getOperand(NumVecs + 1))->getZExtValue(); | ||||
1661 | |||||
1662 | SDValue Ops[] = {RegSeq, | ||||
1663 | CurDAG->getTargetConstant(LaneNo, dl, | ||||
1664 | MVT::i64), // Lane Number | ||||
1665 | N->getOperand(NumVecs + 2), // Base register | ||||
1666 | N->getOperand(NumVecs + 3), // Incremental | ||||
1667 | N->getOperand(0)}; | ||||
1668 | SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); | ||||
1669 | |||||
1670 | // Update uses of the write back register | ||||
1671 | ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 0)); | ||||
1672 | |||||
1673 | // Update uses of the vector list | ||||
1674 | SDValue SuperReg = SDValue(Ld, 1); | ||||
1675 | if (NumVecs == 1) { | ||||
1676 | ReplaceUses(SDValue(N, 0), | ||||
1677 | Narrow
| ||||
1678 | } else { | ||||
1679 | EVT WideVT = RegSeq.getOperand(1)->getValueType(0); | ||||
1680 | static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1, | ||||
1681 | AArch64::qsub2, AArch64::qsub3 }; | ||||
1682 | for (unsigned i = 0; i < NumVecs; ++i) { | ||||
1683 | SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, | ||||
1684 | SuperReg); | ||||
1685 | if (Narrow) | ||||
1686 | NV = NarrowVector(NV, *CurDAG); | ||||
1687 | ReplaceUses(SDValue(N, i), NV); | ||||
1688 | } | ||||
1689 | } | ||||
1690 | |||||
1691 | // Update the Chain | ||||
1692 | ReplaceUses(SDValue(N, NumVecs + 1), SDValue(Ld, 2)); | ||||
1693 | CurDAG->RemoveDeadNode(N); | ||||
1694 | } | ||||
1695 | |||||
1696 | void AArch64DAGToDAGISel::SelectStoreLane(SDNode *N, unsigned NumVecs, | ||||
1697 | unsigned Opc) { | ||||
1698 | SDLoc dl(N); | ||||
1699 | EVT VT = N->getOperand(2)->getValueType(0); | ||||
1700 | bool Narrow = VT.getSizeInBits() == 64; | ||||
1701 | |||||
1702 | // Form a REG_SEQUENCE to force register allocation. | ||||
1703 | SmallVector<SDValue, 4> Regs(N->op_begin() + 2, N->op_begin() + 2 + NumVecs); | ||||
1704 | |||||
1705 | if (Narrow) | ||||
1706 | transform(Regs, Regs.begin(), | ||||
1707 | WidenVector(*CurDAG)); | ||||
1708 | |||||
1709 | SDValue RegSeq = createQTuple(Regs); | ||||
1710 | |||||
1711 | unsigned LaneNo = | ||||
1712 | cast<ConstantSDNode>(N->getOperand(NumVecs + 2))->getZExtValue(); | ||||
1713 | |||||
1714 | SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64), | ||||
1715 | N->getOperand(NumVecs + 3), N->getOperand(0)}; | ||||
1716 | SDNode *St = CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops); | ||||
1717 | |||||
1718 | // Transfer memoperands. | ||||
1719 | MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); | ||||
1720 | CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp}); | ||||
1721 | |||||
1722 | ReplaceNode(N, St); | ||||
1723 | } | ||||
1724 | |||||
1725 | void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *N, unsigned NumVecs, | ||||
1726 | unsigned Opc) { | ||||
1727 | SDLoc dl(N); | ||||
1728 | EVT VT = N->getOperand(2)->getValueType(0); | ||||
1729 | bool Narrow = VT.getSizeInBits() == 64; | ||||
1730 | |||||
1731 | // Form a REG_SEQUENCE to force register allocation. | ||||
1732 | SmallVector<SDValue, 4> Regs(N->op_begin() + 1, N->op_begin() + 1 + NumVecs); | ||||
1733 | |||||
1734 | if (Narrow) | ||||
1735 | transform(Regs, Regs.begin(), | ||||
1736 | WidenVector(*CurDAG)); | ||||
1737 | |||||
1738 | SDValue RegSeq = createQTuple(Regs); | ||||
1739 | |||||
1740 | const EVT ResTys[] = {MVT::i64, // Type of the write back register | ||||
1741 | MVT::Other}; | ||||
1742 | |||||
1743 | unsigned LaneNo = | ||||
1744 | cast<ConstantSDNode>(N->getOperand(NumVecs + 1))->getZExtValue(); | ||||
1745 | |||||
1746 | SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64), | ||||
1747 | N->getOperand(NumVecs + 2), // Base Register | ||||
1748 | N->getOperand(NumVecs + 3), // Incremental | ||||
1749 | N->getOperand(0)}; | ||||
1750 | SDNode *St = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); | ||||
1751 | |||||
1752 | // Transfer memoperands. | ||||
1753 | MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); | ||||
1754 | CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp}); | ||||
1755 | |||||
1756 | ReplaceNode(N, St); | ||||
1757 | } | ||||
1758 | |||||
1759 | static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N, | ||||
1760 | unsigned &Opc, SDValue &Opd0, | ||||
1761 | unsigned &LSB, unsigned &MSB, | ||||
1762 | unsigned NumberOfIgnoredLowBits, | ||||
1763 | bool BiggerPattern) { | ||||
1764 | assert(N->getOpcode() == ISD::AND &&((N->getOpcode() == ISD::AND && "N must be a AND operation to call this function" ) ? static_cast<void> (0) : __assert_fail ("N->getOpcode() == ISD::AND && \"N must be a AND operation to call this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1765, __PRETTY_FUNCTION__)) | ||||
1765 | "N must be a AND operation to call this function")((N->getOpcode() == ISD::AND && "N must be a AND operation to call this function" ) ? static_cast<void> (0) : __assert_fail ("N->getOpcode() == ISD::AND && \"N must be a AND operation to call this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1765, __PRETTY_FUNCTION__)); | ||||
1766 | |||||
1767 | EVT VT = N->getValueType(0); | ||||
1768 | |||||
1769 | // Here we can test the type of VT and return false when the type does not | ||||
1770 | // match, but since it is done prior to that call in the current context | ||||
1771 | // we turned that into an assert to avoid redundant code. | ||||
1772 | assert((VT == MVT::i32 || VT == MVT::i64) &&(((VT == MVT::i32 || VT == MVT::i64) && "Type checking must have been done before calling this function" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"Type checking must have been done before calling this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1773, __PRETTY_FUNCTION__)) | ||||
1773 | "Type checking must have been done before calling this function")(((VT == MVT::i32 || VT == MVT::i64) && "Type checking must have been done before calling this function" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"Type checking must have been done before calling this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1773, __PRETTY_FUNCTION__)); | ||||
1774 | |||||
1775 | // FIXME: simplify-demanded-bits in DAGCombine will probably have | ||||
1776 | // changed the AND node to a 32-bit mask operation. We'll have to | ||||
1777 | // undo that as part of the transform here if we want to catch all | ||||
1778 | // the opportunities. | ||||
1779 | // Currently the NumberOfIgnoredLowBits argument helps to recover | ||||
1780 | // form these situations when matching bigger pattern (bitfield insert). | ||||
1781 | |||||
1782 | // For unsigned extracts, check for a shift right and mask | ||||
1783 | uint64_t AndImm = 0; | ||||
1784 | if (!isOpcWithIntImmediate(N, ISD::AND, AndImm)) | ||||
1785 | return false; | ||||
1786 | |||||
1787 | const SDNode *Op0 = N->getOperand(0).getNode(); | ||||
1788 | |||||
1789 | // Because of simplify-demanded-bits in DAGCombine, the mask may have been | ||||
1790 | // simplified. Try to undo that | ||||
1791 | AndImm |= maskTrailingOnes<uint64_t>(NumberOfIgnoredLowBits); | ||||
1792 | |||||
1793 | // The immediate is a mask of the low bits iff imm & (imm+1) == 0 | ||||
1794 | if (AndImm & (AndImm + 1)) | ||||
1795 | return false; | ||||
1796 | |||||
1797 | bool ClampMSB = false; | ||||
1798 | uint64_t SrlImm = 0; | ||||
1799 | // Handle the SRL + ANY_EXTEND case. | ||||
1800 | if (VT == MVT::i64 && Op0->getOpcode() == ISD::ANY_EXTEND && | ||||
1801 | isOpcWithIntImmediate(Op0->getOperand(0).getNode(), ISD::SRL, SrlImm)) { | ||||
1802 | // Extend the incoming operand of the SRL to 64-bit. | ||||
1803 | Opd0 = Widen(CurDAG, Op0->getOperand(0).getOperand(0)); | ||||
1804 | // Make sure to clamp the MSB so that we preserve the semantics of the | ||||
1805 | // original operations. | ||||
1806 | ClampMSB = true; | ||||
1807 | } else if (VT == MVT::i32 && Op0->getOpcode() == ISD::TRUNCATE && | ||||
1808 | isOpcWithIntImmediate(Op0->getOperand(0).getNode(), ISD::SRL, | ||||
1809 | SrlImm)) { | ||||
1810 | // If the shift result was truncated, we can still combine them. | ||||
1811 | Opd0 = Op0->getOperand(0).getOperand(0); | ||||
1812 | |||||
1813 | // Use the type of SRL node. | ||||
1814 | VT = Opd0->getValueType(0); | ||||
1815 | } else if (isOpcWithIntImmediate(Op0, ISD::SRL, SrlImm)) { | ||||
1816 | Opd0 = Op0->getOperand(0); | ||||
1817 | } else if (BiggerPattern) { | ||||
1818 | // Let's pretend a 0 shift right has been performed. | ||||
1819 | // The resulting code will be at least as good as the original one | ||||
1820 | // plus it may expose more opportunities for bitfield insert pattern. | ||||
1821 | // FIXME: Currently we limit this to the bigger pattern, because | ||||
1822 | // some optimizations expect AND and not UBFM. | ||||
1823 | Opd0 = N->getOperand(0); | ||||
1824 | } else | ||||
1825 | return false; | ||||
1826 | |||||
1827 | // Bail out on large immediates. This happens when no proper | ||||
1828 | // combining/constant folding was performed. | ||||
1829 | if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.getSizeInBits())) { | ||||
1830 | LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("aarch64-isel")) { (dbgs() << N << ": Found large shift immediate, this should not happen\n" ); } } while (false) | ||||
1831 | (dbgs() << Ndo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("aarch64-isel")) { (dbgs() << N << ": Found large shift immediate, this should not happen\n" ); } } while (false) | ||||
1832 | << ": Found large shift immediate, this should not happen\n"))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("aarch64-isel")) { (dbgs() << N << ": Found large shift immediate, this should not happen\n" ); } } while (false); | ||||
1833 | return false; | ||||
1834 | } | ||||
1835 | |||||
1836 | LSB = SrlImm; | ||||
1837 | MSB = SrlImm + (VT == MVT::i32 ? countTrailingOnes<uint32_t>(AndImm) | ||||
1838 | : countTrailingOnes<uint64_t>(AndImm)) - | ||||
1839 | 1; | ||||
1840 | if (ClampMSB) | ||||
1841 | // Since we're moving the extend before the right shift operation, we need | ||||
1842 | // to clamp the MSB to make sure we don't shift in undefined bits instead of | ||||
1843 | // the zeros which would get shifted in with the original right shift | ||||
1844 | // operation. | ||||
1845 | MSB = MSB > 31 ? 31 : MSB; | ||||
1846 | |||||
1847 | Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri; | ||||
1848 | return true; | ||||
1849 | } | ||||
1850 | |||||
1851 | static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc, | ||||
1852 | SDValue &Opd0, unsigned &Immr, | ||||
1853 | unsigned &Imms) { | ||||
1854 | assert(N->getOpcode() == ISD::SIGN_EXTEND_INREG)((N->getOpcode() == ISD::SIGN_EXTEND_INREG) ? static_cast< void> (0) : __assert_fail ("N->getOpcode() == ISD::SIGN_EXTEND_INREG" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1854, __PRETTY_FUNCTION__)); | ||||
1855 | |||||
1856 | EVT VT = N->getValueType(0); | ||||
1857 | unsigned BitWidth = VT.getSizeInBits(); | ||||
1858 | assert((VT == MVT::i32 || VT == MVT::i64) &&(((VT == MVT::i32 || VT == MVT::i64) && "Type checking must have been done before calling this function" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"Type checking must have been done before calling this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1859, __PRETTY_FUNCTION__)) | ||||
1859 | "Type checking must have been done before calling this function")(((VT == MVT::i32 || VT == MVT::i64) && "Type checking must have been done before calling this function" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"Type checking must have been done before calling this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1859, __PRETTY_FUNCTION__)); | ||||
1860 | |||||
1861 | SDValue Op = N->getOperand(0); | ||||
1862 | if (Op->getOpcode() == ISD::TRUNCATE) { | ||||
1863 | Op = Op->getOperand(0); | ||||
1864 | VT = Op->getValueType(0); | ||||
1865 | BitWidth = VT.getSizeInBits(); | ||||
1866 | } | ||||
1867 | |||||
1868 | uint64_t ShiftImm; | ||||
1869 | if (!isOpcWithIntImmediate(Op.getNode(), ISD::SRL, ShiftImm) && | ||||
1870 | !isOpcWithIntImmediate(Op.getNode(), ISD::SRA, ShiftImm)) | ||||
1871 | return false; | ||||
1872 | |||||
1873 | unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits(); | ||||
1874 | if (ShiftImm + Width > BitWidth) | ||||
1875 | return false; | ||||
1876 | |||||
1877 | Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri; | ||||
1878 | Opd0 = Op.getOperand(0); | ||||
1879 | Immr = ShiftImm; | ||||
1880 | Imms = ShiftImm + Width - 1; | ||||
1881 | return true; | ||||
1882 | } | ||||
1883 | |||||
1884 | static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc, | ||||
1885 | SDValue &Opd0, unsigned &LSB, | ||||
1886 | unsigned &MSB) { | ||||
1887 | // We are looking for the following pattern which basically extracts several | ||||
1888 | // continuous bits from the source value and places it from the LSB of the | ||||
1889 | // destination value, all other bits of the destination value or set to zero: | ||||
1890 | // | ||||
1891 | // Value2 = AND Value, MaskImm | ||||
1892 | // SRL Value2, ShiftImm | ||||
1893 | // | ||||
1894 | // with MaskImm >> ShiftImm to search for the bit width. | ||||
1895 | // | ||||
1896 | // This gets selected into a single UBFM: | ||||
1897 | // | ||||
1898 | // UBFM Value, ShiftImm, BitWide + SrlImm -1 | ||||
1899 | // | ||||
1900 | |||||
1901 | if (N->getOpcode() != ISD::SRL) | ||||
1902 | return false; | ||||
1903 | |||||
1904 | uint64_t AndMask = 0; | ||||
1905 | if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, AndMask)) | ||||
1906 | return false; | ||||
1907 | |||||
1908 | Opd0 = N->getOperand(0).getOperand(0); | ||||
1909 | |||||
1910 | uint64_t SrlImm = 0; | ||||
1911 | if (!isIntImmediate(N->getOperand(1), SrlImm)) | ||||
1912 | return false; | ||||
1913 | |||||
1914 | // Check whether we really have several bits extract here. | ||||
1915 | unsigned BitWide = 64 - countLeadingOnes(~(AndMask >> SrlImm)); | ||||
1916 | if (BitWide && isMask_64(AndMask >> SrlImm)) { | ||||
1917 | if (N->getValueType(0) == MVT::i32) | ||||
1918 | Opc = AArch64::UBFMWri; | ||||
1919 | else | ||||
1920 | Opc = AArch64::UBFMXri; | ||||
1921 | |||||
1922 | LSB = SrlImm; | ||||
1923 | MSB = BitWide + SrlImm - 1; | ||||
1924 | return true; | ||||
1925 | } | ||||
1926 | |||||
1927 | return false; | ||||
1928 | } | ||||
1929 | |||||
1930 | static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, | ||||
1931 | unsigned &Immr, unsigned &Imms, | ||||
1932 | bool BiggerPattern) { | ||||
1933 | assert((N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL) &&(((N->getOpcode() == ISD::SRA || N->getOpcode() == ISD:: SRL) && "N must be a SHR/SRA operation to call this function" ) ? static_cast<void> (0) : __assert_fail ("(N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL) && \"N must be a SHR/SRA operation to call this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1934, __PRETTY_FUNCTION__)) | ||||
1934 | "N must be a SHR/SRA operation to call this function")(((N->getOpcode() == ISD::SRA || N->getOpcode() == ISD:: SRL) && "N must be a SHR/SRA operation to call this function" ) ? static_cast<void> (0) : __assert_fail ("(N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL) && \"N must be a SHR/SRA operation to call this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1934, __PRETTY_FUNCTION__)); | ||||
1935 | |||||
1936 | EVT VT = N->getValueType(0); | ||||
1937 | |||||
1938 | // Here we can test the type of VT and return false when the type does not | ||||
1939 | // match, but since it is done prior to that call in the current context | ||||
1940 | // we turned that into an assert to avoid redundant code. | ||||
1941 | assert((VT == MVT::i32 || VT == MVT::i64) &&(((VT == MVT::i32 || VT == MVT::i64) && "Type checking must have been done before calling this function" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"Type checking must have been done before calling this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1942, __PRETTY_FUNCTION__)) | ||||
1942 | "Type checking must have been done before calling this function")(((VT == MVT::i32 || VT == MVT::i64) && "Type checking must have been done before calling this function" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"Type checking must have been done before calling this function\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1942, __PRETTY_FUNCTION__)); | ||||
1943 | |||||
1944 | // Check for AND + SRL doing several bits extract. | ||||
1945 | if (isSeveralBitsExtractOpFromShr(N, Opc, Opd0, Immr, Imms)) | ||||
1946 | return true; | ||||
1947 | |||||
1948 | // We're looking for a shift of a shift. | ||||
1949 | uint64_t ShlImm = 0; | ||||
1950 | uint64_t TruncBits = 0; | ||||
1951 | if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, ShlImm)) { | ||||
1952 | Opd0 = N->getOperand(0).getOperand(0); | ||||
1953 | } else if (VT == MVT::i32 && N->getOpcode() == ISD::SRL && | ||||
1954 | N->getOperand(0).getNode()->getOpcode() == ISD::TRUNCATE) { | ||||
1955 | // We are looking for a shift of truncate. Truncate from i64 to i32 could | ||||
1956 | // be considered as setting high 32 bits as zero. Our strategy here is to | ||||
1957 | // always generate 64bit UBFM. This consistency will help the CSE pass | ||||
1958 | // later find more redundancy. | ||||
1959 | Opd0 = N->getOperand(0).getOperand(0); | ||||
1960 | TruncBits = Opd0->getValueType(0).getSizeInBits() - VT.getSizeInBits(); | ||||
1961 | VT = Opd0.getValueType(); | ||||
1962 | assert(VT == MVT::i64 && "the promoted type should be i64")((VT == MVT::i64 && "the promoted type should be i64" ) ? static_cast<void> (0) : __assert_fail ("VT == MVT::i64 && \"the promoted type should be i64\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1962, __PRETTY_FUNCTION__)); | ||||
1963 | } else if (BiggerPattern) { | ||||
1964 | // Let's pretend a 0 shift left has been performed. | ||||
1965 | // FIXME: Currently we limit this to the bigger pattern case, | ||||
1966 | // because some optimizations expect AND and not UBFM | ||||
1967 | Opd0 = N->getOperand(0); | ||||
1968 | } else | ||||
1969 | return false; | ||||
1970 | |||||
1971 | // Missing combines/constant folding may have left us with strange | ||||
1972 | // constants. | ||||
1973 | if (ShlImm >= VT.getSizeInBits()) { | ||||
1974 | LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("aarch64-isel")) { (dbgs() << N << ": Found large shift immediate, this should not happen\n" ); } } while (false) | ||||
1975 | (dbgs() << Ndo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("aarch64-isel")) { (dbgs() << N << ": Found large shift immediate, this should not happen\n" ); } } while (false) | ||||
1976 | << ": Found large shift immediate, this should not happen\n"))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("aarch64-isel")) { (dbgs() << N << ": Found large shift immediate, this should not happen\n" ); } } while (false); | ||||
1977 | return false; | ||||
1978 | } | ||||
1979 | |||||
1980 | uint64_t SrlImm = 0; | ||||
1981 | if (!isIntImmediate(N->getOperand(1), SrlImm)) | ||||
1982 | return false; | ||||
1983 | |||||
1984 | assert(SrlImm > 0 && SrlImm < VT.getSizeInBits() &&((SrlImm > 0 && SrlImm < VT.getSizeInBits() && "bad amount in shift node!") ? static_cast<void> (0) : __assert_fail ("SrlImm > 0 && SrlImm < VT.getSizeInBits() && \"bad amount in shift node!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1985, __PRETTY_FUNCTION__)) | ||||
1985 | "bad amount in shift node!")((SrlImm > 0 && SrlImm < VT.getSizeInBits() && "bad amount in shift node!") ? static_cast<void> (0) : __assert_fail ("SrlImm > 0 && SrlImm < VT.getSizeInBits() && \"bad amount in shift node!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1985, __PRETTY_FUNCTION__)); | ||||
1986 | int immr = SrlImm - ShlImm; | ||||
1987 | Immr = immr < 0 ? immr + VT.getSizeInBits() : immr; | ||||
1988 | Imms = VT.getSizeInBits() - ShlImm - TruncBits - 1; | ||||
1989 | // SRA requires a signed extraction | ||||
1990 | if (VT == MVT::i32) | ||||
1991 | Opc = N->getOpcode() == ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri; | ||||
1992 | else | ||||
1993 | Opc = N->getOpcode() == ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri; | ||||
1994 | return true; | ||||
1995 | } | ||||
1996 | |||||
1997 | bool AArch64DAGToDAGISel::tryBitfieldExtractOpFromSExt(SDNode *N) { | ||||
1998 | assert(N->getOpcode() == ISD::SIGN_EXTEND)((N->getOpcode() == ISD::SIGN_EXTEND) ? static_cast<void > (0) : __assert_fail ("N->getOpcode() == ISD::SIGN_EXTEND" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 1998, __PRETTY_FUNCTION__)); | ||||
1999 | |||||
2000 | EVT VT = N->getValueType(0); | ||||
2001 | EVT NarrowVT = N->getOperand(0)->getValueType(0); | ||||
2002 | if (VT != MVT::i64 || NarrowVT != MVT::i32) | ||||
2003 | return false; | ||||
2004 | |||||
2005 | uint64_t ShiftImm; | ||||
2006 | SDValue Op = N->getOperand(0); | ||||
2007 | if (!isOpcWithIntImmediate(Op.getNode(), ISD::SRA, ShiftImm)) | ||||
2008 | return false; | ||||
2009 | |||||
2010 | SDLoc dl(N); | ||||
2011 | // Extend the incoming operand of the shift to 64-bits. | ||||
2012 | SDValue Opd0 = Widen(CurDAG, Op.getOperand(0)); | ||||
2013 | unsigned Immr = ShiftImm; | ||||
2014 | unsigned Imms = NarrowVT.getSizeInBits() - 1; | ||||
2015 | SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT), | ||||
2016 | CurDAG->getTargetConstant(Imms, dl, VT)}; | ||||
2017 | CurDAG->SelectNodeTo(N, AArch64::SBFMXri, VT, Ops); | ||||
2018 | return true; | ||||
2019 | } | ||||
2020 | |||||
2021 | /// Try to form fcvtl2 instructions from a floating-point extend of a high-half | ||||
2022 | /// extract of a subvector. | ||||
2023 | bool AArch64DAGToDAGISel::tryHighFPExt(SDNode *N) { | ||||
2024 | assert(N->getOpcode() == ISD::FP_EXTEND)((N->getOpcode() == ISD::FP_EXTEND) ? static_cast<void> (0) : __assert_fail ("N->getOpcode() == ISD::FP_EXTEND", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2024, __PRETTY_FUNCTION__)); | ||||
2025 | |||||
2026 | // There are 2 forms of fcvtl2 - extend to double or extend to float. | ||||
2027 | SDValue Extract = N->getOperand(0); | ||||
2028 | EVT VT = N->getValueType(0); | ||||
2029 | EVT NarrowVT = Extract.getValueType(); | ||||
2030 | if ((VT != MVT::v2f64 || NarrowVT != MVT::v2f32) && | ||||
2031 | (VT != MVT::v4f32 || NarrowVT != MVT::v4f16)) | ||||
2032 | return false; | ||||
2033 | |||||
2034 | // Optionally look past a bitcast. | ||||
2035 | Extract = peekThroughBitcasts(Extract); | ||||
2036 | if (Extract.getOpcode() != ISD::EXTRACT_SUBVECTOR) | ||||
2037 | return false; | ||||
2038 | |||||
2039 | // Match extract from start of high half index. | ||||
2040 | // Example: v8i16 -> v4i16 means the extract must begin at index 4. | ||||
2041 | unsigned ExtractIndex = Extract.getConstantOperandVal(1); | ||||
2042 | if (ExtractIndex != Extract.getValueType().getVectorNumElements()) | ||||
2043 | return false; | ||||
2044 | |||||
2045 | auto Opcode = VT == MVT::v2f64 ? AArch64::FCVTLv4i32 : AArch64::FCVTLv8i16; | ||||
2046 | CurDAG->SelectNodeTo(N, Opcode, VT, Extract.getOperand(0)); | ||||
2047 | return true; | ||||
2048 | } | ||||
2049 | |||||
2050 | static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, | ||||
2051 | SDValue &Opd0, unsigned &Immr, unsigned &Imms, | ||||
2052 | unsigned NumberOfIgnoredLowBits = 0, | ||||
2053 | bool BiggerPattern = false) { | ||||
2054 | if (N->getValueType(0) != MVT::i32 && N->getValueType(0) != MVT::i64) | ||||
2055 | return false; | ||||
2056 | |||||
2057 | switch (N->getOpcode()) { | ||||
2058 | default: | ||||
2059 | if (!N->isMachineOpcode()) | ||||
2060 | return false; | ||||
2061 | break; | ||||
2062 | case ISD::AND: | ||||
2063 | return isBitfieldExtractOpFromAnd(CurDAG, N, Opc, Opd0, Immr, Imms, | ||||
2064 | NumberOfIgnoredLowBits, BiggerPattern); | ||||
2065 | case ISD::SRL: | ||||
2066 | case ISD::SRA: | ||||
2067 | return isBitfieldExtractOpFromShr(N, Opc, Opd0, Immr, Imms, BiggerPattern); | ||||
2068 | |||||
2069 | case ISD::SIGN_EXTEND_INREG: | ||||
2070 | return isBitfieldExtractOpFromSExtInReg(N, Opc, Opd0, Immr, Imms); | ||||
2071 | } | ||||
2072 | |||||
2073 | unsigned NOpc = N->getMachineOpcode(); | ||||
2074 | switch (NOpc) { | ||||
2075 | default: | ||||
2076 | return false; | ||||
2077 | case AArch64::SBFMWri: | ||||
2078 | case AArch64::UBFMWri: | ||||
2079 | case AArch64::SBFMXri: | ||||
2080 | case AArch64::UBFMXri: | ||||
2081 | Opc = NOpc; | ||||
2082 | Opd0 = N->getOperand(0); | ||||
2083 | Immr = cast<ConstantSDNode>(N->getOperand(1).getNode())->getZExtValue(); | ||||
2084 | Imms = cast<ConstantSDNode>(N->getOperand(2).getNode())->getZExtValue(); | ||||
2085 | return true; | ||||
2086 | } | ||||
2087 | // Unreachable | ||||
2088 | return false; | ||||
2089 | } | ||||
2090 | |||||
2091 | bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *N) { | ||||
2092 | unsigned Opc, Immr, Imms; | ||||
2093 | SDValue Opd0; | ||||
2094 | if (!isBitfieldExtractOp(CurDAG, N, Opc, Opd0, Immr, Imms)) | ||||
2095 | return false; | ||||
2096 | |||||
2097 | EVT VT = N->getValueType(0); | ||||
2098 | SDLoc dl(N); | ||||
2099 | |||||
2100 | // If the bit extract operation is 64bit but the original type is 32bit, we | ||||
2101 | // need to add one EXTRACT_SUBREG. | ||||
2102 | if ((Opc == AArch64::SBFMXri || Opc == AArch64::UBFMXri) && VT == MVT::i32) { | ||||
2103 | SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64), | ||||
2104 | CurDAG->getTargetConstant(Imms, dl, MVT::i64)}; | ||||
2105 | |||||
2106 | SDNode *BFM = CurDAG->getMachineNode(Opc, dl, MVT::i64, Ops64); | ||||
2107 | SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32); | ||||
2108 | ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, | ||||
2109 | MVT::i32, SDValue(BFM, 0), SubReg)); | ||||
2110 | return true; | ||||
2111 | } | ||||
2112 | |||||
2113 | SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT), | ||||
2114 | CurDAG->getTargetConstant(Imms, dl, VT)}; | ||||
2115 | CurDAG->SelectNodeTo(N, Opc, VT, Ops); | ||||
2116 | return true; | ||||
2117 | } | ||||
2118 | |||||
2119 | /// Does DstMask form a complementary pair with the mask provided by | ||||
2120 | /// BitsToBeInserted, suitable for use in a BFI instruction. Roughly speaking, | ||||
2121 | /// this asks whether DstMask zeroes precisely those bits that will be set by | ||||
2122 | /// the other half. | ||||
2123 | static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted, | ||||
2124 | unsigned NumberOfIgnoredHighBits, EVT VT) { | ||||
2125 | assert((VT == MVT::i32 || VT == MVT::i64) &&(((VT == MVT::i32 || VT == MVT::i64) && "i32 or i64 mask type expected!" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"i32 or i64 mask type expected!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2126, __PRETTY_FUNCTION__)) | ||||
2126 | "i32 or i64 mask type expected!")(((VT == MVT::i32 || VT == MVT::i64) && "i32 or i64 mask type expected!" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"i32 or i64 mask type expected!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2126, __PRETTY_FUNCTION__)); | ||||
2127 | unsigned BitWidth = VT.getSizeInBits() - NumberOfIgnoredHighBits; | ||||
2128 | |||||
2129 | APInt SignificantDstMask = APInt(BitWidth, DstMask); | ||||
2130 | APInt SignificantBitsToBeInserted = BitsToBeInserted.zextOrTrunc(BitWidth); | ||||
2131 | |||||
2132 | return (SignificantDstMask & SignificantBitsToBeInserted) == 0 && | ||||
2133 | (SignificantDstMask | SignificantBitsToBeInserted).isAllOnesValue(); | ||||
2134 | } | ||||
2135 | |||||
2136 | // Look for bits that will be useful for later uses. | ||||
2137 | // A bit is consider useless as soon as it is dropped and never used | ||||
2138 | // before it as been dropped. | ||||
2139 | // E.g., looking for useful bit of x | ||||
2140 | // 1. y = x & 0x7 | ||||
2141 | // 2. z = y >> 2 | ||||
2142 | // After #1, x useful bits are 0x7, then the useful bits of x, live through | ||||
2143 | // y. | ||||
2144 | // After #2, the useful bits of x are 0x4. | ||||
2145 | // However, if x is used on an unpredicatable instruction, then all its bits | ||||
2146 | // are useful. | ||||
2147 | // E.g. | ||||
2148 | // 1. y = x & 0x7 | ||||
2149 | // 2. z = y >> 2 | ||||
2150 | // 3. str x, [@x] | ||||
2151 | static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth = 0); | ||||
2152 | |||||
2153 | static void getUsefulBitsFromAndWithImmediate(SDValue Op, APInt &UsefulBits, | ||||
2154 | unsigned Depth) { | ||||
2155 | uint64_t Imm = | ||||
2156 | cast<const ConstantSDNode>(Op.getOperand(1).getNode())->getZExtValue(); | ||||
2157 | Imm = AArch64_AM::decodeLogicalImmediate(Imm, UsefulBits.getBitWidth()); | ||||
2158 | UsefulBits &= APInt(UsefulBits.getBitWidth(), Imm); | ||||
2159 | getUsefulBits(Op, UsefulBits, Depth + 1); | ||||
2160 | } | ||||
2161 | |||||
2162 | static void getUsefulBitsFromBitfieldMoveOpd(SDValue Op, APInt &UsefulBits, | ||||
2163 | uint64_t Imm, uint64_t MSB, | ||||
2164 | unsigned Depth) { | ||||
2165 | // inherit the bitwidth value | ||||
2166 | APInt OpUsefulBits(UsefulBits); | ||||
2167 | OpUsefulBits = 1; | ||||
2168 | |||||
2169 | if (MSB >= Imm) { | ||||
2170 | OpUsefulBits <<= MSB - Imm + 1; | ||||
2171 | --OpUsefulBits; | ||||
2172 | // The interesting part will be in the lower part of the result | ||||
2173 | getUsefulBits(Op, OpUsefulBits, Depth + 1); | ||||
2174 | // The interesting part was starting at Imm in the argument | ||||
2175 | OpUsefulBits <<= Imm; | ||||
2176 | } else { | ||||
2177 | OpUsefulBits <<= MSB + 1; | ||||
2178 | --OpUsefulBits; | ||||
2179 | // The interesting part will be shifted in the result | ||||
2180 | OpUsefulBits <<= OpUsefulBits.getBitWidth() - Imm; | ||||
2181 | getUsefulBits(Op, OpUsefulBits, Depth + 1); | ||||
2182 | // The interesting part was at zero in the argument | ||||
2183 | OpUsefulBits.lshrInPlace(OpUsefulBits.getBitWidth() - Imm); | ||||
2184 | } | ||||
2185 | |||||
2186 | UsefulBits &= OpUsefulBits; | ||||
2187 | } | ||||
2188 | |||||
2189 | static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits, | ||||
2190 | unsigned Depth) { | ||||
2191 | uint64_t Imm = | ||||
2192 | cast<const ConstantSDNode>(Op.getOperand(1).getNode())->getZExtValue(); | ||||
2193 | uint64_t MSB = | ||||
2194 | cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue(); | ||||
2195 | |||||
2196 | getUsefulBitsFromBitfieldMoveOpd(Op, UsefulBits, Imm, MSB, Depth); | ||||
2197 | } | ||||
2198 | |||||
2199 | static void getUsefulBitsFromOrWithShiftedReg(SDValue Op, APInt &UsefulBits, | ||||
2200 | unsigned Depth) { | ||||
2201 | uint64_t ShiftTypeAndValue = | ||||
2202 | cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue(); | ||||
2203 | APInt Mask(UsefulBits); | ||||
2204 | Mask.clearAllBits(); | ||||
2205 | Mask.flipAllBits(); | ||||
2206 | |||||
2207 | if (AArch64_AM::getShiftType(ShiftTypeAndValue) == AArch64_AM::LSL) { | ||||
2208 | // Shift Left | ||||
2209 | uint64_t ShiftAmt = AArch64_AM::getShiftValue(ShiftTypeAndValue); | ||||
2210 | Mask <<= ShiftAmt; | ||||
2211 | getUsefulBits(Op, Mask, Depth + 1); | ||||
2212 | Mask.lshrInPlace(ShiftAmt); | ||||
2213 | } else if (AArch64_AM::getShiftType(ShiftTypeAndValue) == AArch64_AM::LSR) { | ||||
2214 | // Shift Right | ||||
2215 | // We do not handle AArch64_AM::ASR, because the sign will change the | ||||
2216 | // number of useful bits | ||||
2217 | uint64_t ShiftAmt = AArch64_AM::getShiftValue(ShiftTypeAndValue); | ||||
2218 | Mask.lshrInPlace(ShiftAmt); | ||||
2219 | getUsefulBits(Op, Mask, Depth + 1); | ||||
2220 | Mask <<= ShiftAmt; | ||||
2221 | } else | ||||
2222 | return; | ||||
2223 | |||||
2224 | UsefulBits &= Mask; | ||||
2225 | } | ||||
2226 | |||||
2227 | static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits, | ||||
2228 | unsigned Depth) { | ||||
2229 | uint64_t Imm = | ||||
2230 | cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue(); | ||||
2231 | uint64_t MSB = | ||||
2232 | cast<const ConstantSDNode>(Op.getOperand(3).getNode())->getZExtValue(); | ||||
2233 | |||||
2234 | APInt OpUsefulBits(UsefulBits); | ||||
2235 | OpUsefulBits = 1; | ||||
2236 | |||||
2237 | APInt ResultUsefulBits(UsefulBits.getBitWidth(), 0); | ||||
2238 | ResultUsefulBits.flipAllBits(); | ||||
2239 | APInt Mask(UsefulBits.getBitWidth(), 0); | ||||
2240 | |||||
2241 | getUsefulBits(Op, ResultUsefulBits, Depth + 1); | ||||
2242 | |||||
2243 | if (MSB >= Imm) { | ||||
2244 | // The instruction is a BFXIL. | ||||
2245 | uint64_t Width = MSB - Imm + 1; | ||||
2246 | uint64_t LSB = Imm; | ||||
2247 | |||||
2248 | OpUsefulBits <<= Width; | ||||
2249 | --OpUsefulBits; | ||||
2250 | |||||
2251 | if (Op.getOperand(1) == Orig) { | ||||
2252 | // Copy the low bits from the result to bits starting from LSB. | ||||
2253 | Mask = ResultUsefulBits & OpUsefulBits; | ||||
2254 | Mask <<= LSB; | ||||
2255 | } | ||||
2256 | |||||
2257 | if (Op.getOperand(0) == Orig) | ||||
2258 | // Bits starting from LSB in the input contribute to the result. | ||||
2259 | Mask |= (ResultUsefulBits & ~OpUsefulBits); | ||||
2260 | } else { | ||||
2261 | // The instruction is a BFI. | ||||
2262 | uint64_t Width = MSB + 1; | ||||
2263 | uint64_t LSB = UsefulBits.getBitWidth() - Imm; | ||||
2264 | |||||
2265 | OpUsefulBits <<= Width; | ||||
2266 | --OpUsefulBits; | ||||
2267 | OpUsefulBits <<= LSB; | ||||
2268 | |||||
2269 | if (Op.getOperand(1) == Orig) { | ||||
2270 | // Copy the bits from the result to the zero bits. | ||||
2271 | Mask = ResultUsefulBits & OpUsefulBits; | ||||
2272 | Mask.lshrInPlace(LSB); | ||||
2273 | } | ||||
2274 | |||||
2275 | if (Op.getOperand(0) == Orig) | ||||
2276 | Mask |= (ResultUsefulBits & ~OpUsefulBits); | ||||
2277 | } | ||||
2278 | |||||
2279 | UsefulBits &= Mask; | ||||
2280 | } | ||||
2281 | |||||
2282 | static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits, | ||||
2283 | SDValue Orig, unsigned Depth) { | ||||
2284 | |||||
2285 | // Users of this node should have already been instruction selected | ||||
2286 | // FIXME: Can we turn that into an assert? | ||||
2287 | if (!UserNode->isMachineOpcode()) | ||||
2288 | return; | ||||
2289 | |||||
2290 | switch (UserNode->getMachineOpcode()) { | ||||
2291 | default: | ||||
2292 | return; | ||||
2293 | case AArch64::ANDSWri: | ||||
2294 | case AArch64::ANDSXri: | ||||
2295 | case AArch64::ANDWri: | ||||
2296 | case AArch64::ANDXri: | ||||
2297 | // We increment Depth only when we call the getUsefulBits | ||||
2298 | return getUsefulBitsFromAndWithImmediate(SDValue(UserNode, 0), UsefulBits, | ||||
2299 | Depth); | ||||
2300 | case AArch64::UBFMWri: | ||||
2301 | case AArch64::UBFMXri: | ||||
2302 | return getUsefulBitsFromUBFM(SDValue(UserNode, 0), UsefulBits, Depth); | ||||
2303 | |||||
2304 | case AArch64::ORRWrs: | ||||
2305 | case AArch64::ORRXrs: | ||||
2306 | if (UserNode->getOperand(1) != Orig) | ||||
2307 | return; | ||||
2308 | return getUsefulBitsFromOrWithShiftedReg(SDValue(UserNode, 0), UsefulBits, | ||||
2309 | Depth); | ||||
2310 | case AArch64::BFMWri: | ||||
2311 | case AArch64::BFMXri: | ||||
2312 | return getUsefulBitsFromBFM(SDValue(UserNode, 0), Orig, UsefulBits, Depth); | ||||
2313 | |||||
2314 | case AArch64::STRBBui: | ||||
2315 | case AArch64::STURBBi: | ||||
2316 | if (UserNode->getOperand(0) != Orig) | ||||
2317 | return; | ||||
2318 | UsefulBits &= APInt(UsefulBits.getBitWidth(), 0xff); | ||||
2319 | return; | ||||
2320 | |||||
2321 | case AArch64::STRHHui: | ||||
2322 | case AArch64::STURHHi: | ||||
2323 | if (UserNode->getOperand(0) != Orig) | ||||
2324 | return; | ||||
2325 | UsefulBits &= APInt(UsefulBits.getBitWidth(), 0xffff); | ||||
2326 | return; | ||||
2327 | } | ||||
2328 | } | ||||
2329 | |||||
2330 | static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth) { | ||||
2331 | if (Depth >= SelectionDAG::MaxRecursionDepth) | ||||
2332 | return; | ||||
2333 | // Initialize UsefulBits | ||||
2334 | if (!Depth) { | ||||
2335 | unsigned Bitwidth = Op.getScalarValueSizeInBits(); | ||||
2336 | // At the beginning, assume every produced bits is useful | ||||
2337 | UsefulBits = APInt(Bitwidth, 0); | ||||
2338 | UsefulBits.flipAllBits(); | ||||
2339 | } | ||||
2340 | APInt UsersUsefulBits(UsefulBits.getBitWidth(), 0); | ||||
2341 | |||||
2342 | for (SDNode *Node : Op.getNode()->uses()) { | ||||
2343 | // A use cannot produce useful bits | ||||
2344 | APInt UsefulBitsForUse = APInt(UsefulBits); | ||||
2345 | getUsefulBitsForUse(Node, UsefulBitsForUse, Op, Depth); | ||||
2346 | UsersUsefulBits |= UsefulBitsForUse; | ||||
2347 | } | ||||
2348 | // UsefulBits contains the produced bits that are meaningful for the | ||||
2349 | // current definition, thus a user cannot make a bit meaningful at | ||||
2350 | // this point | ||||
2351 | UsefulBits &= UsersUsefulBits; | ||||
2352 | } | ||||
2353 | |||||
2354 | /// Create a machine node performing a notional SHL of Op by ShlAmount. If | ||||
2355 | /// ShlAmount is negative, do a (logical) right-shift instead. If ShlAmount is | ||||
2356 | /// 0, return Op unchanged. | ||||
2357 | static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount) { | ||||
2358 | if (ShlAmount == 0) | ||||
2359 | return Op; | ||||
2360 | |||||
2361 | EVT VT = Op.getValueType(); | ||||
2362 | SDLoc dl(Op); | ||||
2363 | unsigned BitWidth = VT.getSizeInBits(); | ||||
2364 | unsigned UBFMOpc = BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri; | ||||
2365 | |||||
2366 | SDNode *ShiftNode; | ||||
2367 | if (ShlAmount > 0) { | ||||
2368 | // LSL wD, wN, #Amt == UBFM wD, wN, #32-Amt, #31-Amt | ||||
2369 | ShiftNode = CurDAG->getMachineNode( | ||||
2370 | UBFMOpc, dl, VT, Op, | ||||
2371 | CurDAG->getTargetConstant(BitWidth - ShlAmount, dl, VT), | ||||
2372 | CurDAG->getTargetConstant(BitWidth - 1 - ShlAmount, dl, VT)); | ||||
2373 | } else { | ||||
2374 | // LSR wD, wN, #Amt == UBFM wD, wN, #Amt, #32-1 | ||||
2375 | assert(ShlAmount < 0 && "expected right shift")((ShlAmount < 0 && "expected right shift") ? static_cast <void> (0) : __assert_fail ("ShlAmount < 0 && \"expected right shift\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2375, __PRETTY_FUNCTION__)); | ||||
2376 | int ShrAmount = -ShlAmount; | ||||
2377 | ShiftNode = CurDAG->getMachineNode( | ||||
2378 | UBFMOpc, dl, VT, Op, CurDAG->getTargetConstant(ShrAmount, dl, VT), | ||||
2379 | CurDAG->getTargetConstant(BitWidth - 1, dl, VT)); | ||||
2380 | } | ||||
2381 | |||||
2382 | return SDValue(ShiftNode, 0); | ||||
2383 | } | ||||
2384 | |||||
2385 | /// Does this tree qualify as an attempt to move a bitfield into position, | ||||
2386 | /// essentially "(and (shl VAL, N), Mask)". | ||||
2387 | static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op, | ||||
2388 | bool BiggerPattern, | ||||
2389 | SDValue &Src, int &ShiftAmount, | ||||
2390 | int &MaskWidth) { | ||||
2391 | EVT VT = Op.getValueType(); | ||||
2392 | unsigned BitWidth = VT.getSizeInBits(); | ||||
2393 | (void)BitWidth; | ||||
2394 | assert(BitWidth == 32 || BitWidth == 64)((BitWidth == 32 || BitWidth == 64) ? static_cast<void> (0) : __assert_fail ("BitWidth == 32 || BitWidth == 64", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2394, __PRETTY_FUNCTION__)); | ||||
2395 | |||||
2396 | KnownBits Known = CurDAG->computeKnownBits(Op); | ||||
2397 | |||||
2398 | // Non-zero in the sense that they're not provably zero, which is the key | ||||
2399 | // point if we want to use this value | ||||
2400 | uint64_t NonZeroBits = (~Known.Zero).getZExtValue(); | ||||
2401 | |||||
2402 | // Discard a constant AND mask if present. It's safe because the node will | ||||
2403 | // already have been factored into the computeKnownBits calculation above. | ||||
2404 | uint64_t AndImm; | ||||
2405 | if (isOpcWithIntImmediate(Op.getNode(), ISD::AND, AndImm)) { | ||||
2406 | assert((~APInt(BitWidth, AndImm) & ~Known.Zero) == 0)(((~APInt(BitWidth, AndImm) & ~Known.Zero) == 0) ? static_cast <void> (0) : __assert_fail ("(~APInt(BitWidth, AndImm) & ~Known.Zero) == 0" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2406, __PRETTY_FUNCTION__)); | ||||
2407 | Op = Op.getOperand(0); | ||||
2408 | } | ||||
2409 | |||||
2410 | // Don't match if the SHL has more than one use, since then we'll end up | ||||
2411 | // generating SHL+UBFIZ instead of just keeping SHL+AND. | ||||
2412 | if (!BiggerPattern && !Op.hasOneUse()) | ||||
2413 | return false; | ||||
2414 | |||||
2415 | uint64_t ShlImm; | ||||
2416 | if (!isOpcWithIntImmediate(Op.getNode(), ISD::SHL, ShlImm)) | ||||
2417 | return false; | ||||
2418 | Op = Op.getOperand(0); | ||||
2419 | |||||
2420 | if (!isShiftedMask_64(NonZeroBits)) | ||||
2421 | return false; | ||||
2422 | |||||
2423 | ShiftAmount = countTrailingZeros(NonZeroBits); | ||||
2424 | MaskWidth = countTrailingOnes(NonZeroBits >> ShiftAmount); | ||||
2425 | |||||
2426 | // BFI encompasses sufficiently many nodes that it's worth inserting an extra | ||||
2427 | // LSL/LSR if the mask in NonZeroBits doesn't quite match up with the ISD::SHL | ||||
2428 | // amount. BiggerPattern is true when this pattern is being matched for BFI, | ||||
2429 | // BiggerPattern is false when this pattern is being matched for UBFIZ, in | ||||
2430 | // which case it is not profitable to insert an extra shift. | ||||
2431 | if (ShlImm - ShiftAmount != 0 && !BiggerPattern) | ||||
2432 | return false; | ||||
2433 | Src = getLeftShift(CurDAG, Op, ShlImm - ShiftAmount); | ||||
2434 | |||||
2435 | return true; | ||||
2436 | } | ||||
2437 | |||||
2438 | static bool isShiftedMask(uint64_t Mask, EVT VT) { | ||||
2439 | assert(VT == MVT::i32 || VT == MVT::i64)((VT == MVT::i32 || VT == MVT::i64) ? static_cast<void> (0) : __assert_fail ("VT == MVT::i32 || VT == MVT::i64", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2439, __PRETTY_FUNCTION__)); | ||||
2440 | if (VT == MVT::i32) | ||||
2441 | return isShiftedMask_32(Mask); | ||||
2442 | return isShiftedMask_64(Mask); | ||||
2443 | } | ||||
2444 | |||||
2445 | // Generate a BFI/BFXIL from 'or (and X, MaskImm), OrImm' iff the value being | ||||
2446 | // inserted only sets known zero bits. | ||||
2447 | static bool tryBitfieldInsertOpFromOrAndImm(SDNode *N, SelectionDAG *CurDAG) { | ||||
2448 | assert(N->getOpcode() == ISD::OR && "Expect a OR operation")((N->getOpcode() == ISD::OR && "Expect a OR operation" ) ? static_cast<void> (0) : __assert_fail ("N->getOpcode() == ISD::OR && \"Expect a OR operation\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2448, __PRETTY_FUNCTION__)); | ||||
2449 | |||||
2450 | EVT VT = N->getValueType(0); | ||||
2451 | if (VT != MVT::i32 && VT != MVT::i64) | ||||
2452 | return false; | ||||
2453 | |||||
2454 | unsigned BitWidth = VT.getSizeInBits(); | ||||
2455 | |||||
2456 | uint64_t OrImm; | ||||
2457 | if (!isOpcWithIntImmediate(N, ISD::OR, OrImm)) | ||||
2458 | return false; | ||||
2459 | |||||
2460 | // Skip this transformation if the ORR immediate can be encoded in the ORR. | ||||
2461 | // Otherwise, we'll trade an AND+ORR for ORR+BFI/BFXIL, which is most likely | ||||
2462 | // performance neutral. | ||||
2463 | if (AArch64_AM::isLogicalImmediate(OrImm, BitWidth)) | ||||
2464 | return false; | ||||
2465 | |||||
2466 | uint64_t MaskImm; | ||||
2467 | SDValue And = N->getOperand(0); | ||||
2468 | // Must be a single use AND with an immediate operand. | ||||
2469 | if (!And.hasOneUse() || | ||||
2470 | !isOpcWithIntImmediate(And.getNode(), ISD::AND, MaskImm)) | ||||
2471 | return false; | ||||
2472 | |||||
2473 | // Compute the Known Zero for the AND as this allows us to catch more general | ||||
2474 | // cases than just looking for AND with imm. | ||||
2475 | KnownBits Known = CurDAG->computeKnownBits(And); | ||||
2476 | |||||
2477 | // Non-zero in the sense that they're not provably zero, which is the key | ||||
2478 | // point if we want to use this value. | ||||
2479 | uint64_t NotKnownZero = (~Known.Zero).getZExtValue(); | ||||
2480 | |||||
2481 | // The KnownZero mask must be a shifted mask (e.g., 1110..011, 11100..00). | ||||
2482 | if (!isShiftedMask(Known.Zero.getZExtValue(), VT)) | ||||
2483 | return false; | ||||
2484 | |||||
2485 | // The bits being inserted must only set those bits that are known to be zero. | ||||
2486 | if ((OrImm & NotKnownZero) != 0) { | ||||
2487 | // FIXME: It's okay if the OrImm sets NotKnownZero bits to 1, but we don't | ||||
2488 | // currently handle this case. | ||||
2489 | return false; | ||||
2490 | } | ||||
2491 | |||||
2492 | // BFI/BFXIL dst, src, #lsb, #width. | ||||
2493 | int LSB = countTrailingOnes(NotKnownZero); | ||||
2494 | int Width = BitWidth - APInt(BitWidth, NotKnownZero).countPopulation(); | ||||
2495 | |||||
2496 | // BFI/BFXIL is an alias of BFM, so translate to BFM operands. | ||||
2497 | unsigned ImmR = (BitWidth - LSB) % BitWidth; | ||||
2498 | unsigned ImmS = Width - 1; | ||||
2499 | |||||
2500 | // If we're creating a BFI instruction avoid cases where we need more | ||||
2501 | // instructions to materialize the BFI constant as compared to the original | ||||
2502 | // ORR. A BFXIL will use the same constant as the original ORR, so the code | ||||
2503 | // should be no worse in this case. | ||||
2504 | bool IsBFI = LSB != 0; | ||||
2505 | uint64_t BFIImm = OrImm >> LSB; | ||||
2506 | if (IsBFI && !AArch64_AM::isLogicalImmediate(BFIImm, BitWidth)) { | ||||
2507 | // We have a BFI instruction and we know the constant can't be materialized | ||||
2508 | // with a ORR-immediate with the zero register. | ||||
2509 | unsigned OrChunks = 0, BFIChunks = 0; | ||||
2510 | for (unsigned Shift = 0; Shift < BitWidth; Shift += 16) { | ||||
2511 | if (((OrImm >> Shift) & 0xFFFF) != 0) | ||||
2512 | ++OrChunks; | ||||
2513 | if (((BFIImm >> Shift) & 0xFFFF) != 0) | ||||
2514 | ++BFIChunks; | ||||
2515 | } | ||||
2516 | if (BFIChunks > OrChunks) | ||||
2517 | return false; | ||||
2518 | } | ||||
2519 | |||||
2520 | // Materialize the constant to be inserted. | ||||
2521 | SDLoc DL(N); | ||||
2522 | unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm; | ||||
2523 | SDNode *MOVI = CurDAG->getMachineNode( | ||||
2524 | MOVIOpc, DL, VT, CurDAG->getTargetConstant(BFIImm, DL, VT)); | ||||
2525 | |||||
2526 | // Create the BFI/BFXIL instruction. | ||||
2527 | SDValue Ops[] = {And.getOperand(0), SDValue(MOVI, 0), | ||||
2528 | CurDAG->getTargetConstant(ImmR, DL, VT), | ||||
2529 | CurDAG->getTargetConstant(ImmS, DL, VT)}; | ||||
2530 | unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri; | ||||
2531 | CurDAG->SelectNodeTo(N, Opc, VT, Ops); | ||||
2532 | return true; | ||||
2533 | } | ||||
2534 | |||||
2535 | static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits, | ||||
2536 | SelectionDAG *CurDAG) { | ||||
2537 | assert(N->getOpcode() == ISD::OR && "Expect a OR operation")((N->getOpcode() == ISD::OR && "Expect a OR operation" ) ? static_cast<void> (0) : __assert_fail ("N->getOpcode() == ISD::OR && \"Expect a OR operation\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2537, __PRETTY_FUNCTION__)); | ||||
2538 | |||||
2539 | EVT VT = N->getValueType(0); | ||||
2540 | if (VT != MVT::i32 && VT != MVT::i64) | ||||
2541 | return false; | ||||
2542 | |||||
2543 | unsigned BitWidth = VT.getSizeInBits(); | ||||
2544 | |||||
2545 | // Because of simplify-demanded-bits in DAGCombine, involved masks may not | ||||
2546 | // have the expected shape. Try to undo that. | ||||
2547 | |||||
2548 | unsigned NumberOfIgnoredLowBits = UsefulBits.countTrailingZeros(); | ||||
2549 | unsigned NumberOfIgnoredHighBits = UsefulBits.countLeadingZeros(); | ||||
2550 | |||||
2551 | // Given a OR operation, check if we have the following pattern | ||||
2552 | // ubfm c, b, imm, imm2 (or something that does the same jobs, see | ||||
2553 | // isBitfieldExtractOp) | ||||
2554 | // d = e & mask2 ; where mask is a binary sequence of 1..10..0 and | ||||
2555 | // countTrailingZeros(mask2) == imm2 - imm + 1 | ||||
2556 | // f = d | c | ||||
2557 | // if yes, replace the OR instruction with: | ||||
2558 | // f = BFM Opd0, Opd1, LSB, MSB ; where LSB = imm, and MSB = imm2 | ||||
2559 | |||||
2560 | // OR is commutative, check all combinations of operand order and values of | ||||
2561 | // BiggerPattern, i.e. | ||||
2562 | // Opd0, Opd1, BiggerPattern=false | ||||
2563 | // Opd1, Opd0, BiggerPattern=false | ||||
2564 | // Opd0, Opd1, BiggerPattern=true | ||||
2565 | // Opd1, Opd0, BiggerPattern=true | ||||
2566 | // Several of these combinations may match, so check with BiggerPattern=false | ||||
2567 | // first since that will produce better results by matching more instructions | ||||
2568 | // and/or inserting fewer extra instructions. | ||||
2569 | for (int I = 0; I < 4; ++I) { | ||||
2570 | |||||
2571 | SDValue Dst, Src; | ||||
2572 | unsigned ImmR, ImmS; | ||||
2573 | bool BiggerPattern = I / 2; | ||||
2574 | SDValue OrOpd0Val = N->getOperand(I % 2); | ||||
2575 | SDNode *OrOpd0 = OrOpd0Val.getNode(); | ||||
2576 | SDValue OrOpd1Val = N->getOperand((I + 1) % 2); | ||||
2577 | SDNode *OrOpd1 = OrOpd1Val.getNode(); | ||||
2578 | |||||
2579 | unsigned BFXOpc; | ||||
2580 | int DstLSB, Width; | ||||
2581 | if (isBitfieldExtractOp(CurDAG, OrOpd0, BFXOpc, Src, ImmR, ImmS, | ||||
2582 | NumberOfIgnoredLowBits, BiggerPattern)) { | ||||
2583 | // Check that the returned opcode is compatible with the pattern, | ||||
2584 | // i.e., same type and zero extended (U and not S) | ||||
2585 | if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) || | ||||
2586 | (BFXOpc != AArch64::UBFMWri && VT == MVT::i32)) | ||||
2587 | continue; | ||||
2588 | |||||
2589 | // Compute the width of the bitfield insertion | ||||
2590 | DstLSB = 0; | ||||
2591 | Width = ImmS - ImmR + 1; | ||||
2592 | // FIXME: This constraint is to catch bitfield insertion we may | ||||
2593 | // want to widen the pattern if we want to grab general bitfied | ||||
2594 | // move case | ||||
2595 | if (Width <= 0) | ||||
2596 | continue; | ||||
2597 | |||||
2598 | // If the mask on the insertee is correct, we have a BFXIL operation. We | ||||
2599 | // can share the ImmR and ImmS values from the already-computed UBFM. | ||||
2600 | } else if (isBitfieldPositioningOp(CurDAG, OrOpd0Val, | ||||
2601 | BiggerPattern, | ||||
2602 | Src, DstLSB, Width)) { | ||||
2603 | ImmR = (BitWidth - DstLSB) % BitWidth; | ||||
2604 | ImmS = Width - 1; | ||||
2605 | } else | ||||
2606 | continue; | ||||
2607 | |||||
2608 | // Check the second part of the pattern | ||||
2609 | EVT VT = OrOpd1Val.getValueType(); | ||||
2610 | assert((VT == MVT::i32 || VT == MVT::i64) && "unexpected OR operand")(((VT == MVT::i32 || VT == MVT::i64) && "unexpected OR operand" ) ? static_cast<void> (0) : __assert_fail ("(VT == MVT::i32 || VT == MVT::i64) && \"unexpected OR operand\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2610, __PRETTY_FUNCTION__)); | ||||
2611 | |||||
2612 | // Compute the Known Zero for the candidate of the first operand. | ||||
2613 | // This allows to catch more general case than just looking for | ||||
2614 | // AND with imm. Indeed, simplify-demanded-bits may have removed | ||||
2615 | // the AND instruction because it proves it was useless. | ||||
2616 | KnownBits Known = CurDAG->computeKnownBits(OrOpd1Val); | ||||
2617 | |||||
2618 | // Check if there is enough room for the second operand to appear | ||||
2619 | // in the first one | ||||
2620 | APInt BitsToBeInserted = | ||||
2621 | APInt::getBitsSet(Known.getBitWidth(), DstLSB, DstLSB + Width); | ||||
2622 | |||||
2623 | if ((BitsToBeInserted & ~Known.Zero) != 0) | ||||
2624 | continue; | ||||
2625 | |||||
2626 | // Set the first operand | ||||
2627 | uint64_t Imm; | ||||
2628 | if (isOpcWithIntImmediate(OrOpd1, ISD::AND, Imm) && | ||||
2629 | isBitfieldDstMask(Imm, BitsToBeInserted, NumberOfIgnoredHighBits, VT)) | ||||
2630 | // In that case, we can eliminate the AND | ||||
2631 | Dst = OrOpd1->getOperand(0); | ||||
2632 | else | ||||
2633 | // Maybe the AND has been removed by simplify-demanded-bits | ||||
2634 | // or is useful because it discards more bits | ||||
2635 | Dst = OrOpd1Val; | ||||
2636 | |||||
2637 | // both parts match | ||||
2638 | SDLoc DL(N); | ||||
2639 | SDValue Ops[] = {Dst, Src, CurDAG->getTargetConstant(ImmR, DL, VT), | ||||
2640 | CurDAG->getTargetConstant(ImmS, DL, VT)}; | ||||
2641 | unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri; | ||||
2642 | CurDAG->SelectNodeTo(N, Opc, VT, Ops); | ||||
2643 | return true; | ||||
2644 | } | ||||
2645 | |||||
2646 | // Generate a BFXIL from 'or (and X, Mask0Imm), (and Y, Mask1Imm)' iff | ||||
2647 | // Mask0Imm and ~Mask1Imm are equivalent and one of the MaskImms is a shifted | ||||
2648 | // mask (e.g., 0x000ffff0). | ||||
2649 | uint64_t Mask0Imm, Mask1Imm; | ||||
2650 | SDValue And0 = N->getOperand(0); | ||||
2651 | SDValue And1 = N->getOperand(1); | ||||
2652 | if (And0.hasOneUse() && And1.hasOneUse() && | ||||
2653 | isOpcWithIntImmediate(And0.getNode(), ISD::AND, Mask0Imm) && | ||||
2654 | isOpcWithIntImmediate(And1.getNode(), ISD::AND, Mask1Imm) && | ||||
2655 | APInt(BitWidth, Mask0Imm) == ~APInt(BitWidth, Mask1Imm) && | ||||
2656 | (isShiftedMask(Mask0Imm, VT) || isShiftedMask(Mask1Imm, VT))) { | ||||
2657 | |||||
2658 | // ORR is commutative, so canonicalize to the form 'or (and X, Mask0Imm), | ||||
2659 | // (and Y, Mask1Imm)' where Mask1Imm is the shifted mask masking off the | ||||
2660 | // bits to be inserted. | ||||
2661 | if (isShiftedMask(Mask0Imm, VT)) { | ||||
2662 | std::swap(And0, And1); | ||||
2663 | std::swap(Mask0Imm, Mask1Imm); | ||||
2664 | } | ||||
2665 | |||||
2666 | SDValue Src = And1->getOperand(0); | ||||
2667 | SDValue Dst = And0->getOperand(0); | ||||
2668 | unsigned LSB = countTrailingZeros(Mask1Imm); | ||||
2669 | int Width = BitWidth - APInt(BitWidth, Mask0Imm).countPopulation(); | ||||
2670 | |||||
2671 | // The BFXIL inserts the low-order bits from a source register, so right | ||||
2672 | // shift the needed bits into place. | ||||
2673 | SDLoc DL(N); | ||||
2674 | unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri; | ||||
2675 | SDNode *LSR = CurDAG->getMachineNode( | ||||
2676 | ShiftOpc, DL, VT, Src, CurDAG->getTargetConstant(LSB, DL, VT), | ||||
2677 | CurDAG->getTargetConstant(BitWidth - 1, DL, VT)); | ||||
2678 | |||||
2679 | // BFXIL is an alias of BFM, so translate to BFM operands. | ||||
2680 | unsigned ImmR = (BitWidth - LSB) % BitWidth; | ||||
2681 | unsigned ImmS = Width - 1; | ||||
2682 | |||||
2683 | // Create the BFXIL instruction. | ||||
2684 | SDValue Ops[] = {Dst, SDValue(LSR, 0), | ||||
2685 | CurDAG->getTargetConstant(ImmR, DL, VT), | ||||
2686 | CurDAG->getTargetConstant(ImmS, DL, VT)}; | ||||
2687 | unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri; | ||||
2688 | CurDAG->SelectNodeTo(N, Opc, VT, Ops); | ||||
2689 | return true; | ||||
2690 | } | ||||
2691 | |||||
2692 | return false; | ||||
2693 | } | ||||
2694 | |||||
2695 | bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *N) { | ||||
2696 | if (N->getOpcode() != ISD::OR) | ||||
2697 | return false; | ||||
2698 | |||||
2699 | APInt NUsefulBits; | ||||
2700 | getUsefulBits(SDValue(N, 0), NUsefulBits); | ||||
2701 | |||||
2702 | // If all bits are not useful, just return UNDEF. | ||||
2703 | if (!NUsefulBits) { | ||||
2704 | CurDAG->SelectNodeTo(N, TargetOpcode::IMPLICIT_DEF, N->getValueType(0)); | ||||
2705 | return true; | ||||
2706 | } | ||||
2707 | |||||
2708 | if (tryBitfieldInsertOpFromOr(N, NUsefulBits, CurDAG)) | ||||
2709 | return true; | ||||
2710 | |||||
2711 | return tryBitfieldInsertOpFromOrAndImm(N, CurDAG); | ||||
2712 | } | ||||
2713 | |||||
2714 | /// SelectBitfieldInsertInZeroOp - Match a UBFIZ instruction that is the | ||||
2715 | /// equivalent of a left shift by a constant amount followed by an and masking | ||||
2716 | /// out a contiguous set of bits. | ||||
2717 | bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *N) { | ||||
2718 | if (N->getOpcode() != ISD::AND) | ||||
2719 | return false; | ||||
2720 | |||||
2721 | EVT VT = N->getValueType(0); | ||||
2722 | if (VT != MVT::i32 && VT != MVT::i64) | ||||
2723 | return false; | ||||
2724 | |||||
2725 | SDValue Op0; | ||||
2726 | int DstLSB, Width; | ||||
2727 | if (!isBitfieldPositioningOp(CurDAG, SDValue(N, 0), /*BiggerPattern=*/false, | ||||
2728 | Op0, DstLSB, Width)) | ||||
2729 | return false; | ||||
2730 | |||||
2731 | // ImmR is the rotate right amount. | ||||
2732 | unsigned ImmR = (VT.getSizeInBits() - DstLSB) % VT.getSizeInBits(); | ||||
2733 | // ImmS is the most significant bit of the source to be moved. | ||||
2734 | unsigned ImmS = Width - 1; | ||||
2735 | |||||
2736 | SDLoc DL(N); | ||||
2737 | SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR, DL, VT), | ||||
2738 | CurDAG->getTargetConstant(ImmS, DL, VT)}; | ||||
2739 | unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri; | ||||
2740 | CurDAG->SelectNodeTo(N, Opc, VT, Ops); | ||||
2741 | return true; | ||||
2742 | } | ||||
2743 | |||||
2744 | /// tryShiftAmountMod - Take advantage of built-in mod of shift amount in | ||||
2745 | /// variable shift/rotate instructions. | ||||
2746 | bool AArch64DAGToDAGISel::tryShiftAmountMod(SDNode *N) { | ||||
2747 | EVT VT = N->getValueType(0); | ||||
2748 | |||||
2749 | unsigned Opc; | ||||
2750 | switch (N->getOpcode()) { | ||||
2751 | case ISD::ROTR: | ||||
2752 | Opc = (VT == MVT::i32) ? AArch64::RORVWr : AArch64::RORVXr; | ||||
2753 | break; | ||||
2754 | case ISD::SHL: | ||||
2755 | Opc = (VT == MVT::i32) ? AArch64::LSLVWr : AArch64::LSLVXr; | ||||
2756 | break; | ||||
2757 | case ISD::SRL: | ||||
2758 | Opc = (VT == MVT::i32) ? AArch64::LSRVWr : AArch64::LSRVXr; | ||||
2759 | break; | ||||
2760 | case ISD::SRA: | ||||
2761 | Opc = (VT == MVT::i32) ? AArch64::ASRVWr : AArch64::ASRVXr; | ||||
2762 | break; | ||||
2763 | default: | ||||
2764 | return false; | ||||
2765 | } | ||||
2766 | |||||
2767 | uint64_t Size; | ||||
2768 | uint64_t Bits; | ||||
2769 | if (VT == MVT::i32) { | ||||
2770 | Bits = 5; | ||||
2771 | Size = 32; | ||||
2772 | } else if (VT == MVT::i64) { | ||||
2773 | Bits = 6; | ||||
2774 | Size = 64; | ||||
2775 | } else | ||||
2776 | return false; | ||||
2777 | |||||
2778 | SDValue ShiftAmt = N->getOperand(1); | ||||
2779 | SDLoc DL(N); | ||||
2780 | SDValue NewShiftAmt; | ||||
2781 | |||||
2782 | // Skip over an extend of the shift amount. | ||||
2783 | if (ShiftAmt->getOpcode() == ISD::ZERO_EXTEND || | ||||
2784 | ShiftAmt->getOpcode() == ISD::ANY_EXTEND) | ||||
2785 | ShiftAmt = ShiftAmt->getOperand(0); | ||||
2786 | |||||
2787 | if (ShiftAmt->getOpcode() == ISD::ADD || ShiftAmt->getOpcode() == ISD::SUB) { | ||||
2788 | SDValue Add0 = ShiftAmt->getOperand(0); | ||||
2789 | SDValue Add1 = ShiftAmt->getOperand(1); | ||||
2790 | uint64_t Add0Imm; | ||||
2791 | uint64_t Add1Imm; | ||||
2792 | // If we are shifting by X+/-N where N == 0 mod Size, then just shift by X | ||||
2793 | // to avoid the ADD/SUB. | ||||
2794 | if (isIntImmediate(Add1, Add1Imm) && (Add1Imm % Size == 0)) | ||||
2795 | NewShiftAmt = Add0; | ||||
2796 | // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to | ||||
2797 | // generate a NEG instead of a SUB of a constant. | ||||
2798 | else if (ShiftAmt->getOpcode() == ISD::SUB && | ||||
2799 | isIntImmediate(Add0, Add0Imm) && Add0Imm != 0 && | ||||
2800 | (Add0Imm % Size == 0)) { | ||||
2801 | unsigned NegOpc; | ||||
2802 | unsigned ZeroReg; | ||||
2803 | EVT SubVT = ShiftAmt->getValueType(0); | ||||
2804 | if (SubVT == MVT::i32) { | ||||
2805 | NegOpc = AArch64::SUBWrr; | ||||
2806 | ZeroReg = AArch64::WZR; | ||||
2807 | } else { | ||||
2808 | assert(SubVT == MVT::i64)((SubVT == MVT::i64) ? static_cast<void> (0) : __assert_fail ("SubVT == MVT::i64", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2808, __PRETTY_FUNCTION__)); | ||||
2809 | NegOpc = AArch64::SUBXrr; | ||||
2810 | ZeroReg = AArch64::XZR; | ||||
2811 | } | ||||
2812 | SDValue Zero = | ||||
2813 | CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, ZeroReg, SubVT); | ||||
2814 | MachineSDNode *Neg = | ||||
2815 | CurDAG->getMachineNode(NegOpc, DL, SubVT, Zero, Add1); | ||||
2816 | NewShiftAmt = SDValue(Neg, 0); | ||||
2817 | } else | ||||
2818 | return false; | ||||
2819 | } else { | ||||
2820 | // If the shift amount is masked with an AND, check that the mask covers the | ||||
2821 | // bits that are implicitly ANDed off by the above opcodes and if so, skip | ||||
2822 | // the AND. | ||||
2823 | uint64_t MaskImm; | ||||
2824 | if (!isOpcWithIntImmediate(ShiftAmt.getNode(), ISD::AND, MaskImm) && | ||||
2825 | !isOpcWithIntImmediate(ShiftAmt.getNode(), AArch64ISD::ANDS, MaskImm)) | ||||
2826 | return false; | ||||
2827 | |||||
2828 | if (countTrailingOnes(MaskImm) < Bits) | ||||
2829 | return false; | ||||
2830 | |||||
2831 | NewShiftAmt = ShiftAmt->getOperand(0); | ||||
2832 | } | ||||
2833 | |||||
2834 | // Narrow/widen the shift amount to match the size of the shift operation. | ||||
2835 | if (VT == MVT::i32) | ||||
2836 | NewShiftAmt = narrowIfNeeded(CurDAG, NewShiftAmt); | ||||
2837 | else if (VT == MVT::i64 && NewShiftAmt->getValueType(0) == MVT::i32) { | ||||
2838 | SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, DL, MVT::i32); | ||||
2839 | MachineSDNode *Ext = CurDAG->getMachineNode( | ||||
2840 | AArch64::SUBREG_TO_REG, DL, VT, | ||||
2841 | CurDAG->getTargetConstant(0, DL, MVT::i64), NewShiftAmt, SubReg); | ||||
2842 | NewShiftAmt = SDValue(Ext, 0); | ||||
2843 | } | ||||
2844 | |||||
2845 | SDValue Ops[] = {N->getOperand(0), NewShiftAmt}; | ||||
2846 | CurDAG->SelectNodeTo(N, Opc, VT, Ops); | ||||
2847 | return true; | ||||
2848 | } | ||||
2849 | |||||
2850 | bool | ||||
2851 | AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos, | ||||
2852 | unsigned RegWidth) { | ||||
2853 | APFloat FVal(0.0); | ||||
2854 | if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) | ||||
2855 | FVal = CN->getValueAPF(); | ||||
2856 | else if (LoadSDNode *LN = dyn_cast<LoadSDNode>(N)) { | ||||
2857 | // Some otherwise illegal constants are allowed in this case. | ||||
2858 | if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow || | ||||
2859 | !isa<ConstantPoolSDNode>(LN->getOperand(1)->getOperand(1))) | ||||
2860 | return false; | ||||
2861 | |||||
2862 | ConstantPoolSDNode *CN = | ||||
2863 | dyn_cast<ConstantPoolSDNode>(LN->getOperand(1)->getOperand(1)); | ||||
2864 | FVal = cast<ConstantFP>(CN->getConstVal())->getValueAPF(); | ||||
2865 | } else | ||||
2866 | return false; | ||||
2867 | |||||
2868 | // An FCVT[SU] instruction performs: convertToInt(Val * 2^fbits) where fbits | ||||
2869 | // is between 1 and 32 for a destination w-register, or 1 and 64 for an | ||||
2870 | // x-register. | ||||
2871 | // | ||||
2872 | // By this stage, we've detected (fp_to_[su]int (fmul Val, THIS_NODE)) so we | ||||
2873 | // want THIS_NODE to be 2^fbits. This is much easier to deal with using | ||||
2874 | // integers. | ||||
2875 | bool IsExact; | ||||
2876 | |||||
2877 | // fbits is between 1 and 64 in the worst-case, which means the fmul | ||||
2878 | // could have 2^64 as an actual operand. Need 65 bits of precision. | ||||
2879 | APSInt IntVal(65, true); | ||||
2880 | FVal.convertToInteger(IntVal, APFloat::rmTowardZero, &IsExact); | ||||
2881 | |||||
2882 | // N.b. isPowerOf2 also checks for > 0. | ||||
2883 | if (!IsExact || !IntVal.isPowerOf2()) return false; | ||||
2884 | unsigned FBits = IntVal.logBase2(); | ||||
2885 | |||||
2886 | // Checks above should have guaranteed that we haven't lost information in | ||||
2887 | // finding FBits, but it must still be in range. | ||||
2888 | if (FBits == 0 || FBits > RegWidth) return false; | ||||
2889 | |||||
2890 | FixedPos = CurDAG->getTargetConstant(FBits, SDLoc(N), MVT::i32); | ||||
2891 | return true; | ||||
2892 | } | ||||
2893 | |||||
2894 | // Inspects a register string of the form o0:op1:CRn:CRm:op2 gets the fields | ||||
2895 | // of the string and obtains the integer values from them and combines these | ||||
2896 | // into a single value to be used in the MRS/MSR instruction. | ||||
2897 | static int getIntOperandFromRegisterString(StringRef RegString) { | ||||
2898 | SmallVector<StringRef, 5> Fields; | ||||
2899 | RegString.split(Fields, ':'); | ||||
2900 | |||||
2901 | if (Fields.size() == 1) | ||||
2902 | return -1; | ||||
2903 | |||||
2904 | assert(Fields.size() == 5((Fields.size() == 5 && "Invalid number of fields in read register string" ) ? static_cast<void> (0) : __assert_fail ("Fields.size() == 5 && \"Invalid number of fields in read register string\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2905, __PRETTY_FUNCTION__)) | ||||
2905 | && "Invalid number of fields in read register string")((Fields.size() == 5 && "Invalid number of fields in read register string" ) ? static_cast<void> (0) : __assert_fail ("Fields.size() == 5 && \"Invalid number of fields in read register string\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2905, __PRETTY_FUNCTION__)); | ||||
2906 | |||||
2907 | SmallVector<int, 5> Ops; | ||||
2908 | bool AllIntFields = true; | ||||
2909 | |||||
2910 | for (StringRef Field : Fields) { | ||||
2911 | unsigned IntField; | ||||
2912 | AllIntFields &= !Field.getAsInteger(10, IntField); | ||||
2913 | Ops.push_back(IntField); | ||||
2914 | } | ||||
2915 | |||||
2916 | assert(AllIntFields &&((AllIntFields && "Unexpected non-integer value in special register string." ) ? static_cast<void> (0) : __assert_fail ("AllIntFields && \"Unexpected non-integer value in special register string.\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2917, __PRETTY_FUNCTION__)) | ||||
2917 | "Unexpected non-integer value in special register string.")((AllIntFields && "Unexpected non-integer value in special register string." ) ? static_cast<void> (0) : __assert_fail ("AllIntFields && \"Unexpected non-integer value in special register string.\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2917, __PRETTY_FUNCTION__)); | ||||
2918 | |||||
2919 | // Need to combine the integer fields of the string into a single value | ||||
2920 | // based on the bit encoding of MRS/MSR instruction. | ||||
2921 | return (Ops[0] << 14) | (Ops[1] << 11) | (Ops[2] << 7) | | ||||
2922 | (Ops[3] << 3) | (Ops[4]); | ||||
2923 | } | ||||
2924 | |||||
2925 | // Lower the read_register intrinsic to an MRS instruction node if the special | ||||
2926 | // register string argument is either of the form detailed in the ALCE (the | ||||
2927 | // form described in getIntOperandsFromRegsterString) or is a named register | ||||
2928 | // known by the MRS SysReg mapper. | ||||
2929 | bool AArch64DAGToDAGISel::tryReadRegister(SDNode *N) { | ||||
2930 | const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1)); | ||||
2931 | const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0)); | ||||
2932 | SDLoc DL(N); | ||||
2933 | |||||
2934 | int Reg = getIntOperandFromRegisterString(RegString->getString()); | ||||
2935 | if (Reg != -1) { | ||||
2936 | ReplaceNode(N, CurDAG->getMachineNode( | ||||
2937 | AArch64::MRS, DL, N->getSimpleValueType(0), MVT::Other, | ||||
2938 | CurDAG->getTargetConstant(Reg, DL, MVT::i32), | ||||
2939 | N->getOperand(0))); | ||||
2940 | return true; | ||||
2941 | } | ||||
2942 | |||||
2943 | // Use the sysreg mapper to map the remaining possible strings to the | ||||
2944 | // value for the register to be used for the instruction operand. | ||||
2945 | auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString()); | ||||
2946 | if (TheReg && TheReg->Readable && | ||||
2947 | TheReg->haveFeatures(Subtarget->getFeatureBits())) | ||||
2948 | Reg = TheReg->Encoding; | ||||
2949 | else | ||||
2950 | Reg = AArch64SysReg::parseGenericRegister(RegString->getString()); | ||||
2951 | |||||
2952 | if (Reg != -1) { | ||||
2953 | ReplaceNode(N, CurDAG->getMachineNode( | ||||
2954 | AArch64::MRS, DL, N->getSimpleValueType(0), MVT::Other, | ||||
2955 | CurDAG->getTargetConstant(Reg, DL, MVT::i32), | ||||
2956 | N->getOperand(0))); | ||||
2957 | return true; | ||||
2958 | } | ||||
2959 | |||||
2960 | if (RegString->getString() == "pc") { | ||||
2961 | ReplaceNode(N, CurDAG->getMachineNode( | ||||
2962 | AArch64::ADR, DL, N->getSimpleValueType(0), MVT::Other, | ||||
2963 | CurDAG->getTargetConstant(0, DL, MVT::i32), | ||||
2964 | N->getOperand(0))); | ||||
2965 | return true; | ||||
2966 | } | ||||
2967 | |||||
2968 | return false; | ||||
2969 | } | ||||
2970 | |||||
2971 | // Lower the write_register intrinsic to an MSR instruction node if the special | ||||
2972 | // register string argument is either of the form detailed in the ALCE (the | ||||
2973 | // form described in getIntOperandsFromRegsterString) or is a named register | ||||
2974 | // known by the MSR SysReg mapper. | ||||
2975 | bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *N) { | ||||
2976 | const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1)); | ||||
2977 | const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0)); | ||||
2978 | SDLoc DL(N); | ||||
2979 | |||||
2980 | int Reg = getIntOperandFromRegisterString(RegString->getString()); | ||||
2981 | if (Reg != -1) { | ||||
2982 | ReplaceNode( | ||||
2983 | N, CurDAG->getMachineNode(AArch64::MSR, DL, MVT::Other, | ||||
2984 | CurDAG->getTargetConstant(Reg, DL, MVT::i32), | ||||
2985 | N->getOperand(2), N->getOperand(0))); | ||||
2986 | return true; | ||||
2987 | } | ||||
2988 | |||||
2989 | // Check if the register was one of those allowed as the pstatefield value in | ||||
2990 | // the MSR (immediate) instruction. To accept the values allowed in the | ||||
2991 | // pstatefield for the MSR (immediate) instruction, we also require that an | ||||
2992 | // immediate value has been provided as an argument, we know that this is | ||||
2993 | // the case as it has been ensured by semantic checking. | ||||
2994 | auto PMapper = AArch64PState::lookupPStateByName(RegString->getString()); | ||||
2995 | if (PMapper) { | ||||
2996 | assert (isa<ConstantSDNode>(N->getOperand(2))((isa<ConstantSDNode>(N->getOperand(2)) && "Expected a constant integer expression." ) ? static_cast<void> (0) : __assert_fail ("isa<ConstantSDNode>(N->getOperand(2)) && \"Expected a constant integer expression.\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2997, __PRETTY_FUNCTION__)) | ||||
2997 | && "Expected a constant integer expression.")((isa<ConstantSDNode>(N->getOperand(2)) && "Expected a constant integer expression." ) ? static_cast<void> (0) : __assert_fail ("isa<ConstantSDNode>(N->getOperand(2)) && \"Expected a constant integer expression.\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 2997, __PRETTY_FUNCTION__)); | ||||
2998 | unsigned Reg = PMapper->Encoding; | ||||
2999 | uint64_t Immed = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(); | ||||
3000 | unsigned State; | ||||
3001 | if (Reg == AArch64PState::PAN || Reg == AArch64PState::UAO || Reg == AArch64PState::SSBS) { | ||||
3002 | assert(Immed < 2 && "Bad imm")((Immed < 2 && "Bad imm") ? static_cast<void> (0) : __assert_fail ("Immed < 2 && \"Bad imm\"", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3002, __PRETTY_FUNCTION__)); | ||||
3003 | State = AArch64::MSRpstateImm1; | ||||
3004 | } else { | ||||
3005 | assert(Immed < 16 && "Bad imm")((Immed < 16 && "Bad imm") ? static_cast<void> (0) : __assert_fail ("Immed < 16 && \"Bad imm\"", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3005, __PRETTY_FUNCTION__)); | ||||
3006 | State = AArch64::MSRpstateImm4; | ||||
3007 | } | ||||
3008 | ReplaceNode(N, CurDAG->getMachineNode( | ||||
3009 | State, DL, MVT::Other, | ||||
3010 | CurDAG->getTargetConstant(Reg, DL, MVT::i32), | ||||
3011 | CurDAG->getTargetConstant(Immed, DL, MVT::i16), | ||||
3012 | N->getOperand(0))); | ||||
3013 | return true; | ||||
3014 | } | ||||
3015 | |||||
3016 | // Use the sysreg mapper to attempt to map the remaining possible strings | ||||
3017 | // to the value for the register to be used for the MSR (register) | ||||
3018 | // instruction operand. | ||||
3019 | auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString()); | ||||
3020 | if (TheReg && TheReg->Writeable && | ||||
3021 | TheReg->haveFeatures(Subtarget->getFeatureBits())) | ||||
3022 | Reg = TheReg->Encoding; | ||||
3023 | else | ||||
3024 | Reg = AArch64SysReg::parseGenericRegister(RegString->getString()); | ||||
3025 | if (Reg != -1) { | ||||
3026 | ReplaceNode(N, CurDAG->getMachineNode( | ||||
3027 | AArch64::MSR, DL, MVT::Other, | ||||
3028 | CurDAG->getTargetConstant(Reg, DL, MVT::i32), | ||||
3029 | N->getOperand(2), N->getOperand(0))); | ||||
3030 | return true; | ||||
3031 | } | ||||
3032 | |||||
3033 | return false; | ||||
3034 | } | ||||
3035 | |||||
3036 | /// We've got special pseudo-instructions for these | ||||
3037 | bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *N) { | ||||
3038 | unsigned Opcode; | ||||
3039 | EVT MemTy = cast<MemSDNode>(N)->getMemoryVT(); | ||||
3040 | |||||
3041 | // Leave IR for LSE if subtarget supports it. | ||||
3042 | if (Subtarget->hasLSE()) return false; | ||||
3043 | |||||
3044 | if (MemTy == MVT::i8) | ||||
3045 | Opcode = AArch64::CMP_SWAP_8; | ||||
3046 | else if (MemTy == MVT::i16) | ||||
3047 | Opcode = AArch64::CMP_SWAP_16; | ||||
3048 | else if (MemTy == MVT::i32) | ||||
3049 | Opcode = AArch64::CMP_SWAP_32; | ||||
3050 | else if (MemTy == MVT::i64) | ||||
3051 | Opcode = AArch64::CMP_SWAP_64; | ||||
3052 | else | ||||
3053 | llvm_unreachable("Unknown AtomicCmpSwap type")::llvm::llvm_unreachable_internal("Unknown AtomicCmpSwap type" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3053); | ||||
3054 | |||||
3055 | MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32; | ||||
3056 | SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3), | ||||
3057 | N->getOperand(0)}; | ||||
3058 | SDNode *CmpSwap = CurDAG->getMachineNode( | ||||
3059 | Opcode, SDLoc(N), | ||||
3060 | CurDAG->getVTList(RegTy, MVT::i32, MVT::Other), Ops); | ||||
3061 | |||||
3062 | MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand(); | ||||
3063 | CurDAG->setNodeMemRefs(cast<MachineSDNode>(CmpSwap), {MemOp}); | ||||
3064 | |||||
3065 | ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0)); | ||||
3066 | ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2)); | ||||
3067 | CurDAG->RemoveDeadNode(N); | ||||
3068 | |||||
3069 | return true; | ||||
3070 | } | ||||
3071 | |||||
3072 | bool AArch64DAGToDAGISel::SelectSVE8BitLslImm(SDValue N, SDValue &Base, | ||||
3073 | SDValue &Offset) { | ||||
3074 | auto C = dyn_cast<ConstantSDNode>(N); | ||||
3075 | if (!C) | ||||
3076 | return false; | ||||
3077 | |||||
3078 | auto Ty = N->getValueType(0); | ||||
3079 | |||||
3080 | int64_t Imm = C->getSExtValue(); | ||||
3081 | SDLoc DL(N); | ||||
3082 | |||||
3083 | if ((Imm >= -128) && (Imm <= 127)) { | ||||
3084 | Base = CurDAG->getTargetConstant(Imm, DL, Ty); | ||||
3085 | Offset = CurDAG->getTargetConstant(0, DL, Ty); | ||||
3086 | return true; | ||||
3087 | } | ||||
3088 | |||||
3089 | if (((Imm % 256) == 0) && (Imm >= -32768) && (Imm <= 32512)) { | ||||
3090 | Base = CurDAG->getTargetConstant(Imm/256, DL, Ty); | ||||
3091 | Offset = CurDAG->getTargetConstant(8, DL, Ty); | ||||
3092 | return true; | ||||
3093 | } | ||||
3094 | |||||
3095 | return false; | ||||
3096 | } | ||||
3097 | |||||
3098 | bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDValue N, MVT VT, SDValue &Imm, SDValue &Shift) { | ||||
3099 | if (auto CNode = dyn_cast<ConstantSDNode>(N)) { | ||||
3100 | const int64_t ImmVal = CNode->getZExtValue(); | ||||
3101 | SDLoc DL(N); | ||||
3102 | |||||
3103 | switch (VT.SimpleTy) { | ||||
3104 | case MVT::i8: | ||||
3105 | if ((ImmVal & 0xFF) == ImmVal) { | ||||
3106 | Shift = CurDAG->getTargetConstant(0, DL, MVT::i32); | ||||
3107 | Imm = CurDAG->getTargetConstant(ImmVal, DL, MVT::i32); | ||||
3108 | return true; | ||||
3109 | } | ||||
3110 | break; | ||||
3111 | case MVT::i16: | ||||
3112 | case MVT::i32: | ||||
3113 | case MVT::i64: | ||||
3114 | if ((ImmVal & 0xFF) == ImmVal) { | ||||
3115 | Shift = CurDAG->getTargetConstant(0, DL, MVT::i32); | ||||
3116 | Imm = CurDAG->getTargetConstant(ImmVal, DL, MVT::i32); | ||||
3117 | return true; | ||||
3118 | } else if ((ImmVal & 0xFF00) == ImmVal) { | ||||
3119 | Shift = CurDAG->getTargetConstant(8, DL, MVT::i32); | ||||
3120 | Imm = CurDAG->getTargetConstant(ImmVal >> 8, DL, MVT::i32); | ||||
3121 | return true; | ||||
3122 | } | ||||
3123 | break; | ||||
3124 | default: | ||||
3125 | break; | ||||
3126 | } | ||||
3127 | } | ||||
3128 | |||||
3129 | return false; | ||||
3130 | } | ||||
3131 | |||||
3132 | bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDValue N, SDValue &Imm) { | ||||
3133 | if (auto CNode = dyn_cast<ConstantSDNode>(N)) { | ||||
3134 | int64_t ImmVal = CNode->getSExtValue(); | ||||
3135 | SDLoc DL(N); | ||||
3136 | if (ImmVal >= -128 && ImmVal < 128) { | ||||
3137 | Imm = CurDAG->getTargetConstant(ImmVal, DL, MVT::i32); | ||||
3138 | return true; | ||||
3139 | } | ||||
3140 | } | ||||
3141 | return false; | ||||
3142 | } | ||||
3143 | |||||
3144 | bool AArch64DAGToDAGISel::SelectSVEArithImm(SDValue N, MVT VT, SDValue &Imm) { | ||||
3145 | if (auto CNode = dyn_cast<ConstantSDNode>(N)) { | ||||
3146 | uint64_t ImmVal = CNode->getZExtValue(); | ||||
3147 | |||||
3148 | switch (VT.SimpleTy) { | ||||
3149 | case MVT::i8: | ||||
3150 | ImmVal &= 0xFF; | ||||
3151 | break; | ||||
3152 | case MVT::i16: | ||||
3153 | ImmVal &= 0xFFFF; | ||||
3154 | break; | ||||
3155 | case MVT::i32: | ||||
3156 | ImmVal &= 0xFFFFFFFF; | ||||
3157 | break; | ||||
3158 | case MVT::i64: | ||||
3159 | break; | ||||
3160 | default: | ||||
3161 | llvm_unreachable("Unexpected type")::llvm::llvm_unreachable_internal("Unexpected type", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3161); | ||||
3162 | } | ||||
3163 | |||||
3164 | if (ImmVal < 256) { | ||||
3165 | Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(N), MVT::i32); | ||||
3166 | return true; | ||||
3167 | } | ||||
3168 | } | ||||
3169 | return false; | ||||
3170 | } | ||||
3171 | |||||
3172 | bool AArch64DAGToDAGISel::SelectSVELogicalImm(SDValue N, MVT VT, SDValue &Imm) { | ||||
3173 | if (auto CNode = dyn_cast<ConstantSDNode>(N)) { | ||||
3174 | uint64_t ImmVal = CNode->getZExtValue(); | ||||
3175 | SDLoc DL(N); | ||||
3176 | |||||
3177 | // Shift mask depending on type size. | ||||
3178 | switch (VT.SimpleTy) { | ||||
3179 | case MVT::i8: | ||||
3180 | ImmVal &= 0xFF; | ||||
3181 | ImmVal |= ImmVal << 8; | ||||
3182 | ImmVal |= ImmVal << 16; | ||||
3183 | ImmVal |= ImmVal << 32; | ||||
3184 | break; | ||||
3185 | case MVT::i16: | ||||
3186 | ImmVal &= 0xFFFF; | ||||
3187 | ImmVal |= ImmVal << 16; | ||||
3188 | ImmVal |= ImmVal << 32; | ||||
3189 | break; | ||||
3190 | case MVT::i32: | ||||
3191 | ImmVal &= 0xFFFFFFFF; | ||||
3192 | ImmVal |= ImmVal << 32; | ||||
3193 | break; | ||||
3194 | case MVT::i64: | ||||
3195 | break; | ||||
3196 | default: | ||||
3197 | llvm_unreachable("Unexpected type")::llvm::llvm_unreachable_internal("Unexpected type", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3197); | ||||
3198 | } | ||||
3199 | |||||
3200 | uint64_t encoding; | ||||
3201 | if (AArch64_AM::processLogicalImmediate(ImmVal, 64, encoding)) { | ||||
3202 | Imm = CurDAG->getTargetConstant(encoding, DL, MVT::i64); | ||||
3203 | return true; | ||||
3204 | } | ||||
3205 | } | ||||
3206 | return false; | ||||
3207 | } | ||||
3208 | |||||
3209 | // SVE shift intrinsics allow shift amounts larger than the element's bitwidth. | ||||
3210 | // Rather than attempt to normalise everything we can sometimes saturate the | ||||
3211 | // shift amount during selection. This function also allows for consistent | ||||
3212 | // isel patterns by ensuring the resulting "Imm" node is of the i32 type | ||||
3213 | // required by the instructions. | ||||
3214 | bool AArch64DAGToDAGISel::SelectSVEShiftImm(SDValue N, uint64_t Low, | ||||
3215 | uint64_t High, bool AllowSaturation, | ||||
3216 | SDValue &Imm) { | ||||
3217 | if (auto *CN = dyn_cast<ConstantSDNode>(N)) { | ||||
3218 | uint64_t ImmVal = CN->getZExtValue(); | ||||
3219 | |||||
3220 | // Reject shift amounts that are too small. | ||||
3221 | if (ImmVal < Low) | ||||
3222 | return false; | ||||
3223 | |||||
3224 | // Reject or saturate shift amounts that are too big. | ||||
3225 | if (ImmVal > High) { | ||||
3226 | if (!AllowSaturation) | ||||
3227 | return false; | ||||
3228 | ImmVal = High; | ||||
3229 | } | ||||
3230 | |||||
3231 | Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(N), MVT::i32); | ||||
3232 | return true; | ||||
3233 | } | ||||
3234 | |||||
3235 | return false; | ||||
3236 | } | ||||
3237 | |||||
3238 | bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *N) { | ||||
3239 | // tagp(FrameIndex, IRGstack, tag_offset): | ||||
3240 | // since the offset between FrameIndex and IRGstack is a compile-time | ||||
3241 | // constant, this can be lowered to a single ADDG instruction. | ||||
3242 | if (!(isa<FrameIndexSDNode>(N->getOperand(1)))) { | ||||
3243 | return false; | ||||
3244 | } | ||||
3245 | |||||
3246 | SDValue IRG_SP = N->getOperand(2); | ||||
3247 | if (IRG_SP->getOpcode() != ISD::INTRINSIC_W_CHAIN || | ||||
3248 | cast<ConstantSDNode>(IRG_SP->getOperand(1))->getZExtValue() != | ||||
3249 | Intrinsic::aarch64_irg_sp) { | ||||
3250 | return false; | ||||
3251 | } | ||||
3252 | |||||
3253 | const TargetLowering *TLI = getTargetLowering(); | ||||
3254 | SDLoc DL(N); | ||||
3255 | int FI = cast<FrameIndexSDNode>(N->getOperand(1))->getIndex(); | ||||
3256 | SDValue FiOp = CurDAG->getTargetFrameIndex( | ||||
3257 | FI, TLI->getPointerTy(CurDAG->getDataLayout())); | ||||
3258 | int TagOffset = cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(); | ||||
3259 | |||||
3260 | SDNode *Out = CurDAG->getMachineNode( | ||||
3261 | AArch64::TAGPstack, DL, MVT::i64, | ||||
3262 | {FiOp, CurDAG->getTargetConstant(0, DL, MVT::i64), N->getOperand(2), | ||||
3263 | CurDAG->getTargetConstant(TagOffset, DL, MVT::i64)}); | ||||
3264 | ReplaceNode(N, Out); | ||||
3265 | return true; | ||||
3266 | } | ||||
3267 | |||||
3268 | void AArch64DAGToDAGISel::SelectTagP(SDNode *N) { | ||||
3269 | assert(isa<ConstantSDNode>(N->getOperand(3)) &&((isa<ConstantSDNode>(N->getOperand(3)) && "llvm.aarch64.tagp third argument must be an immediate" ) ? static_cast<void> (0) : __assert_fail ("isa<ConstantSDNode>(N->getOperand(3)) && \"llvm.aarch64.tagp third argument must be an immediate\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3270, __PRETTY_FUNCTION__)) | ||||
3270 | "llvm.aarch64.tagp third argument must be an immediate")((isa<ConstantSDNode>(N->getOperand(3)) && "llvm.aarch64.tagp third argument must be an immediate" ) ? static_cast<void> (0) : __assert_fail ("isa<ConstantSDNode>(N->getOperand(3)) && \"llvm.aarch64.tagp third argument must be an immediate\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3270, __PRETTY_FUNCTION__)); | ||||
3271 | if (trySelectStackSlotTagP(N)) | ||||
3272 | return; | ||||
3273 | // FIXME: above applies in any case when offset between Op1 and Op2 is a | ||||
3274 | // compile-time constant, not just for stack allocations. | ||||
3275 | |||||
3276 | // General case for unrelated pointers in Op1 and Op2. | ||||
3277 | SDLoc DL(N); | ||||
3278 | int TagOffset = cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(); | ||||
3279 | SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP, DL, MVT::i64, | ||||
3280 | {N->getOperand(1), N->getOperand(2)}); | ||||
3281 | SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr, DL, MVT::i64, | ||||
3282 | {SDValue(N1, 0), N->getOperand(2)}); | ||||
3283 | SDNode *N3 = CurDAG->getMachineNode( | ||||
3284 | AArch64::ADDG, DL, MVT::i64, | ||||
3285 | {SDValue(N2, 0), CurDAG->getTargetConstant(0, DL, MVT::i64), | ||||
3286 | CurDAG->getTargetConstant(TagOffset, DL, MVT::i64)}); | ||||
3287 | ReplaceNode(N, N3); | ||||
3288 | } | ||||
3289 | |||||
3290 | // NOTE: We cannot use EXTRACT_SUBREG in all cases because the fixed length | ||||
3291 | // vector types larger than NEON don't have a matching SubRegIndex. | ||||
3292 | static SDNode *extractSubReg(SelectionDAG *DAG, EVT VT, SDValue V) { | ||||
3293 | assert(V.getValueType().isScalableVector() &&((V.getValueType().isScalableVector() && V.getValueType ().getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && "Expected to extract from a packed scalable vector!" ) ? static_cast<void> (0) : __assert_fail ("V.getValueType().isScalableVector() && V.getValueType().getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && \"Expected to extract from a packed scalable vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3296, __PRETTY_FUNCTION__)) | ||||
3294 | V.getValueType().getSizeInBits().getKnownMinSize() ==((V.getValueType().isScalableVector() && V.getValueType ().getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && "Expected to extract from a packed scalable vector!" ) ? static_cast<void> (0) : __assert_fail ("V.getValueType().isScalableVector() && V.getValueType().getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && \"Expected to extract from a packed scalable vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3296, __PRETTY_FUNCTION__)) | ||||
3295 | AArch64::SVEBitsPerBlock &&((V.getValueType().isScalableVector() && V.getValueType ().getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && "Expected to extract from a packed scalable vector!" ) ? static_cast<void> (0) : __assert_fail ("V.getValueType().isScalableVector() && V.getValueType().getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && \"Expected to extract from a packed scalable vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3296, __PRETTY_FUNCTION__)) | ||||
3296 | "Expected to extract from a packed scalable vector!")((V.getValueType().isScalableVector() && V.getValueType ().getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && "Expected to extract from a packed scalable vector!" ) ? static_cast<void> (0) : __assert_fail ("V.getValueType().isScalableVector() && V.getValueType().getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && \"Expected to extract from a packed scalable vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3296, __PRETTY_FUNCTION__)); | ||||
3297 | assert(VT.isFixedLengthVector() &&((VT.isFixedLengthVector() && "Expected to extract a fixed length vector!" ) ? static_cast<void> (0) : __assert_fail ("VT.isFixedLengthVector() && \"Expected to extract a fixed length vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3298, __PRETTY_FUNCTION__)) | ||||
3298 | "Expected to extract a fixed length vector!")((VT.isFixedLengthVector() && "Expected to extract a fixed length vector!" ) ? static_cast<void> (0) : __assert_fail ("VT.isFixedLengthVector() && \"Expected to extract a fixed length vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3298, __PRETTY_FUNCTION__)); | ||||
3299 | |||||
3300 | SDLoc DL(V); | ||||
3301 | switch (VT.getSizeInBits()) { | ||||
3302 | case 64: { | ||||
3303 | auto SubReg = DAG->getTargetConstant(AArch64::dsub, DL, MVT::i32); | ||||
3304 | return DAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, VT, V, SubReg); | ||||
3305 | } | ||||
3306 | case 128: { | ||||
3307 | auto SubReg = DAG->getTargetConstant(AArch64::zsub, DL, MVT::i32); | ||||
3308 | return DAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, VT, V, SubReg); | ||||
3309 | } | ||||
3310 | default: { | ||||
3311 | auto RC = DAG->getTargetConstant(AArch64::ZPRRegClassID, DL, MVT::i64); | ||||
3312 | return DAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, DL, VT, V, RC); | ||||
3313 | } | ||||
3314 | } | ||||
3315 | } | ||||
3316 | |||||
3317 | // NOTE: We cannot use INSERT_SUBREG in all cases because the fixed length | ||||
3318 | // vector types larger than NEON don't have a matching SubRegIndex. | ||||
3319 | static SDNode *insertSubReg(SelectionDAG *DAG, EVT VT, SDValue V) { | ||||
3320 | assert(VT.isScalableVector() &&((VT.isScalableVector() && VT.getSizeInBits().getKnownMinSize () == AArch64::SVEBitsPerBlock && "Expected to insert into a packed scalable vector!" ) ? static_cast<void> (0) : __assert_fail ("VT.isScalableVector() && VT.getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && \"Expected to insert into a packed scalable vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3322, __PRETTY_FUNCTION__)) | ||||
3321 | VT.getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock &&((VT.isScalableVector() && VT.getSizeInBits().getKnownMinSize () == AArch64::SVEBitsPerBlock && "Expected to insert into a packed scalable vector!" ) ? static_cast<void> (0) : __assert_fail ("VT.isScalableVector() && VT.getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && \"Expected to insert into a packed scalable vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3322, __PRETTY_FUNCTION__)) | ||||
3322 | "Expected to insert into a packed scalable vector!")((VT.isScalableVector() && VT.getSizeInBits().getKnownMinSize () == AArch64::SVEBitsPerBlock && "Expected to insert into a packed scalable vector!" ) ? static_cast<void> (0) : __assert_fail ("VT.isScalableVector() && VT.getSizeInBits().getKnownMinSize() == AArch64::SVEBitsPerBlock && \"Expected to insert into a packed scalable vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3322, __PRETTY_FUNCTION__)); | ||||
3323 | assert(V.getValueType().isFixedLengthVector() &&((V.getValueType().isFixedLengthVector() && "Expected to insert a fixed length vector!" ) ? static_cast<void> (0) : __assert_fail ("V.getValueType().isFixedLengthVector() && \"Expected to insert a fixed length vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3324, __PRETTY_FUNCTION__)) | ||||
3324 | "Expected to insert a fixed length vector!")((V.getValueType().isFixedLengthVector() && "Expected to insert a fixed length vector!" ) ? static_cast<void> (0) : __assert_fail ("V.getValueType().isFixedLengthVector() && \"Expected to insert a fixed length vector!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 3324, __PRETTY_FUNCTION__)); | ||||
3325 | |||||
3326 | SDLoc DL(V); | ||||
3327 | switch (V.getValueType().getSizeInBits()) { | ||||
3328 | case 64: { | ||||
3329 | auto SubReg = DAG->getTargetConstant(AArch64::dsub, DL, MVT::i32); | ||||
3330 | auto Container = DAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT); | ||||
3331 | return DAG->getMachineNode(TargetOpcode::INSERT_SUBREG, DL, VT, | ||||
3332 | SDValue(Container, 0), V, SubReg); | ||||
3333 | } | ||||
3334 | case 128: { | ||||
3335 | auto SubReg = DAG->getTargetConstant(AArch64::zsub, DL, MVT::i32); | ||||
3336 | auto Container = DAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT); | ||||
3337 | return DAG->getMachineNode(TargetOpcode::INSERT_SUBREG, DL, VT, | ||||
3338 | SDValue(Container, 0), V, SubReg); | ||||
3339 | } | ||||
3340 | default: { | ||||
3341 | auto RC = DAG->getTargetConstant(AArch64::ZPRRegClassID, DL, MVT::i64); | ||||
3342 | return DAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, DL, VT, V, RC); | ||||
3343 | } | ||||
3344 | } | ||||
3345 | } | ||||
3346 | |||||
3347 | void AArch64DAGToDAGISel::Select(SDNode *Node) { | ||||
3348 | // If we have a custom node, we already have selected! | ||||
3349 | if (Node->isMachineOpcode()) { | ||||
3350 | LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("aarch64-isel")) { errs() << "== "; Node->dump(CurDAG ); errs() << "\n"; } } while (false); | ||||
3351 | Node->setNodeId(-1); | ||||
3352 | return; | ||||
3353 | } | ||||
3354 | |||||
3355 | // Few custom selection stuff. | ||||
3356 | EVT VT = Node->getValueType(0); | ||||
3357 | |||||
3358 | switch (Node->getOpcode()) { | ||||
3359 | default: | ||||
3360 | break; | ||||
3361 | |||||
3362 | case ISD::ATOMIC_CMP_SWAP: | ||||
3363 | if (SelectCMP_SWAP(Node)) | ||||
3364 | return; | ||||
3365 | break; | ||||
3366 | |||||
3367 | case ISD::READ_REGISTER: | ||||
3368 | if (tryReadRegister(Node)) | ||||
3369 | return; | ||||
3370 | break; | ||||
3371 | |||||
3372 | case ISD::WRITE_REGISTER: | ||||
3373 | if (tryWriteRegister(Node)) | ||||
3374 | return; | ||||
3375 | break; | ||||
3376 | |||||
3377 | case ISD::ADD: | ||||
3378 | if (tryMLAV64LaneV128(Node)) | ||||
3379 | return; | ||||
3380 | break; | ||||
3381 | |||||
3382 | case ISD::LOAD: { | ||||
3383 | // Try to select as an indexed load. Fall through to normal processing | ||||
3384 | // if we can't. | ||||
3385 | if (tryIndexedLoad(Node)) | ||||
3386 | return; | ||||
3387 | break; | ||||
3388 | } | ||||
3389 | |||||
3390 | case ISD::SRL: | ||||
3391 | case ISD::AND: | ||||
3392 | case ISD::SRA: | ||||
3393 | case ISD::SIGN_EXTEND_INREG: | ||||
3394 | if (tryBitfieldExtractOp(Node)) | ||||
3395 | return; | ||||
3396 | if (tryBitfieldInsertInZeroOp(Node)) | ||||
3397 | return; | ||||
3398 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
3399 | case ISD::ROTR: | ||||
3400 | case ISD::SHL: | ||||
3401 | if (tryShiftAmountMod(Node)) | ||||
3402 | return; | ||||
3403 | break; | ||||
3404 | |||||
3405 | case ISD::SIGN_EXTEND: | ||||
3406 | if (tryBitfieldExtractOpFromSExt(Node)) | ||||
3407 | return; | ||||
3408 | break; | ||||
3409 | |||||
3410 | case ISD::FP_EXTEND: | ||||
3411 | if (tryHighFPExt(Node)) | ||||
3412 | return; | ||||
3413 | break; | ||||
3414 | |||||
3415 | case ISD::OR: | ||||
3416 | if (tryBitfieldInsertOp(Node)) | ||||
3417 | return; | ||||
3418 | break; | ||||
3419 | |||||
3420 | case ISD::EXTRACT_SUBVECTOR: { | ||||
3421 | // Bail when not a "cast" like extract_subvector. | ||||
3422 | if (cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue() != 0) | ||||
3423 | break; | ||||
3424 | |||||
3425 | // Bail when normal isel can do the job. | ||||
3426 | EVT InVT = Node->getOperand(0).getValueType(); | ||||
3427 | if (VT.isScalableVector() || InVT.isFixedLengthVector()) | ||||
3428 | break; | ||||
3429 | |||||
3430 | // NOTE: We can only get here when doing fixed length SVE code generation. | ||||
3431 | // We do manual selection because the types involved are not linked to real | ||||
3432 | // registers (despite being legal) and must be coerced into SVE registers. | ||||
3433 | // | ||||
3434 | // NOTE: If the above changes, be aware that selection will still not work | ||||
3435 | // because the td definition of extract_vector does not support extracting | ||||
3436 | // a fixed length vector from a scalable vector. | ||||
3437 | |||||
3438 | ReplaceNode(Node, extractSubReg(CurDAG, VT, Node->getOperand(0))); | ||||
3439 | return; | ||||
3440 | } | ||||
3441 | |||||
3442 | case ISD::INSERT_SUBVECTOR: { | ||||
3443 | // Bail when not a "cast" like insert_subvector. | ||||
3444 | if (cast<ConstantSDNode>(Node->getOperand(2))->getZExtValue() != 0) | ||||
3445 | break; | ||||
3446 | if (!Node->getOperand(0).isUndef()) | ||||
3447 | break; | ||||
3448 | |||||
3449 | // Bail when normal isel should do the job. | ||||
3450 | EVT InVT = Node->getOperand(1).getValueType(); | ||||
3451 | if (VT.isFixedLengthVector() || InVT.isScalableVector()) | ||||
3452 | break; | ||||
3453 | |||||
3454 | // NOTE: We can only get here when doing fixed length SVE code generation. | ||||
3455 | // We do manual selection because the types involved are not linked to real | ||||
3456 | // registers (despite being legal) and must be coerced into SVE registers. | ||||
3457 | // | ||||
3458 | // NOTE: If the above changes, be aware that selection will still not work | ||||
3459 | // because the td definition of insert_vector does not support inserting a | ||||
3460 | // fixed length vector into a scalable vector. | ||||
3461 | |||||
3462 | ReplaceNode(Node, insertSubReg(CurDAG, VT, Node->getOperand(1))); | ||||
3463 | return; | ||||
3464 | } | ||||
3465 | |||||
3466 | case ISD::Constant: { | ||||
3467 | // Materialize zero constants as copies from WZR/XZR. This allows | ||||
3468 | // the coalescer to propagate these into other instructions. | ||||
3469 | ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node); | ||||
3470 | if (ConstNode->isNullValue()) { | ||||
3471 | if (VT == MVT::i32) { | ||||
3472 | SDValue New = CurDAG->getCopyFromReg( | ||||
3473 | CurDAG->getEntryNode(), SDLoc(Node), AArch64::WZR, MVT::i32); | ||||
3474 | ReplaceNode(Node, New.getNode()); | ||||
3475 | return; | ||||
3476 | } else if (VT == MVT::i64) { | ||||
3477 | SDValue New = CurDAG->getCopyFromReg( | ||||
3478 | CurDAG->getEntryNode(), SDLoc(Node), AArch64::XZR, MVT::i64); | ||||
3479 | ReplaceNode(Node, New.getNode()); | ||||
3480 | return; | ||||
3481 | } | ||||
3482 | } | ||||
3483 | break; | ||||
3484 | } | ||||
3485 | |||||
3486 | case ISD::FrameIndex: { | ||||
3487 | // Selects to ADDXri FI, 0 which in turn will become ADDXri SP, imm. | ||||
3488 | int FI = cast<FrameIndexSDNode>(Node)->getIndex(); | ||||
3489 | unsigned Shifter = AArch64_AM::getShifterImm(AArch64_AM::LSL, 0); | ||||
3490 | const TargetLowering *TLI = getTargetLowering(); | ||||
3491 | SDValue TFI = CurDAG->getTargetFrameIndex( | ||||
3492 | FI, TLI->getPointerTy(CurDAG->getDataLayout())); | ||||
3493 | SDLoc DL(Node); | ||||
3494 | SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, DL, MVT::i32), | ||||
3495 | CurDAG->getTargetConstant(Shifter, DL, MVT::i32) }; | ||||
3496 | CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64, Ops); | ||||
3497 | return; | ||||
3498 | } | ||||
3499 | case ISD::INTRINSIC_W_CHAIN: { | ||||
3500 | unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); | ||||
3501 | switch (IntNo) { | ||||
3502 | default: | ||||
3503 | break; | ||||
3504 | case Intrinsic::aarch64_ldaxp: | ||||
3505 | case Intrinsic::aarch64_ldxp: { | ||||
3506 | unsigned Op = | ||||
3507 | IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX; | ||||
3508 | SDValue MemAddr = Node->getOperand(2); | ||||
3509 | SDLoc DL(Node); | ||||
3510 | SDValue Chain = Node->getOperand(0); | ||||
3511 | |||||
3512 | SDNode *Ld = CurDAG->getMachineNode(Op, DL, MVT::i64, MVT::i64, | ||||
3513 | MVT::Other, MemAddr, Chain); | ||||
3514 | |||||
3515 | // Transfer memoperands. | ||||
3516 | MachineMemOperand *MemOp = | ||||
3517 | cast<MemIntrinsicSDNode>(Node)->getMemOperand(); | ||||
3518 | CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {MemOp}); | ||||
3519 | ReplaceNode(Node, Ld); | ||||
3520 | return; | ||||
3521 | } | ||||
3522 | case Intrinsic::aarch64_stlxp: | ||||
3523 | case Intrinsic::aarch64_stxp: { | ||||
3524 | unsigned Op = | ||||
3525 | IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX; | ||||
3526 | SDLoc DL(Node); | ||||
3527 | SDValue Chain = Node->getOperand(0); | ||||
3528 | SDValue ValLo = Node->getOperand(2); | ||||
3529 | SDValue ValHi = Node->getOperand(3); | ||||
3530 | SDValue MemAddr = Node->getOperand(4); | ||||
3531 | |||||
3532 | // Place arguments in the right order. | ||||
3533 | SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain}; | ||||
3534 | |||||
3535 | SDNode *St = CurDAG->getMachineNode(Op, DL, MVT::i32, MVT::Other, Ops); | ||||
3536 | // Transfer memoperands. | ||||
3537 | MachineMemOperand *MemOp = | ||||
3538 | cast<MemIntrinsicSDNode>(Node)->getMemOperand(); | ||||
3539 | CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp}); | ||||
3540 | |||||
3541 | ReplaceNode(Node, St); | ||||
3542 | return; | ||||
3543 | } | ||||
3544 | case Intrinsic::aarch64_neon_ld1x2: | ||||
3545 | if (VT == MVT::v8i8) { | ||||
3546 | SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0); | ||||
3547 | return; | ||||
3548 | } else if (VT == MVT::v16i8) { | ||||
3549 | SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0); | ||||
3550 | return; | ||||
3551 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3552 | SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0); | ||||
3553 | return; | ||||
3554 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3555 | SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0); | ||||
3556 | return; | ||||
3557 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3558 | SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0); | ||||
3559 | return; | ||||
3560 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3561 | SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0); | ||||
3562 | return; | ||||
3563 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3564 | SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0); | ||||
3565 | return; | ||||
3566 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3567 | SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0); | ||||
3568 | return; | ||||
3569 | } | ||||
3570 | break; | ||||
3571 | case Intrinsic::aarch64_neon_ld1x3: | ||||
3572 | if (VT == MVT::v8i8) { | ||||
3573 | SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0); | ||||
3574 | return; | ||||
3575 | } else if (VT == MVT::v16i8) { | ||||
3576 | SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0); | ||||
3577 | return; | ||||
3578 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3579 | SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0); | ||||
3580 | return; | ||||
3581 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3582 | SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0); | ||||
3583 | return; | ||||
3584 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3585 | SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0); | ||||
3586 | return; | ||||
3587 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3588 | SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0); | ||||
3589 | return; | ||||
3590 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3591 | SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0); | ||||
3592 | return; | ||||
3593 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3594 | SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0); | ||||
3595 | return; | ||||
3596 | } | ||||
3597 | break; | ||||
3598 | case Intrinsic::aarch64_neon_ld1x4: | ||||
3599 | if (VT == MVT::v8i8) { | ||||
3600 | SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0); | ||||
3601 | return; | ||||
3602 | } else if (VT == MVT::v16i8) { | ||||
3603 | SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0); | ||||
3604 | return; | ||||
3605 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3606 | SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0); | ||||
3607 | return; | ||||
3608 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3609 | SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0); | ||||
3610 | return; | ||||
3611 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3612 | SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0); | ||||
3613 | return; | ||||
3614 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3615 | SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0); | ||||
3616 | return; | ||||
3617 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3618 | SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0); | ||||
3619 | return; | ||||
3620 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3621 | SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0); | ||||
3622 | return; | ||||
3623 | } | ||||
3624 | break; | ||||
3625 | case Intrinsic::aarch64_neon_ld2: | ||||
3626 | if (VT == MVT::v8i8) { | ||||
3627 | SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0); | ||||
3628 | return; | ||||
3629 | } else if (VT == MVT::v16i8) { | ||||
3630 | SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0); | ||||
3631 | return; | ||||
3632 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3633 | SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0); | ||||
3634 | return; | ||||
3635 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3636 | SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0); | ||||
3637 | return; | ||||
3638 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3639 | SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0); | ||||
3640 | return; | ||||
3641 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3642 | SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0); | ||||
3643 | return; | ||||
3644 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3645 | SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0); | ||||
3646 | return; | ||||
3647 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3648 | SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0); | ||||
3649 | return; | ||||
3650 | } | ||||
3651 | break; | ||||
3652 | case Intrinsic::aarch64_neon_ld3: | ||||
3653 | if (VT == MVT::v8i8) { | ||||
3654 | SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0); | ||||
3655 | return; | ||||
3656 | } else if (VT == MVT::v16i8) { | ||||
3657 | SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0); | ||||
3658 | return; | ||||
3659 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3660 | SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0); | ||||
3661 | return; | ||||
3662 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3663 | SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0); | ||||
3664 | return; | ||||
3665 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3666 | SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0); | ||||
3667 | return; | ||||
3668 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3669 | SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0); | ||||
3670 | return; | ||||
3671 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3672 | SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0); | ||||
3673 | return; | ||||
3674 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3675 | SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0); | ||||
3676 | return; | ||||
3677 | } | ||||
3678 | break; | ||||
3679 | case Intrinsic::aarch64_neon_ld4: | ||||
3680 | if (VT == MVT::v8i8) { | ||||
3681 | SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0); | ||||
3682 | return; | ||||
3683 | } else if (VT == MVT::v16i8) { | ||||
3684 | SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0); | ||||
3685 | return; | ||||
3686 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3687 | SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0); | ||||
3688 | return; | ||||
3689 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3690 | SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0); | ||||
3691 | return; | ||||
3692 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3693 | SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0); | ||||
3694 | return; | ||||
3695 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3696 | SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0); | ||||
3697 | return; | ||||
3698 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3699 | SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0); | ||||
3700 | return; | ||||
3701 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3702 | SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0); | ||||
3703 | return; | ||||
3704 | } | ||||
3705 | break; | ||||
3706 | case Intrinsic::aarch64_neon_ld2r: | ||||
3707 | if (VT == MVT::v8i8) { | ||||
3708 | SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0); | ||||
3709 | return; | ||||
3710 | } else if (VT == MVT::v16i8) { | ||||
3711 | SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0); | ||||
3712 | return; | ||||
3713 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3714 | SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0); | ||||
3715 | return; | ||||
3716 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3717 | SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0); | ||||
3718 | return; | ||||
3719 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3720 | SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0); | ||||
3721 | return; | ||||
3722 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3723 | SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0); | ||||
3724 | return; | ||||
3725 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3726 | SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0); | ||||
3727 | return; | ||||
3728 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3729 | SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0); | ||||
3730 | return; | ||||
3731 | } | ||||
3732 | break; | ||||
3733 | case Intrinsic::aarch64_neon_ld3r: | ||||
3734 | if (VT == MVT::v8i8) { | ||||
3735 | SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0); | ||||
3736 | return; | ||||
3737 | } else if (VT == MVT::v16i8) { | ||||
3738 | SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0); | ||||
3739 | return; | ||||
3740 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3741 | SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0); | ||||
3742 | return; | ||||
3743 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3744 | SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0); | ||||
3745 | return; | ||||
3746 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3747 | SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0); | ||||
3748 | return; | ||||
3749 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3750 | SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0); | ||||
3751 | return; | ||||
3752 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3753 | SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0); | ||||
3754 | return; | ||||
3755 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3756 | SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0); | ||||
3757 | return; | ||||
3758 | } | ||||
3759 | break; | ||||
3760 | case Intrinsic::aarch64_neon_ld4r: | ||||
3761 | if (VT == MVT::v8i8) { | ||||
3762 | SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0); | ||||
3763 | return; | ||||
3764 | } else if (VT == MVT::v16i8) { | ||||
3765 | SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0); | ||||
3766 | return; | ||||
3767 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
3768 | SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0); | ||||
3769 | return; | ||||
3770 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
3771 | SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0); | ||||
3772 | return; | ||||
3773 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3774 | SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0); | ||||
3775 | return; | ||||
3776 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3777 | SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0); | ||||
3778 | return; | ||||
3779 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3780 | SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0); | ||||
3781 | return; | ||||
3782 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3783 | SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0); | ||||
3784 | return; | ||||
3785 | } | ||||
3786 | break; | ||||
3787 | case Intrinsic::aarch64_neon_ld2lane: | ||||
3788 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
3789 | SelectLoadLane(Node, 2, AArch64::LD2i8); | ||||
3790 | return; | ||||
3791 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
3792 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
3793 | SelectLoadLane(Node, 2, AArch64::LD2i16); | ||||
3794 | return; | ||||
3795 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
3796 | VT == MVT::v2f32) { | ||||
3797 | SelectLoadLane(Node, 2, AArch64::LD2i32); | ||||
3798 | return; | ||||
3799 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
3800 | VT == MVT::v1f64) { | ||||
3801 | SelectLoadLane(Node, 2, AArch64::LD2i64); | ||||
3802 | return; | ||||
3803 | } | ||||
3804 | break; | ||||
3805 | case Intrinsic::aarch64_neon_ld3lane: | ||||
3806 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
3807 | SelectLoadLane(Node, 3, AArch64::LD3i8); | ||||
3808 | return; | ||||
3809 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
3810 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
3811 | SelectLoadLane(Node, 3, AArch64::LD3i16); | ||||
3812 | return; | ||||
3813 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
3814 | VT == MVT::v2f32) { | ||||
3815 | SelectLoadLane(Node, 3, AArch64::LD3i32); | ||||
3816 | return; | ||||
3817 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
3818 | VT == MVT::v1f64) { | ||||
3819 | SelectLoadLane(Node, 3, AArch64::LD3i64); | ||||
3820 | return; | ||||
3821 | } | ||||
3822 | break; | ||||
3823 | case Intrinsic::aarch64_neon_ld4lane: | ||||
3824 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
3825 | SelectLoadLane(Node, 4, AArch64::LD4i8); | ||||
3826 | return; | ||||
3827 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
3828 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
3829 | SelectLoadLane(Node, 4, AArch64::LD4i16); | ||||
3830 | return; | ||||
3831 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
3832 | VT == MVT::v2f32) { | ||||
3833 | SelectLoadLane(Node, 4, AArch64::LD4i32); | ||||
3834 | return; | ||||
3835 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
3836 | VT == MVT::v1f64) { | ||||
3837 | SelectLoadLane(Node, 4, AArch64::LD4i64); | ||||
3838 | return; | ||||
3839 | } | ||||
3840 | break; | ||||
3841 | case Intrinsic::aarch64_ld64b: | ||||
3842 | SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0); | ||||
3843 | return; | ||||
3844 | } | ||||
3845 | } break; | ||||
3846 | case ISD::INTRINSIC_WO_CHAIN: { | ||||
3847 | unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue(); | ||||
3848 | switch (IntNo) { | ||||
3849 | default: | ||||
3850 | break; | ||||
3851 | case Intrinsic::aarch64_tagp: | ||||
3852 | SelectTagP(Node); | ||||
3853 | return; | ||||
3854 | case Intrinsic::aarch64_neon_tbl2: | ||||
3855 | SelectTable(Node, 2, | ||||
3856 | VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two, | ||||
3857 | false); | ||||
3858 | return; | ||||
3859 | case Intrinsic::aarch64_neon_tbl3: | ||||
3860 | SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three | ||||
3861 | : AArch64::TBLv16i8Three, | ||||
3862 | false); | ||||
3863 | return; | ||||
3864 | case Intrinsic::aarch64_neon_tbl4: | ||||
3865 | SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four | ||||
3866 | : AArch64::TBLv16i8Four, | ||||
3867 | false); | ||||
3868 | return; | ||||
3869 | case Intrinsic::aarch64_neon_tbx2: | ||||
3870 | SelectTable(Node, 2, | ||||
3871 | VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two, | ||||
3872 | true); | ||||
3873 | return; | ||||
3874 | case Intrinsic::aarch64_neon_tbx3: | ||||
3875 | SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three | ||||
3876 | : AArch64::TBXv16i8Three, | ||||
3877 | true); | ||||
3878 | return; | ||||
3879 | case Intrinsic::aarch64_neon_tbx4: | ||||
3880 | SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four | ||||
3881 | : AArch64::TBXv16i8Four, | ||||
3882 | true); | ||||
3883 | return; | ||||
3884 | case Intrinsic::aarch64_neon_smull: | ||||
3885 | case Intrinsic::aarch64_neon_umull: | ||||
3886 | if (tryMULLV64LaneV128(IntNo, Node)) | ||||
3887 | return; | ||||
3888 | break; | ||||
3889 | } | ||||
3890 | break; | ||||
3891 | } | ||||
3892 | case ISD::INTRINSIC_VOID: { | ||||
3893 | unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); | ||||
3894 | if (Node->getNumOperands() >= 3) | ||||
3895 | VT = Node->getOperand(2)->getValueType(0); | ||||
3896 | switch (IntNo) { | ||||
3897 | default: | ||||
3898 | break; | ||||
3899 | case Intrinsic::aarch64_neon_st1x2: { | ||||
3900 | if (VT == MVT::v8i8) { | ||||
3901 | SelectStore(Node, 2, AArch64::ST1Twov8b); | ||||
3902 | return; | ||||
3903 | } else if (VT == MVT::v16i8) { | ||||
3904 | SelectStore(Node, 2, AArch64::ST1Twov16b); | ||||
3905 | return; | ||||
3906 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
3907 | VT == MVT::v4bf16) { | ||||
3908 | SelectStore(Node, 2, AArch64::ST1Twov4h); | ||||
3909 | return; | ||||
3910 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || | ||||
3911 | VT == MVT::v8bf16) { | ||||
3912 | SelectStore(Node, 2, AArch64::ST1Twov8h); | ||||
3913 | return; | ||||
3914 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3915 | SelectStore(Node, 2, AArch64::ST1Twov2s); | ||||
3916 | return; | ||||
3917 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3918 | SelectStore(Node, 2, AArch64::ST1Twov4s); | ||||
3919 | return; | ||||
3920 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3921 | SelectStore(Node, 2, AArch64::ST1Twov2d); | ||||
3922 | return; | ||||
3923 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3924 | SelectStore(Node, 2, AArch64::ST1Twov1d); | ||||
3925 | return; | ||||
3926 | } | ||||
3927 | break; | ||||
3928 | } | ||||
3929 | case Intrinsic::aarch64_neon_st1x3: { | ||||
3930 | if (VT == MVT::v8i8) { | ||||
3931 | SelectStore(Node, 3, AArch64::ST1Threev8b); | ||||
3932 | return; | ||||
3933 | } else if (VT == MVT::v16i8) { | ||||
3934 | SelectStore(Node, 3, AArch64::ST1Threev16b); | ||||
3935 | return; | ||||
3936 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
3937 | VT == MVT::v4bf16) { | ||||
3938 | SelectStore(Node, 3, AArch64::ST1Threev4h); | ||||
3939 | return; | ||||
3940 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || | ||||
3941 | VT == MVT::v8bf16) { | ||||
3942 | SelectStore(Node, 3, AArch64::ST1Threev8h); | ||||
3943 | return; | ||||
3944 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3945 | SelectStore(Node, 3, AArch64::ST1Threev2s); | ||||
3946 | return; | ||||
3947 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3948 | SelectStore(Node, 3, AArch64::ST1Threev4s); | ||||
3949 | return; | ||||
3950 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3951 | SelectStore(Node, 3, AArch64::ST1Threev2d); | ||||
3952 | return; | ||||
3953 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3954 | SelectStore(Node, 3, AArch64::ST1Threev1d); | ||||
3955 | return; | ||||
3956 | } | ||||
3957 | break; | ||||
3958 | } | ||||
3959 | case Intrinsic::aarch64_neon_st1x4: { | ||||
3960 | if (VT == MVT::v8i8) { | ||||
3961 | SelectStore(Node, 4, AArch64::ST1Fourv8b); | ||||
3962 | return; | ||||
3963 | } else if (VT == MVT::v16i8) { | ||||
3964 | SelectStore(Node, 4, AArch64::ST1Fourv16b); | ||||
3965 | return; | ||||
3966 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
3967 | VT == MVT::v4bf16) { | ||||
3968 | SelectStore(Node, 4, AArch64::ST1Fourv4h); | ||||
3969 | return; | ||||
3970 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || | ||||
3971 | VT == MVT::v8bf16) { | ||||
3972 | SelectStore(Node, 4, AArch64::ST1Fourv8h); | ||||
3973 | return; | ||||
3974 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
3975 | SelectStore(Node, 4, AArch64::ST1Fourv2s); | ||||
3976 | return; | ||||
3977 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
3978 | SelectStore(Node, 4, AArch64::ST1Fourv4s); | ||||
3979 | return; | ||||
3980 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
3981 | SelectStore(Node, 4, AArch64::ST1Fourv2d); | ||||
3982 | return; | ||||
3983 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
3984 | SelectStore(Node, 4, AArch64::ST1Fourv1d); | ||||
3985 | return; | ||||
3986 | } | ||||
3987 | break; | ||||
3988 | } | ||||
3989 | case Intrinsic::aarch64_neon_st2: { | ||||
3990 | if (VT == MVT::v8i8) { | ||||
3991 | SelectStore(Node, 2, AArch64::ST2Twov8b); | ||||
3992 | return; | ||||
3993 | } else if (VT == MVT::v16i8) { | ||||
3994 | SelectStore(Node, 2, AArch64::ST2Twov16b); | ||||
3995 | return; | ||||
3996 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
3997 | VT == MVT::v4bf16) { | ||||
3998 | SelectStore(Node, 2, AArch64::ST2Twov4h); | ||||
3999 | return; | ||||
4000 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || | ||||
4001 | VT == MVT::v8bf16) { | ||||
4002 | SelectStore(Node, 2, AArch64::ST2Twov8h); | ||||
4003 | return; | ||||
4004 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4005 | SelectStore(Node, 2, AArch64::ST2Twov2s); | ||||
4006 | return; | ||||
4007 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4008 | SelectStore(Node, 2, AArch64::ST2Twov4s); | ||||
4009 | return; | ||||
4010 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4011 | SelectStore(Node, 2, AArch64::ST2Twov2d); | ||||
4012 | return; | ||||
4013 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4014 | SelectStore(Node, 2, AArch64::ST1Twov1d); | ||||
4015 | return; | ||||
4016 | } | ||||
4017 | break; | ||||
4018 | } | ||||
4019 | case Intrinsic::aarch64_neon_st3: { | ||||
4020 | if (VT == MVT::v8i8) { | ||||
4021 | SelectStore(Node, 3, AArch64::ST3Threev8b); | ||||
4022 | return; | ||||
4023 | } else if (VT == MVT::v16i8) { | ||||
4024 | SelectStore(Node, 3, AArch64::ST3Threev16b); | ||||
4025 | return; | ||||
4026 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4027 | VT == MVT::v4bf16) { | ||||
4028 | SelectStore(Node, 3, AArch64::ST3Threev4h); | ||||
4029 | return; | ||||
4030 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || | ||||
4031 | VT == MVT::v8bf16) { | ||||
4032 | SelectStore(Node, 3, AArch64::ST3Threev8h); | ||||
4033 | return; | ||||
4034 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4035 | SelectStore(Node, 3, AArch64::ST3Threev2s); | ||||
4036 | return; | ||||
4037 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4038 | SelectStore(Node, 3, AArch64::ST3Threev4s); | ||||
4039 | return; | ||||
4040 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4041 | SelectStore(Node, 3, AArch64::ST3Threev2d); | ||||
4042 | return; | ||||
4043 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4044 | SelectStore(Node, 3, AArch64::ST1Threev1d); | ||||
4045 | return; | ||||
4046 | } | ||||
4047 | break; | ||||
4048 | } | ||||
4049 | case Intrinsic::aarch64_neon_st4: { | ||||
4050 | if (VT == MVT::v8i8) { | ||||
4051 | SelectStore(Node, 4, AArch64::ST4Fourv8b); | ||||
4052 | return; | ||||
4053 | } else if (VT == MVT::v16i8) { | ||||
4054 | SelectStore(Node, 4, AArch64::ST4Fourv16b); | ||||
4055 | return; | ||||
4056 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4057 | VT == MVT::v4bf16) { | ||||
4058 | SelectStore(Node, 4, AArch64::ST4Fourv4h); | ||||
4059 | return; | ||||
4060 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || | ||||
4061 | VT == MVT::v8bf16) { | ||||
4062 | SelectStore(Node, 4, AArch64::ST4Fourv8h); | ||||
4063 | return; | ||||
4064 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4065 | SelectStore(Node, 4, AArch64::ST4Fourv2s); | ||||
4066 | return; | ||||
4067 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4068 | SelectStore(Node, 4, AArch64::ST4Fourv4s); | ||||
4069 | return; | ||||
4070 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4071 | SelectStore(Node, 4, AArch64::ST4Fourv2d); | ||||
4072 | return; | ||||
4073 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4074 | SelectStore(Node, 4, AArch64::ST1Fourv1d); | ||||
4075 | return; | ||||
4076 | } | ||||
4077 | break; | ||||
4078 | } | ||||
4079 | case Intrinsic::aarch64_neon_st2lane: { | ||||
4080 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4081 | SelectStoreLane(Node, 2, AArch64::ST2i8); | ||||
4082 | return; | ||||
4083 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4084 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4085 | SelectStoreLane(Node, 2, AArch64::ST2i16); | ||||
4086 | return; | ||||
4087 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4088 | VT == MVT::v2f32) { | ||||
4089 | SelectStoreLane(Node, 2, AArch64::ST2i32); | ||||
4090 | return; | ||||
4091 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4092 | VT == MVT::v1f64) { | ||||
4093 | SelectStoreLane(Node, 2, AArch64::ST2i64); | ||||
4094 | return; | ||||
4095 | } | ||||
4096 | break; | ||||
4097 | } | ||||
4098 | case Intrinsic::aarch64_neon_st3lane: { | ||||
4099 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4100 | SelectStoreLane(Node, 3, AArch64::ST3i8); | ||||
4101 | return; | ||||
4102 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4103 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4104 | SelectStoreLane(Node, 3, AArch64::ST3i16); | ||||
4105 | return; | ||||
4106 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4107 | VT == MVT::v2f32) { | ||||
4108 | SelectStoreLane(Node, 3, AArch64::ST3i32); | ||||
4109 | return; | ||||
4110 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4111 | VT == MVT::v1f64) { | ||||
4112 | SelectStoreLane(Node, 3, AArch64::ST3i64); | ||||
4113 | return; | ||||
4114 | } | ||||
4115 | break; | ||||
4116 | } | ||||
4117 | case Intrinsic::aarch64_neon_st4lane: { | ||||
4118 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4119 | SelectStoreLane(Node, 4, AArch64::ST4i8); | ||||
4120 | return; | ||||
4121 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4122 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4123 | SelectStoreLane(Node, 4, AArch64::ST4i16); | ||||
4124 | return; | ||||
4125 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4126 | VT == MVT::v2f32) { | ||||
4127 | SelectStoreLane(Node, 4, AArch64::ST4i32); | ||||
4128 | return; | ||||
4129 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4130 | VT == MVT::v1f64) { | ||||
4131 | SelectStoreLane(Node, 4, AArch64::ST4i64); | ||||
4132 | return; | ||||
4133 | } | ||||
4134 | break; | ||||
4135 | } | ||||
4136 | case Intrinsic::aarch64_sve_st2: { | ||||
4137 | if (VT == MVT::nxv16i8) { | ||||
4138 | SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM); | ||||
4139 | return; | ||||
4140 | } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 || | ||||
4141 | (VT == MVT::nxv8bf16 && Subtarget->hasBF16())) { | ||||
4142 | SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM); | ||||
4143 | return; | ||||
4144 | } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) { | ||||
4145 | SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM); | ||||
4146 | return; | ||||
4147 | } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) { | ||||
4148 | SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM); | ||||
4149 | return; | ||||
4150 | } | ||||
4151 | break; | ||||
4152 | } | ||||
4153 | case Intrinsic::aarch64_sve_st3: { | ||||
4154 | if (VT == MVT::nxv16i8) { | ||||
4155 | SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM); | ||||
4156 | return; | ||||
4157 | } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 || | ||||
4158 | (VT == MVT::nxv8bf16 && Subtarget->hasBF16())) { | ||||
4159 | SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM); | ||||
4160 | return; | ||||
4161 | } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) { | ||||
4162 | SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM); | ||||
4163 | return; | ||||
4164 | } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) { | ||||
4165 | SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM); | ||||
4166 | return; | ||||
4167 | } | ||||
4168 | break; | ||||
4169 | } | ||||
4170 | case Intrinsic::aarch64_sve_st4: { | ||||
4171 | if (VT == MVT::nxv16i8) { | ||||
4172 | SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM); | ||||
4173 | return; | ||||
4174 | } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 || | ||||
4175 | (VT == MVT::nxv8bf16 && Subtarget->hasBF16())) { | ||||
4176 | SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM); | ||||
4177 | return; | ||||
4178 | } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) { | ||||
4179 | SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM); | ||||
4180 | return; | ||||
4181 | } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) { | ||||
4182 | SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM); | ||||
4183 | return; | ||||
4184 | } | ||||
4185 | break; | ||||
4186 | } | ||||
4187 | } | ||||
4188 | break; | ||||
4189 | } | ||||
4190 | case AArch64ISD::LD2post: { | ||||
4191 | if (VT == MVT::v8i8) { | ||||
4192 | SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0); | ||||
4193 | return; | ||||
4194 | } else if (VT == MVT::v16i8) { | ||||
4195 | SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0); | ||||
4196 | return; | ||||
4197 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4198 | SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0); | ||||
4199 | return; | ||||
4200 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4201 | SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0); | ||||
4202 | return; | ||||
4203 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4204 | SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0); | ||||
4205 | return; | ||||
4206 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4207 | SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0); | ||||
4208 | return; | ||||
4209 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4210 | SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0); | ||||
4211 | return; | ||||
4212 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4213 | SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0); | ||||
4214 | return; | ||||
4215 | } | ||||
4216 | break; | ||||
4217 | } | ||||
4218 | case AArch64ISD::LD3post: { | ||||
4219 | if (VT == MVT::v8i8) { | ||||
4220 | SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0); | ||||
4221 | return; | ||||
4222 | } else if (VT == MVT::v16i8) { | ||||
4223 | SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0); | ||||
4224 | return; | ||||
4225 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4226 | SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0); | ||||
4227 | return; | ||||
4228 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4229 | SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0); | ||||
4230 | return; | ||||
4231 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4232 | SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0); | ||||
4233 | return; | ||||
4234 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4235 | SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0); | ||||
4236 | return; | ||||
4237 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4238 | SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0); | ||||
4239 | return; | ||||
4240 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4241 | SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0); | ||||
4242 | return; | ||||
4243 | } | ||||
4244 | break; | ||||
4245 | } | ||||
4246 | case AArch64ISD::LD4post: { | ||||
4247 | if (VT == MVT::v8i8) { | ||||
4248 | SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0); | ||||
4249 | return; | ||||
4250 | } else if (VT == MVT::v16i8) { | ||||
4251 | SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0); | ||||
4252 | return; | ||||
4253 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4254 | SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0); | ||||
4255 | return; | ||||
4256 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4257 | SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0); | ||||
4258 | return; | ||||
4259 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4260 | SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0); | ||||
4261 | return; | ||||
4262 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4263 | SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0); | ||||
4264 | return; | ||||
4265 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4266 | SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0); | ||||
4267 | return; | ||||
4268 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4269 | SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0); | ||||
4270 | return; | ||||
4271 | } | ||||
4272 | break; | ||||
4273 | } | ||||
4274 | case AArch64ISD::LD1x2post: { | ||||
4275 | if (VT == MVT::v8i8) { | ||||
4276 | SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0); | ||||
4277 | return; | ||||
4278 | } else if (VT == MVT::v16i8) { | ||||
4279 | SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0); | ||||
4280 | return; | ||||
4281 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4282 | SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0); | ||||
4283 | return; | ||||
4284 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4285 | SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0); | ||||
4286 | return; | ||||
4287 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4288 | SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0); | ||||
4289 | return; | ||||
4290 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4291 | SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0); | ||||
4292 | return; | ||||
4293 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4294 | SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0); | ||||
4295 | return; | ||||
4296 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4297 | SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0); | ||||
4298 | return; | ||||
4299 | } | ||||
4300 | break; | ||||
4301 | } | ||||
4302 | case AArch64ISD::LD1x3post: { | ||||
4303 | if (VT == MVT::v8i8) { | ||||
4304 | SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0); | ||||
4305 | return; | ||||
4306 | } else if (VT == MVT::v16i8) { | ||||
4307 | SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0); | ||||
4308 | return; | ||||
4309 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4310 | SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0); | ||||
4311 | return; | ||||
4312 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4313 | SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0); | ||||
4314 | return; | ||||
4315 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4316 | SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0); | ||||
4317 | return; | ||||
4318 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4319 | SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0); | ||||
4320 | return; | ||||
4321 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4322 | SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0); | ||||
4323 | return; | ||||
4324 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4325 | SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0); | ||||
4326 | return; | ||||
4327 | } | ||||
4328 | break; | ||||
4329 | } | ||||
4330 | case AArch64ISD::LD1x4post: { | ||||
4331 | if (VT == MVT::v8i8) { | ||||
4332 | SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0); | ||||
4333 | return; | ||||
4334 | } else if (VT == MVT::v16i8) { | ||||
4335 | SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0); | ||||
4336 | return; | ||||
4337 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4338 | SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0); | ||||
4339 | return; | ||||
4340 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4341 | SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0); | ||||
4342 | return; | ||||
4343 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4344 | SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0); | ||||
4345 | return; | ||||
4346 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4347 | SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0); | ||||
4348 | return; | ||||
4349 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4350 | SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0); | ||||
4351 | return; | ||||
4352 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4353 | SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0); | ||||
4354 | return; | ||||
4355 | } | ||||
4356 | break; | ||||
4357 | } | ||||
4358 | case AArch64ISD::LD1DUPpost: { | ||||
4359 | if (VT == MVT::v8i8) { | ||||
4360 | SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0); | ||||
4361 | return; | ||||
4362 | } else if (VT == MVT::v16i8) { | ||||
4363 | SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0); | ||||
4364 | return; | ||||
4365 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4366 | SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0); | ||||
4367 | return; | ||||
4368 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4369 | SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0); | ||||
4370 | return; | ||||
4371 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4372 | SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0); | ||||
4373 | return; | ||||
4374 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4375 | SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0); | ||||
4376 | return; | ||||
4377 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4378 | SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0); | ||||
4379 | return; | ||||
4380 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4381 | SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0); | ||||
4382 | return; | ||||
4383 | } | ||||
4384 | break; | ||||
4385 | } | ||||
4386 | case AArch64ISD::LD2DUPpost: { | ||||
4387 | if (VT == MVT::v8i8) { | ||||
4388 | SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0); | ||||
4389 | return; | ||||
4390 | } else if (VT == MVT::v16i8) { | ||||
4391 | SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0); | ||||
4392 | return; | ||||
4393 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4394 | SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0); | ||||
4395 | return; | ||||
4396 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4397 | SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0); | ||||
4398 | return; | ||||
4399 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4400 | SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0); | ||||
4401 | return; | ||||
4402 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4403 | SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0); | ||||
4404 | return; | ||||
4405 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4406 | SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0); | ||||
4407 | return; | ||||
4408 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4409 | SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0); | ||||
4410 | return; | ||||
4411 | } | ||||
4412 | break; | ||||
4413 | } | ||||
4414 | case AArch64ISD::LD3DUPpost: { | ||||
4415 | if (VT == MVT::v8i8) { | ||||
4416 | SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0); | ||||
4417 | return; | ||||
4418 | } else if (VT == MVT::v16i8) { | ||||
4419 | SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0); | ||||
4420 | return; | ||||
4421 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4422 | SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0); | ||||
4423 | return; | ||||
4424 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4425 | SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0); | ||||
4426 | return; | ||||
4427 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4428 | SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0); | ||||
4429 | return; | ||||
4430 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4431 | SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0); | ||||
4432 | return; | ||||
4433 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4434 | SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0); | ||||
4435 | return; | ||||
4436 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4437 | SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0); | ||||
4438 | return; | ||||
4439 | } | ||||
4440 | break; | ||||
4441 | } | ||||
4442 | case AArch64ISD::LD4DUPpost: { | ||||
4443 | if (VT == MVT::v8i8) { | ||||
4444 | SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0); | ||||
4445 | return; | ||||
4446 | } else if (VT == MVT::v16i8) { | ||||
4447 | SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0); | ||||
4448 | return; | ||||
4449 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4450 | SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0); | ||||
4451 | return; | ||||
4452 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4453 | SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0); | ||||
4454 | return; | ||||
4455 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4456 | SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0); | ||||
4457 | return; | ||||
4458 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4459 | SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0); | ||||
4460 | return; | ||||
4461 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4462 | SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0); | ||||
4463 | return; | ||||
4464 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4465 | SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0); | ||||
4466 | return; | ||||
4467 | } | ||||
4468 | break; | ||||
4469 | } | ||||
4470 | case AArch64ISD::LD1LANEpost: { | ||||
4471 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4472 | SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST); | ||||
4473 | return; | ||||
4474 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4475 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4476 | SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST); | ||||
4477 | return; | ||||
4478 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4479 | VT == MVT::v2f32) { | ||||
4480 | SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST); | ||||
4481 | return; | ||||
4482 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4483 | VT == MVT::v1f64) { | ||||
4484 | SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST); | ||||
4485 | return; | ||||
4486 | } | ||||
4487 | break; | ||||
4488 | } | ||||
4489 | case AArch64ISD::LD2LANEpost: { | ||||
4490 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4491 | SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST); | ||||
4492 | return; | ||||
4493 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4494 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4495 | SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST); | ||||
4496 | return; | ||||
4497 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4498 | VT == MVT::v2f32) { | ||||
4499 | SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST); | ||||
4500 | return; | ||||
4501 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4502 | VT == MVT::v1f64) { | ||||
4503 | SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST); | ||||
4504 | return; | ||||
4505 | } | ||||
4506 | break; | ||||
4507 | } | ||||
4508 | case AArch64ISD::LD3LANEpost: { | ||||
4509 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4510 | SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST); | ||||
4511 | return; | ||||
4512 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4513 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4514 | SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST); | ||||
4515 | return; | ||||
4516 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4517 | VT == MVT::v2f32) { | ||||
4518 | SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST); | ||||
4519 | return; | ||||
4520 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4521 | VT == MVT::v1f64) { | ||||
4522 | SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST); | ||||
4523 | return; | ||||
4524 | } | ||||
4525 | break; | ||||
4526 | } | ||||
4527 | case AArch64ISD::LD4LANEpost: { | ||||
4528 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4529 | SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST); | ||||
4530 | return; | ||||
4531 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4532 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4533 | SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST); | ||||
4534 | return; | ||||
4535 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4536 | VT == MVT::v2f32) { | ||||
4537 | SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST); | ||||
4538 | return; | ||||
4539 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4540 | VT == MVT::v1f64) { | ||||
4541 | SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST); | ||||
4542 | return; | ||||
4543 | } | ||||
4544 | break; | ||||
4545 | } | ||||
4546 | case AArch64ISD::ST2post: { | ||||
4547 | VT = Node->getOperand(1).getValueType(); | ||||
4548 | if (VT == MVT::v8i8) { | ||||
4549 | SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST); | ||||
4550 | return; | ||||
4551 | } else if (VT == MVT::v16i8) { | ||||
4552 | SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST); | ||||
4553 | return; | ||||
4554 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4555 | SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST); | ||||
4556 | return; | ||||
4557 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4558 | SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST); | ||||
4559 | return; | ||||
4560 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4561 | SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST); | ||||
4562 | return; | ||||
4563 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4564 | SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST); | ||||
4565 | return; | ||||
4566 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4567 | SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST); | ||||
4568 | return; | ||||
4569 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4570 | SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST); | ||||
4571 | return; | ||||
4572 | } | ||||
4573 | break; | ||||
4574 | } | ||||
4575 | case AArch64ISD::ST3post: { | ||||
4576 | VT = Node->getOperand(1).getValueType(); | ||||
4577 | if (VT == MVT::v8i8) { | ||||
4578 | SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST); | ||||
4579 | return; | ||||
4580 | } else if (VT == MVT::v16i8) { | ||||
4581 | SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST); | ||||
4582 | return; | ||||
4583 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4584 | SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST); | ||||
4585 | return; | ||||
4586 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4587 | SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST); | ||||
4588 | return; | ||||
4589 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4590 | SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST); | ||||
4591 | return; | ||||
4592 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4593 | SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST); | ||||
4594 | return; | ||||
4595 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4596 | SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST); | ||||
4597 | return; | ||||
4598 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4599 | SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST); | ||||
4600 | return; | ||||
4601 | } | ||||
4602 | break; | ||||
4603 | } | ||||
4604 | case AArch64ISD::ST4post: { | ||||
4605 | VT = Node->getOperand(1).getValueType(); | ||||
4606 | if (VT == MVT::v8i8) { | ||||
4607 | SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST); | ||||
4608 | return; | ||||
4609 | } else if (VT == MVT::v16i8) { | ||||
4610 | SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST); | ||||
4611 | return; | ||||
4612 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4613 | SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST); | ||||
4614 | return; | ||||
4615 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4616 | SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST); | ||||
4617 | return; | ||||
4618 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4619 | SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST); | ||||
4620 | return; | ||||
4621 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4622 | SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST); | ||||
4623 | return; | ||||
4624 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4625 | SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST); | ||||
4626 | return; | ||||
4627 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4628 | SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST); | ||||
4629 | return; | ||||
4630 | } | ||||
4631 | break; | ||||
4632 | } | ||||
4633 | case AArch64ISD::ST1x2post: { | ||||
4634 | VT = Node->getOperand(1).getValueType(); | ||||
4635 | if (VT == MVT::v8i8) { | ||||
4636 | SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST); | ||||
4637 | return; | ||||
4638 | } else if (VT == MVT::v16i8) { | ||||
4639 | SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST); | ||||
4640 | return; | ||||
4641 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4642 | SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST); | ||||
4643 | return; | ||||
4644 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4645 | SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST); | ||||
4646 | return; | ||||
4647 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4648 | SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST); | ||||
4649 | return; | ||||
4650 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4651 | SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST); | ||||
4652 | return; | ||||
4653 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4654 | SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST); | ||||
4655 | return; | ||||
4656 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4657 | SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST); | ||||
4658 | return; | ||||
4659 | } | ||||
4660 | break; | ||||
4661 | } | ||||
4662 | case AArch64ISD::ST1x3post: { | ||||
4663 | VT = Node->getOperand(1).getValueType(); | ||||
4664 | if (VT == MVT::v8i8) { | ||||
4665 | SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST); | ||||
4666 | return; | ||||
4667 | } else if (VT == MVT::v16i8) { | ||||
4668 | SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST); | ||||
4669 | return; | ||||
4670 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4671 | SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST); | ||||
4672 | return; | ||||
4673 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) { | ||||
4674 | SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST); | ||||
4675 | return; | ||||
4676 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4677 | SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST); | ||||
4678 | return; | ||||
4679 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4680 | SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST); | ||||
4681 | return; | ||||
4682 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4683 | SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST); | ||||
4684 | return; | ||||
4685 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4686 | SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST); | ||||
4687 | return; | ||||
4688 | } | ||||
4689 | break; | ||||
4690 | } | ||||
4691 | case AArch64ISD::ST1x4post: { | ||||
4692 | VT = Node->getOperand(1).getValueType(); | ||||
4693 | if (VT == MVT::v8i8) { | ||||
4694 | SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST); | ||||
4695 | return; | ||||
4696 | } else if (VT == MVT::v16i8) { | ||||
4697 | SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST); | ||||
4698 | return; | ||||
4699 | } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) { | ||||
4700 | SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST); | ||||
4701 | return; | ||||
4702 | } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) { | ||||
4703 | SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST); | ||||
4704 | return; | ||||
4705 | } else if (VT == MVT::v2i32 || VT == MVT::v2f32) { | ||||
4706 | SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST); | ||||
4707 | return; | ||||
4708 | } else if (VT == MVT::v4i32 || VT == MVT::v4f32) { | ||||
4709 | SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST); | ||||
4710 | return; | ||||
4711 | } else if (VT == MVT::v1i64 || VT == MVT::v1f64) { | ||||
4712 | SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST); | ||||
4713 | return; | ||||
4714 | } else if (VT == MVT::v2i64 || VT == MVT::v2f64) { | ||||
4715 | SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST); | ||||
4716 | return; | ||||
4717 | } | ||||
4718 | break; | ||||
4719 | } | ||||
4720 | case AArch64ISD::ST2LANEpost: { | ||||
4721 | VT = Node->getOperand(1).getValueType(); | ||||
4722 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4723 | SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST); | ||||
4724 | return; | ||||
4725 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4726 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4727 | SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST); | ||||
4728 | return; | ||||
4729 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4730 | VT == MVT::v2f32) { | ||||
4731 | SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST); | ||||
4732 | return; | ||||
4733 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4734 | VT == MVT::v1f64) { | ||||
4735 | SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST); | ||||
4736 | return; | ||||
4737 | } | ||||
4738 | break; | ||||
4739 | } | ||||
4740 | case AArch64ISD::ST3LANEpost: { | ||||
4741 | VT = Node->getOperand(1).getValueType(); | ||||
4742 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4743 | SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST); | ||||
4744 | return; | ||||
4745 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4746 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4747 | SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST); | ||||
4748 | return; | ||||
4749 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4750 | VT == MVT::v2f32) { | ||||
4751 | SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST); | ||||
4752 | return; | ||||
4753 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4754 | VT == MVT::v1f64) { | ||||
4755 | SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST); | ||||
4756 | return; | ||||
4757 | } | ||||
4758 | break; | ||||
4759 | } | ||||
4760 | case AArch64ISD::ST4LANEpost: { | ||||
4761 | VT = Node->getOperand(1).getValueType(); | ||||
4762 | if (VT == MVT::v16i8 || VT == MVT::v8i8) { | ||||
4763 | SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST); | ||||
4764 | return; | ||||
4765 | } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 || | ||||
4766 | VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) { | ||||
4767 | SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST); | ||||
4768 | return; | ||||
4769 | } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 || | ||||
4770 | VT == MVT::v2f32) { | ||||
4771 | SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST); | ||||
4772 | return; | ||||
4773 | } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 || | ||||
4774 | VT == MVT::v1f64) { | ||||
4775 | SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST); | ||||
4776 | return; | ||||
4777 | } | ||||
4778 | break; | ||||
4779 | } | ||||
4780 | case AArch64ISD::SVE_LD2_MERGE_ZERO: { | ||||
4781 | if (VT == MVT::nxv16i8) { | ||||
4782 | SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B); | ||||
4783 | return; | ||||
4784 | } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 || | ||||
4785 | (VT == MVT::nxv8bf16 && Subtarget->hasBF16())) { | ||||
4786 | SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H); | ||||
4787 | return; | ||||
4788 | } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) { | ||||
4789 | SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W); | ||||
4790 | return; | ||||
4791 | } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) { | ||||
4792 | SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D); | ||||
4793 | return; | ||||
4794 | } | ||||
4795 | break; | ||||
4796 | } | ||||
4797 | case AArch64ISD::SVE_LD3_MERGE_ZERO: { | ||||
4798 | if (VT == MVT::nxv16i8) { | ||||
4799 | SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B); | ||||
4800 | return; | ||||
4801 | } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 || | ||||
4802 | (VT == MVT::nxv8bf16 && Subtarget->hasBF16())) { | ||||
4803 | SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H); | ||||
4804 | return; | ||||
4805 | } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) { | ||||
4806 | SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W); | ||||
4807 | return; | ||||
4808 | } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) { | ||||
4809 | SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D); | ||||
4810 | return; | ||||
4811 | } | ||||
4812 | break; | ||||
4813 | } | ||||
4814 | case AArch64ISD::SVE_LD4_MERGE_ZERO: { | ||||
4815 | if (VT == MVT::nxv16i8) { | ||||
4816 | SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B); | ||||
4817 | return; | ||||
4818 | } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 || | ||||
4819 | (VT == MVT::nxv8bf16 && Subtarget->hasBF16())) { | ||||
4820 | SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H); | ||||
4821 | return; | ||||
4822 | } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) { | ||||
4823 | SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W); | ||||
4824 | return; | ||||
4825 | } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) { | ||||
4826 | SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D); | ||||
4827 | return; | ||||
4828 | } | ||||
4829 | break; | ||||
4830 | } | ||||
4831 | } | ||||
4832 | |||||
4833 | // Select the default instruction | ||||
4834 | SelectCode(Node); | ||||
4835 | } | ||||
4836 | |||||
4837 | /// createAArch64ISelDag - This pass converts a legalized DAG into a | ||||
4838 | /// AArch64-specific DAG, ready for instruction scheduling. | ||||
4839 | FunctionPass *llvm::createAArch64ISelDag(AArch64TargetMachine &TM, | ||||
4840 | CodeGenOpt::Level OptLevel) { | ||||
4841 | return new AArch64DAGToDAGISel(TM, OptLevel); | ||||
4842 | } | ||||
4843 | |||||
4844 | /// When \p PredVT is a scalable vector predicate in the form | ||||
4845 | /// MVT::nx<M>xi1, it builds the correspondent scalable vector of | ||||
4846 | /// integers MVT::nx<M>xi<bits> s.t. M x bits = 128. When targeting | ||||
4847 | /// structured vectors (NumVec >1), the output data type is | ||||
4848 | /// MVT::nx<M*NumVec>xi<bits> s.t. M x bits = 128. If the input | ||||
4849 | /// PredVT is not in the form MVT::nx<M>xi1, it returns an invalid | ||||
4850 | /// EVT. | ||||
4851 | static EVT getPackedVectorTypeFromPredicateType(LLVMContext &Ctx, EVT PredVT, | ||||
4852 | unsigned NumVec) { | ||||
4853 | assert(NumVec > 0 && NumVec < 5 && "Invalid number of vectors.")((NumVec > 0 && NumVec < 5 && "Invalid number of vectors." ) ? static_cast<void> (0) : __assert_fail ("NumVec > 0 && NumVec < 5 && \"Invalid number of vectors.\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp" , 4853, __PRETTY_FUNCTION__)); | ||||
4854 | if (!PredVT.isScalableVector() || PredVT.getVectorElementType() != MVT::i1) | ||||
4855 | return EVT(); | ||||
4856 | |||||
4857 | if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 && | ||||
4858 | PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1) | ||||
4859 | return EVT(); | ||||
4860 | |||||
4861 | ElementCount EC = PredVT.getVectorElementCount(); | ||||
4862 | EVT ScalarVT = | ||||
4863 | EVT::getIntegerVT(Ctx, AArch64::SVEBitsPerBlock / EC.getKnownMinValue()); | ||||
4864 | EVT MemVT = EVT::getVectorVT(Ctx, ScalarVT, EC * NumVec); | ||||
4865 | |||||
4866 | return MemVT; | ||||
4867 | } | ||||
4868 | |||||
4869 | /// Return the EVT of the data associated to a memory operation in \p | ||||
4870 | /// Root. If such EVT cannot be retrived, it returns an invalid EVT. | ||||
4871 | static EVT getMemVTFromNode(LLVMContext &Ctx, SDNode *Root) { | ||||
4872 | if (isa<MemSDNode>(Root)) | ||||
4873 | return cast<MemSDNode>(Root)->getMemoryVT(); | ||||
4874 | |||||
4875 | if (isa<MemIntrinsicSDNode>(Root)) | ||||
4876 | return cast<MemIntrinsicSDNode>(Root)->getMemoryVT(); | ||||
4877 | |||||
4878 | const unsigned Opcode = Root->getOpcode(); | ||||
4879 | // For custom ISD nodes, we have to look at them individually to extract the | ||||
4880 | // type of the data moved to/from memory. | ||||
4881 | switch (Opcode) { | ||||
4882 | case AArch64ISD::LD1_MERGE_ZERO: | ||||
4883 | case AArch64ISD::LD1S_MERGE_ZERO: | ||||
4884 | case AArch64ISD::LDNF1_MERGE_ZERO: | ||||
4885 | case AArch64ISD::LDNF1S_MERGE_ZERO: | ||||
4886 | return cast<VTSDNode>(Root->getOperand(3))->getVT(); | ||||
4887 | case AArch64ISD::ST1_PRED: | ||||
4888 | return cast<VTSDNode>(Root->getOperand(4))->getVT(); | ||||
4889 | case AArch64ISD::SVE_LD2_MERGE_ZERO: | ||||
4890 | return getPackedVectorTypeFromPredicateType( | ||||
4891 | Ctx, Root->getOperand(1)->getValueType(0), /*NumVec=*/2); | ||||
4892 | case AArch64ISD::SVE_LD3_MERGE_ZERO: | ||||
4893 | return getPackedVectorTypeFromPredicateType( | ||||
4894 | Ctx, Root->getOperand(1)->getValueType(0), /*NumVec=*/3); | ||||
4895 | case AArch64ISD::SVE_LD4_MERGE_ZERO: | ||||
4896 | return getPackedVectorTypeFromPredicateType( | ||||
4897 | Ctx, Root->getOperand(1)->getValueType(0), /*NumVec=*/4); | ||||
4898 | default: | ||||
4899 | break; | ||||
4900 | } | ||||
4901 | |||||
4902 | if (Opcode != ISD::INTRINSIC_VOID) | ||||
4903 | return EVT(); | ||||
4904 | |||||
4905 | const unsigned IntNo = | ||||
4906 | cast<ConstantSDNode>(Root->getOperand(1))->getZExtValue(); | ||||
4907 | if (IntNo != Intrinsic::aarch64_sve_prf) | ||||
4908 | return EVT(); | ||||
4909 | |||||
4910 | // We are using an SVE prefetch intrinsic. Type must be inferred | ||||
4911 | // from the width of the predicate. | ||||
4912 | return getPackedVectorTypeFromPredicateType( | ||||
4913 | Ctx, Root->getOperand(2)->getValueType(0), /*NumVec=*/1); | ||||
4914 | } | ||||
4915 | |||||
4916 | /// SelectAddrModeIndexedSVE - Attempt selection of the addressing mode: | ||||
4917 | /// Base + OffImm * sizeof(MemVT) for Min >= OffImm <= Max | ||||
4918 | /// where Root is the memory access using N for its address. | ||||
4919 | template <int64_t Min, int64_t Max> | ||||
4920 | bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue N, | ||||
4921 | SDValue &Base, | ||||
4922 | SDValue &OffImm) { | ||||
4923 | const EVT MemVT = getMemVTFromNode(*(CurDAG->getContext()), Root); | ||||
4924 | |||||
4925 | if (MemVT == EVT()) | ||||
4926 | return false; | ||||
4927 | |||||
4928 | if (N.getOpcode() != ISD::ADD) | ||||
4929 | return false; | ||||
4930 | |||||
4931 | SDValue VScale = N.getOperand(1); | ||||
4932 | if (VScale.getOpcode() != ISD::VSCALE) | ||||
4933 | return false; | ||||
4934 | |||||
4935 | TypeSize TS = MemVT.getSizeInBits(); | ||||
4936 | int64_t MemWidthBytes = static_cast<int64_t>(TS.getKnownMinSize()) / 8; | ||||
4937 | int64_t MulImm = cast<ConstantSDNode>(VScale.getOperand(0))->getSExtValue(); | ||||
4938 | |||||
4939 | if ((MulImm % MemWidthBytes) != 0) | ||||
4940 | return false; | ||||
4941 | |||||
4942 | int64_t Offset = MulImm / MemWidthBytes; | ||||
4943 | if (Offset < Min || Offset > Max) | ||||
4944 | return false; | ||||
4945 | |||||
4946 | Base = N.getOperand(0); | ||||
4947 | OffImm = CurDAG->getTargetConstant(Offset, SDLoc(N), MVT::i64); | ||||
4948 | return true; | ||||
4949 | } | ||||
4950 | |||||
4951 | /// Select register plus register addressing mode for SVE, with scaled | ||||
4952 | /// offset. | ||||
4953 | bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(SDValue N, unsigned Scale, | ||||
4954 | SDValue &Base, | ||||
4955 | SDValue &Offset) { | ||||
4956 | if (N.getOpcode() != ISD::ADD) | ||||
4957 | return false; | ||||
4958 | |||||
4959 | // Process an ADD node. | ||||
4960 | const SDValue LHS = N.getOperand(0); | ||||
4961 | const SDValue RHS = N.getOperand(1); | ||||
4962 | |||||
4963 | // 8 bit data does not come with the SHL node, so it is treated | ||||
4964 | // separately. | ||||
4965 | if (Scale == 0) { | ||||
4966 | Base = LHS; | ||||
4967 | Offset = RHS; | ||||
4968 | return true; | ||||
4969 | } | ||||
4970 | |||||
4971 | // Check if the RHS is a shift node with a constant. | ||||
4972 | if (RHS.getOpcode() != ISD::SHL) | ||||
4973 | return false; | ||||
4974 | |||||
4975 | const SDValue ShiftRHS = RHS.getOperand(1); | ||||
4976 | if (auto *C = dyn_cast<ConstantSDNode>(ShiftRHS)) | ||||
4977 | if (C->getZExtValue() == Scale) { | ||||
4978 | Base = LHS; | ||||
4979 | Offset = RHS.getOperand(0); | ||||
4980 | return true; | ||||
4981 | } | ||||
4982 | |||||
4983 | return false; | ||||
4984 | } |
1 | //===- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ----*- C++ -*-===// | |||
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 declares the SDNode class and derived classes, which are used to | |||
10 | // represent the nodes and operations present in a SelectionDAG. These nodes | |||
11 | // and operations are machine code level operations, with some similarities to | |||
12 | // the GCC RTL representation. | |||
13 | // | |||
14 | // Clients should include the SelectionDAG.h file instead of this file directly. | |||
15 | // | |||
16 | //===----------------------------------------------------------------------===// | |||
17 | ||||
18 | #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H | |||
19 | #define LLVM_CODEGEN_SELECTIONDAGNODES_H | |||
20 | ||||
21 | #include "llvm/ADT/APFloat.h" | |||
22 | #include "llvm/ADT/ArrayRef.h" | |||
23 | #include "llvm/ADT/BitVector.h" | |||
24 | #include "llvm/ADT/FoldingSet.h" | |||
25 | #include "llvm/ADT/GraphTraits.h" | |||
26 | #include "llvm/ADT/SmallPtrSet.h" | |||
27 | #include "llvm/ADT/SmallVector.h" | |||
28 | #include "llvm/ADT/ilist_node.h" | |||
29 | #include "llvm/ADT/iterator.h" | |||
30 | #include "llvm/ADT/iterator_range.h" | |||
31 | #include "llvm/CodeGen/ISDOpcodes.h" | |||
32 | #include "llvm/CodeGen/MachineMemOperand.h" | |||
33 | #include "llvm/CodeGen/Register.h" | |||
34 | #include "llvm/CodeGen/ValueTypes.h" | |||
35 | #include "llvm/IR/Constants.h" | |||
36 | #include "llvm/IR/DebugLoc.h" | |||
37 | #include "llvm/IR/Instruction.h" | |||
38 | #include "llvm/IR/Instructions.h" | |||
39 | #include "llvm/IR/Metadata.h" | |||
40 | #include "llvm/IR/Operator.h" | |||
41 | #include "llvm/Support/AlignOf.h" | |||
42 | #include "llvm/Support/AtomicOrdering.h" | |||
43 | #include "llvm/Support/Casting.h" | |||
44 | #include "llvm/Support/ErrorHandling.h" | |||
45 | #include "llvm/Support/MachineValueType.h" | |||
46 | #include "llvm/Support/TypeSize.h" | |||
47 | #include <algorithm> | |||
48 | #include <cassert> | |||
49 | #include <climits> | |||
50 | #include <cstddef> | |||
51 | #include <cstdint> | |||
52 | #include <cstring> | |||
53 | #include <iterator> | |||
54 | #include <string> | |||
55 | #include <tuple> | |||
56 | ||||
57 | namespace llvm { | |||
58 | ||||
59 | class APInt; | |||
60 | class Constant; | |||
61 | template <typename T> struct DenseMapInfo; | |||
62 | class GlobalValue; | |||
63 | class MachineBasicBlock; | |||
64 | class MachineConstantPoolValue; | |||
65 | class MCSymbol; | |||
66 | class raw_ostream; | |||
67 | class SDNode; | |||
68 | class SelectionDAG; | |||
69 | class Type; | |||
70 | class Value; | |||
71 | ||||
72 | void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr, | |||
73 | bool force = false); | |||
74 | ||||
75 | /// This represents a list of ValueType's that has been intern'd by | |||
76 | /// a SelectionDAG. Instances of this simple value class are returned by | |||
77 | /// SelectionDAG::getVTList(...). | |||
78 | /// | |||
79 | struct SDVTList { | |||
80 | const EVT *VTs; | |||
81 | unsigned int NumVTs; | |||
82 | }; | |||
83 | ||||
84 | namespace ISD { | |||
85 | ||||
86 | /// Node predicates | |||
87 | ||||
88 | /// If N is a BUILD_VECTOR or SPLAT_VECTOR node whose elements are all the | |||
89 | /// same constant or undefined, return true and return the constant value in | |||
90 | /// \p SplatValue. | |||
91 | bool isConstantSplatVector(const SDNode *N, APInt &SplatValue); | |||
92 | ||||
93 | /// Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where | |||
94 | /// all of the elements are ~0 or undef. If \p BuildVectorOnly is set to | |||
95 | /// true, it only checks BUILD_VECTOR. | |||
96 | bool isConstantSplatVectorAllOnes(const SDNode *N, | |||
97 | bool BuildVectorOnly = false); | |||
98 | ||||
99 | /// Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where | |||
100 | /// all of the elements are 0 or undef. If \p BuildVectorOnly is set to true, it | |||
101 | /// only checks BUILD_VECTOR. | |||
102 | bool isConstantSplatVectorAllZeros(const SDNode *N, | |||
103 | bool BuildVectorOnly = false); | |||
104 | ||||
105 | /// Return true if the specified node is a BUILD_VECTOR where all of the | |||
106 | /// elements are ~0 or undef. | |||
107 | bool isBuildVectorAllOnes(const SDNode *N); | |||
108 | ||||
109 | /// Return true if the specified node is a BUILD_VECTOR where all of the | |||
110 | /// elements are 0 or undef. | |||
111 | bool isBuildVectorAllZeros(const SDNode *N); | |||
112 | ||||
113 | /// Return true if the specified node is a BUILD_VECTOR node of all | |||
114 | /// ConstantSDNode or undef. | |||
115 | bool isBuildVectorOfConstantSDNodes(const SDNode *N); | |||
116 | ||||
117 | /// Return true if the specified node is a BUILD_VECTOR node of all | |||
118 | /// ConstantFPSDNode or undef. | |||
119 | bool isBuildVectorOfConstantFPSDNodes(const SDNode *N); | |||
120 | ||||
121 | /// Return true if the node has at least one operand and all operands of the | |||
122 | /// specified node are ISD::UNDEF. | |||
123 | bool allOperandsUndef(const SDNode *N); | |||
124 | ||||
125 | } // end namespace ISD | |||
126 | ||||
127 | //===----------------------------------------------------------------------===// | |||
128 | /// Unlike LLVM values, Selection DAG nodes may return multiple | |||
129 | /// values as the result of a computation. Many nodes return multiple values, | |||
130 | /// from loads (which define a token and a return value) to ADDC (which returns | |||
131 | /// a result and a carry value), to calls (which may return an arbitrary number | |||
132 | /// of values). | |||
133 | /// | |||
134 | /// As such, each use of a SelectionDAG computation must indicate the node that | |||
135 | /// computes it as well as which return value to use from that node. This pair | |||
136 | /// of information is represented with the SDValue value type. | |||
137 | /// | |||
138 | class SDValue { | |||
139 | friend struct DenseMapInfo<SDValue>; | |||
140 | ||||
141 | SDNode *Node = nullptr; // The node defining the value we are using. | |||
142 | unsigned ResNo = 0; // Which return value of the node we are using. | |||
143 | ||||
144 | public: | |||
145 | SDValue() = default; | |||
146 | SDValue(SDNode *node, unsigned resno); | |||
147 | ||||
148 | /// get the index which selects a specific result in the SDNode | |||
149 | unsigned getResNo() const { return ResNo; } | |||
150 | ||||
151 | /// get the SDNode which holds the desired result | |||
152 | SDNode *getNode() const { return Node; } | |||
153 | ||||
154 | /// set the SDNode | |||
155 | void setNode(SDNode *N) { Node = N; } | |||
156 | ||||
157 | inline SDNode *operator->() const { return Node; } | |||
158 | ||||
159 | bool operator==(const SDValue &O) const { | |||
160 | return Node == O.Node && ResNo == O.ResNo; | |||
161 | } | |||
162 | bool operator!=(const SDValue &O) const { | |||
163 | return !operator==(O); | |||
164 | } | |||
165 | bool operator<(const SDValue &O) const { | |||
166 | return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo); | |||
167 | } | |||
168 | explicit operator bool() const { | |||
169 | return Node != nullptr; | |||
170 | } | |||
171 | ||||
172 | SDValue getValue(unsigned R) const { | |||
173 | return SDValue(Node, R); | |||
174 | } | |||
175 | ||||
176 | /// Return true if this node is an operand of N. | |||
177 | bool isOperandOf(const SDNode *N) const; | |||
178 | ||||
179 | /// Return the ValueType of the referenced return value. | |||
180 | inline EVT getValueType() const; | |||
181 | ||||
182 | /// Return the simple ValueType of the referenced return value. | |||
183 | MVT getSimpleValueType() const { | |||
184 | return getValueType().getSimpleVT(); | |||
185 | } | |||
186 | ||||
187 | /// Returns the size of the value in bits. | |||
188 | /// | |||
189 | /// If the value type is a scalable vector type, the scalable property will | |||
190 | /// be set and the runtime size will be a positive integer multiple of the | |||
191 | /// base size. | |||
192 | TypeSize getValueSizeInBits() const { | |||
193 | return getValueType().getSizeInBits(); | |||
194 | } | |||
195 | ||||
196 | uint64_t getScalarValueSizeInBits() const { | |||
197 | return getValueType().getScalarType().getFixedSizeInBits(); | |||
198 | } | |||
199 | ||||
200 | // Forwarding methods - These forward to the corresponding methods in SDNode. | |||
201 | inline unsigned getOpcode() const; | |||
202 | inline unsigned getNumOperands() const; | |||
203 | inline const SDValue &getOperand(unsigned i) const; | |||
204 | inline uint64_t getConstantOperandVal(unsigned i) const; | |||
205 | inline const APInt &getConstantOperandAPInt(unsigned i) const; | |||
206 | inline bool isTargetMemoryOpcode() const; | |||
207 | inline bool isTargetOpcode() const; | |||
208 | inline bool isMachineOpcode() const; | |||
209 | inline bool isUndef() const; | |||
210 | inline unsigned getMachineOpcode() const; | |||
211 | inline const DebugLoc &getDebugLoc() const; | |||
212 | inline void dump() const; | |||
213 | inline void dump(const SelectionDAG *G) const; | |||
214 | inline void dumpr() const; | |||
215 | inline void dumpr(const SelectionDAG *G) const; | |||
216 | ||||
217 | /// Return true if this operand (which must be a chain) reaches the | |||
218 | /// specified operand without crossing any side-effecting instructions. | |||
219 | /// In practice, this looks through token factors and non-volatile loads. | |||
220 | /// In order to remain efficient, this only | |||
221 | /// looks a couple of nodes in, it does not do an exhaustive search. | |||
222 | bool reachesChainWithoutSideEffects(SDValue Dest, | |||
223 | unsigned Depth = 2) const; | |||
224 | ||||
225 | /// Return true if there are no nodes using value ResNo of Node. | |||
226 | inline bool use_empty() const; | |||
227 | ||||
228 | /// Return true if there is exactly one node using value ResNo of Node. | |||
229 | inline bool hasOneUse() const; | |||
230 | }; | |||
231 | ||||
232 | template<> struct DenseMapInfo<SDValue> { | |||
233 | static inline SDValue getEmptyKey() { | |||
234 | SDValue V; | |||
235 | V.ResNo = -1U; | |||
236 | return V; | |||
237 | } | |||
238 | ||||
239 | static inline SDValue getTombstoneKey() { | |||
240 | SDValue V; | |||
241 | V.ResNo = -2U; | |||
242 | return V; | |||
243 | } | |||
244 | ||||
245 | static unsigned getHashValue(const SDValue &Val) { | |||
246 | return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^ | |||
247 | (unsigned)((uintptr_t)Val.getNode() >> 9)) + Val.getResNo(); | |||
248 | } | |||
249 | ||||
250 | static bool isEqual(const SDValue &LHS, const SDValue &RHS) { | |||
251 | return LHS == RHS; | |||
252 | } | |||
253 | }; | |||
254 | ||||
255 | /// Allow casting operators to work directly on | |||
256 | /// SDValues as if they were SDNode*'s. | |||
257 | template<> struct simplify_type<SDValue> { | |||
258 | using SimpleType = SDNode *; | |||
259 | ||||
260 | static SimpleType getSimplifiedValue(SDValue &Val) { | |||
261 | return Val.getNode(); | |||
262 | } | |||
263 | }; | |||
264 | template<> struct simplify_type<const SDValue> { | |||
265 | using SimpleType = /*const*/ SDNode *; | |||
266 | ||||
267 | static SimpleType getSimplifiedValue(const SDValue &Val) { | |||
268 | return Val.getNode(); | |||
269 | } | |||
270 | }; | |||
271 | ||||
272 | /// Represents a use of a SDNode. This class holds an SDValue, | |||
273 | /// which records the SDNode being used and the result number, a | |||
274 | /// pointer to the SDNode using the value, and Next and Prev pointers, | |||
275 | /// which link together all the uses of an SDNode. | |||
276 | /// | |||
277 | class SDUse { | |||
278 | /// Val - The value being used. | |||
279 | SDValue Val; | |||
280 | /// User - The user of this value. | |||
281 | SDNode *User = nullptr; | |||
282 | /// Prev, Next - Pointers to the uses list of the SDNode referred by | |||
283 | /// this operand. | |||
284 | SDUse **Prev = nullptr; | |||
285 | SDUse *Next = nullptr; | |||
286 | ||||
287 | public: | |||
288 | SDUse() = default; | |||
289 | SDUse(const SDUse &U) = delete; | |||
290 | SDUse &operator=(const SDUse &) = delete; | |||
291 | ||||
292 | /// Normally SDUse will just implicitly convert to an SDValue that it holds. | |||
293 | operator const SDValue&() const { return Val; } | |||
294 | ||||
295 | /// If implicit conversion to SDValue doesn't work, the get() method returns | |||
296 | /// the SDValue. | |||
297 | const SDValue &get() const { return Val; } | |||
298 | ||||
299 | /// This returns the SDNode that contains this Use. | |||
300 | SDNode *getUser() { return User; } | |||
301 | ||||
302 | /// Get the next SDUse in the use list. | |||
303 | SDUse *getNext() const { return Next; } | |||
304 | ||||
305 | /// Convenience function for get().getNode(). | |||
306 | SDNode *getNode() const { return Val.getNode(); } | |||
307 | /// Convenience function for get().getResNo(). | |||
308 | unsigned getResNo() const { return Val.getResNo(); } | |||
309 | /// Convenience function for get().getValueType(). | |||
310 | EVT getValueType() const { return Val.getValueType(); } | |||
311 | ||||
312 | /// Convenience function for get().operator== | |||
313 | bool operator==(const SDValue &V) const { | |||
314 | return Val == V; | |||
315 | } | |||
316 | ||||
317 | /// Convenience function for get().operator!= | |||
318 | bool operator!=(const SDValue &V) const { | |||
319 | return Val != V; | |||
320 | } | |||
321 | ||||
322 | /// Convenience function for get().operator< | |||
323 | bool operator<(const SDValue &V) const { | |||
324 | return Val < V; | |||
325 | } | |||
326 | ||||
327 | private: | |||
328 | friend class SelectionDAG; | |||
329 | friend class SDNode; | |||
330 | // TODO: unfriend HandleSDNode once we fix its operand handling. | |||
331 | friend class HandleSDNode; | |||
332 | ||||
333 | void setUser(SDNode *p) { User = p; } | |||
334 | ||||
335 | /// Remove this use from its existing use list, assign it the | |||
336 | /// given value, and add it to the new value's node's use list. | |||
337 | inline void set(const SDValue &V); | |||
338 | /// Like set, but only supports initializing a newly-allocated | |||
339 | /// SDUse with a non-null value. | |||
340 | inline void setInitial(const SDValue &V); | |||
341 | /// Like set, but only sets the Node portion of the value, | |||
342 | /// leaving the ResNo portion unmodified. | |||
343 | inline void setNode(SDNode *N); | |||
344 | ||||
345 | void addToList(SDUse **List) { | |||
346 | Next = *List; | |||
347 | if (Next) Next->Prev = &Next; | |||
348 | Prev = List; | |||
349 | *List = this; | |||
350 | } | |||
351 | ||||
352 | void removeFromList() { | |||
353 | *Prev = Next; | |||
354 | if (Next) Next->Prev = Prev; | |||
355 | } | |||
356 | }; | |||
357 | ||||
358 | /// simplify_type specializations - Allow casting operators to work directly on | |||
359 | /// SDValues as if they were SDNode*'s. | |||
360 | template<> struct simplify_type<SDUse> { | |||
361 | using SimpleType = SDNode *; | |||
362 | ||||
363 | static SimpleType getSimplifiedValue(SDUse &Val) { | |||
364 | return Val.getNode(); | |||
365 | } | |||
366 | }; | |||
367 | ||||
368 | /// These are IR-level optimization flags that may be propagated to SDNodes. | |||
369 | /// TODO: This data structure should be shared by the IR optimizer and the | |||
370 | /// the backend. | |||
371 | struct SDNodeFlags { | |||
372 | private: | |||
373 | bool NoUnsignedWrap : 1; | |||
374 | bool NoSignedWrap : 1; | |||
375 | bool Exact : 1; | |||
376 | bool NoNaNs : 1; | |||
377 | bool NoInfs : 1; | |||
378 | bool NoSignedZeros : 1; | |||
379 | bool AllowReciprocal : 1; | |||
380 | bool AllowContract : 1; | |||
381 | bool ApproximateFuncs : 1; | |||
382 | bool AllowReassociation : 1; | |||
383 | ||||
384 | // We assume instructions do not raise floating-point exceptions by default, | |||
385 | // and only those marked explicitly may do so. We could choose to represent | |||
386 | // this via a positive "FPExcept" flags like on the MI level, but having a | |||
387 | // negative "NoFPExcept" flag here (that defaults to true) makes the flag | |||
388 | // intersection logic more straightforward. | |||
389 | bool NoFPExcept : 1; | |||
390 | ||||
391 | public: | |||
392 | /// Default constructor turns off all optimization flags. | |||
393 | SDNodeFlags() | |||
394 | : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false), NoNaNs(false), | |||
395 | NoInfs(false), NoSignedZeros(false), AllowReciprocal(false), | |||
396 | AllowContract(false), ApproximateFuncs(false), | |||
397 | AllowReassociation(false), NoFPExcept(false) {} | |||
398 | ||||
399 | /// Propagate the fast-math-flags from an IR FPMathOperator. | |||
400 | void copyFMF(const FPMathOperator &FPMO) { | |||
401 | setNoNaNs(FPMO.hasNoNaNs()); | |||
402 | setNoInfs(FPMO.hasNoInfs()); | |||
403 | setNoSignedZeros(FPMO.hasNoSignedZeros()); | |||
404 | setAllowReciprocal(FPMO.hasAllowReciprocal()); | |||
405 | setAllowContract(FPMO.hasAllowContract()); | |||
406 | setApproximateFuncs(FPMO.hasApproxFunc()); | |||
407 | setAllowReassociation(FPMO.hasAllowReassoc()); | |||
408 | } | |||
409 | ||||
410 | // These are mutators for each flag. | |||
411 | void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; } | |||
412 | void setNoSignedWrap(bool b) { NoSignedWrap = b; } | |||
413 | void setExact(bool b) { Exact = b; } | |||
414 | void setNoNaNs(bool b) { NoNaNs = b; } | |||
415 | void setNoInfs(bool b) { NoInfs = b; } | |||
416 | void setNoSignedZeros(bool b) { NoSignedZeros = b; } | |||
417 | void setAllowReciprocal(bool b) { AllowReciprocal = b; } | |||
418 | void setAllowContract(bool b) { AllowContract = b; } | |||
419 | void setApproximateFuncs(bool b) { ApproximateFuncs = b; } | |||
420 | void setAllowReassociation(bool b) { AllowReassociation = b; } | |||
421 | void setNoFPExcept(bool b) { NoFPExcept = b; } | |||
422 | ||||
423 | // These are accessors for each flag. | |||
424 | bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } | |||
425 | bool hasNoSignedWrap() const { return NoSignedWrap; } | |||
426 | bool hasExact() const { return Exact; } | |||
427 | bool hasNoNaNs() const { return NoNaNs; } | |||
428 | bool hasNoInfs() const { return NoInfs; } | |||
429 | bool hasNoSignedZeros() const { return NoSignedZeros; } | |||
430 | bool hasAllowReciprocal() const { return AllowReciprocal; } | |||
431 | bool hasAllowContract() const { return AllowContract; } | |||
432 | bool hasApproximateFuncs() const { return ApproximateFuncs; } | |||
433 | bool hasAllowReassociation() const { return AllowReassociation; } | |||
434 | bool hasNoFPExcept() const { return NoFPExcept; } | |||
435 | ||||
436 | /// Clear any flags in this flag set that aren't also set in Flags. All | |||
437 | /// flags will be cleared if Flags are undefined. | |||
438 | void intersectWith(const SDNodeFlags Flags) { | |||
439 | NoUnsignedWrap &= Flags.NoUnsignedWrap; | |||
440 | NoSignedWrap &= Flags.NoSignedWrap; | |||
441 | Exact &= Flags.Exact; | |||
442 | NoNaNs &= Flags.NoNaNs; | |||
443 | NoInfs &= Flags.NoInfs; | |||
444 | NoSignedZeros &= Flags.NoSignedZeros; | |||
445 | AllowReciprocal &= Flags.AllowReciprocal; | |||
446 | AllowContract &= Flags.AllowContract; | |||
447 | ApproximateFuncs &= Flags.ApproximateFuncs; | |||
448 | AllowReassociation &= Flags.AllowReassociation; | |||
449 | NoFPExcept &= Flags.NoFPExcept; | |||
450 | } | |||
451 | }; | |||
452 | ||||
453 | /// Represents one node in the SelectionDAG. | |||
454 | /// | |||
455 | class SDNode : public FoldingSetNode, public ilist_node<SDNode> { | |||
456 | private: | |||
457 | /// The operation that this node performs. | |||
458 | int16_t NodeType; | |||
459 | ||||
460 | protected: | |||
461 | // We define a set of mini-helper classes to help us interpret the bits in our | |||
462 | // SubclassData. These are designed to fit within a uint16_t so they pack | |||
463 | // with NodeType. | |||
464 | ||||
465 | #if defined(_AIX) && (!defined(__GNUC__4) || defined(__ibmxl__)) | |||
466 | // Except for GCC; by default, AIX compilers store bit-fields in 4-byte words | |||
467 | // and give the `pack` pragma push semantics. | |||
468 | #define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)")pack(2) | |||
469 | #define END_TWO_BYTE_PACK() _Pragma("pack(pop)")pack(pop) | |||
470 | #else | |||
471 | #define BEGIN_TWO_BYTE_PACK() | |||
472 | #define END_TWO_BYTE_PACK() | |||
473 | #endif | |||
474 | ||||
475 | BEGIN_TWO_BYTE_PACK() | |||
476 | class SDNodeBitfields { | |||
477 | friend class SDNode; | |||
478 | friend class MemIntrinsicSDNode; | |||
479 | friend class MemSDNode; | |||
480 | friend class SelectionDAG; | |||
481 | ||||
482 | uint16_t HasDebugValue : 1; | |||
483 | uint16_t IsMemIntrinsic : 1; | |||
484 | uint16_t IsDivergent : 1; | |||
485 | }; | |||
486 | enum { NumSDNodeBits = 3 }; | |||
487 | ||||
488 | class ConstantSDNodeBitfields { | |||
489 | friend class ConstantSDNode; | |||
490 | ||||
491 | uint16_t : NumSDNodeBits; | |||
492 | ||||
493 | uint16_t IsOpaque : 1; | |||
494 | }; | |||
495 | ||||
496 | class MemSDNodeBitfields { | |||
497 | friend class MemSDNode; | |||
498 | friend class MemIntrinsicSDNode; | |||
499 | friend class AtomicSDNode; | |||
500 | ||||
501 | uint16_t : NumSDNodeBits; | |||
502 | ||||
503 | uint16_t IsVolatile : 1; | |||
504 | uint16_t IsNonTemporal : 1; | |||
505 | uint16_t IsDereferenceable : 1; | |||
506 | uint16_t IsInvariant : 1; | |||
507 | }; | |||
508 | enum { NumMemSDNodeBits = NumSDNodeBits + 4 }; | |||
509 | ||||
510 | class LSBaseSDNodeBitfields { | |||
511 | friend class LSBaseSDNode; | |||
512 | friend class MaskedLoadStoreSDNode; | |||
513 | friend class MaskedGatherScatterSDNode; | |||
514 | ||||
515 | uint16_t : NumMemSDNodeBits; | |||
516 | ||||
517 | // This storage is shared between disparate class hierarchies to hold an | |||
518 | // enumeration specific to the class hierarchy in use. | |||
519 | // LSBaseSDNode => enum ISD::MemIndexedMode | |||
520 | // MaskedLoadStoreBaseSDNode => enum ISD::MemIndexedMode | |||
521 | // MaskedGatherScatterSDNode => enum ISD::MemIndexType | |||
522 | uint16_t AddressingMode : 3; | |||
523 | }; | |||
524 | enum { NumLSBaseSDNodeBits = NumMemSDNodeBits + 3 }; | |||
525 | ||||
526 | class LoadSDNodeBitfields { | |||
527 | friend class LoadSDNode; | |||
528 | friend class MaskedLoadSDNode; | |||
529 | friend class MaskedGatherSDNode; | |||
530 | ||||
531 | uint16_t : NumLSBaseSDNodeBits; | |||
532 | ||||
533 | uint16_t ExtTy : 2; // enum ISD::LoadExtType | |||
534 | uint16_t IsExpanding : 1; | |||
535 | }; | |||
536 | ||||
537 | class StoreSDNodeBitfields { | |||
538 | friend class StoreSDNode; | |||
539 | friend class MaskedStoreSDNode; | |||
540 | friend class MaskedScatterSDNode; | |||
541 | ||||
542 | uint16_t : NumLSBaseSDNodeBits; | |||
543 | ||||
544 | uint16_t IsTruncating : 1; | |||
545 | uint16_t IsCompressing : 1; | |||
546 | }; | |||
547 | ||||
548 | union { | |||
549 | char RawSDNodeBits[sizeof(uint16_t)]; | |||
550 | SDNodeBitfields SDNodeBits; | |||
551 | ConstantSDNodeBitfields ConstantSDNodeBits; | |||
552 | MemSDNodeBitfields MemSDNodeBits; | |||
553 | LSBaseSDNodeBitfields LSBaseSDNodeBits; | |||
554 | LoadSDNodeBitfields LoadSDNodeBits; | |||
555 | StoreSDNodeBitfields StoreSDNodeBits; | |||
556 | }; | |||
557 | END_TWO_BYTE_PACK() | |||
558 | #undef BEGIN_TWO_BYTE_PACK | |||
559 | #undef END_TWO_BYTE_PACK | |||
560 | ||||
561 | // RawSDNodeBits must cover the entirety of the union. This means that all of | |||
562 | // the union's members must have size <= RawSDNodeBits. We write the RHS as | |||
563 | // "2" instead of sizeof(RawSDNodeBits) because MSVC can't handle the latter. | |||
564 | static_assert(sizeof(SDNodeBitfields) <= 2, "field too wide"); | |||
565 | static_assert(sizeof(ConstantSDNodeBitfields) <= 2, "field too wide"); | |||
566 | static_assert(sizeof(MemSDNodeBitfields) <= 2, "field too wide"); | |||
567 | static_assert(sizeof(LSBaseSDNodeBitfields) <= 2, "field too wide"); | |||
568 | static_assert(sizeof(LoadSDNodeBitfields) <= 2, "field too wide"); | |||
569 | static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide"); | |||
570 | ||||
571 | private: | |||
572 | friend class SelectionDAG; | |||
573 | // TODO: unfriend HandleSDNode once we fix its operand handling. | |||
574 | friend class HandleSDNode; | |||
575 | ||||
576 | /// Unique id per SDNode in the DAG. | |||
577 | int NodeId = -1; | |||
578 | ||||
579 | /// The values that are used by this operation. | |||
580 | SDUse *OperandList = nullptr; | |||
581 | ||||
582 | /// The types of the values this node defines. SDNode's may | |||
583 | /// define multiple values simultaneously. | |||
584 | const EVT *ValueList; | |||
585 | ||||
586 | /// List of uses for this SDNode. | |||
587 | SDUse *UseList = nullptr; | |||
588 | ||||
589 | /// The number of entries in the Operand/Value list. | |||
590 | unsigned short NumOperands = 0; | |||
591 | unsigned short NumValues; | |||
592 | ||||
593 | // The ordering of the SDNodes. It roughly corresponds to the ordering of the | |||
594 | // original LLVM instructions. | |||
595 | // This is used for turning off scheduling, because we'll forgo | |||
596 | // the normal scheduling algorithms and output the instructions according to | |||
597 | // this ordering. | |||
598 | unsigned IROrder; | |||
599 | ||||
600 | /// Source line information. | |||
601 | DebugLoc debugLoc; | |||
602 | ||||
603 | /// Return a pointer to the specified value type. | |||
604 | static const EVT *getValueTypeList(EVT VT); | |||
605 | ||||
606 | SDNodeFlags Flags; | |||
607 | ||||
608 | public: | |||
609 | /// Unique and persistent id per SDNode in the DAG. | |||
610 | /// Used for debug printing. | |||
611 | uint16_t PersistentId; | |||
612 | ||||
613 | //===--------------------------------------------------------------------===// | |||
614 | // Accessors | |||
615 | // | |||
616 | ||||
617 | /// Return the SelectionDAG opcode value for this node. For | |||
618 | /// pre-isel nodes (those for which isMachineOpcode returns false), these | |||
619 | /// are the opcode values in the ISD and <target>ISD namespaces. For | |||
620 | /// post-isel opcodes, see getMachineOpcode. | |||
621 | unsigned getOpcode() const { return (unsigned short)NodeType; } | |||
622 | ||||
623 | /// Test if this node has a target-specific opcode (in the | |||
624 | /// \<target\>ISD namespace). | |||
625 | bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } | |||
626 | ||||
627 | /// Test if this node has a target-specific opcode that may raise | |||
628 | /// FP exceptions (in the \<target\>ISD namespace and greater than | |||
629 | /// FIRST_TARGET_STRICTFP_OPCODE). Note that all target memory | |||
630 | /// opcode are currently automatically considered to possibly raise | |||
631 | /// FP exceptions as well. | |||
632 | bool isTargetStrictFPOpcode() const { | |||
633 | return NodeType >= ISD::FIRST_TARGET_STRICTFP_OPCODE; | |||
634 | } | |||
635 | ||||
636 | /// Test if this node has a target-specific | |||
637 | /// memory-referencing opcode (in the \<target\>ISD namespace and | |||
638 | /// greater than FIRST_TARGET_MEMORY_OPCODE). | |||
639 | bool isTargetMemoryOpcode() const { | |||
640 | return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; | |||
641 | } | |||
642 | ||||
643 | /// Return true if the type of the node type undefined. | |||
644 | bool isUndef() const { return NodeType == ISD::UNDEF; } | |||
645 | ||||
646 | /// Test if this node is a memory intrinsic (with valid pointer information). | |||
647 | /// INTRINSIC_W_CHAIN and INTRINSIC_VOID nodes are sometimes created for | |||
648 | /// non-memory intrinsics (with chains) that are not really instances of | |||
649 | /// MemSDNode. For such nodes, we need some extra state to determine the | |||
650 | /// proper classof relationship. | |||
651 | bool isMemIntrinsic() const { | |||
652 | return (NodeType == ISD::INTRINSIC_W_CHAIN || | |||
653 | NodeType == ISD::INTRINSIC_VOID) && | |||
654 | SDNodeBits.IsMemIntrinsic; | |||
655 | } | |||
656 | ||||
657 | /// Test if this node is a strict floating point pseudo-op. | |||
658 | bool isStrictFPOpcode() { | |||
659 | switch (NodeType) { | |||
660 | default: | |||
661 | return false; | |||
662 | case ISD::STRICT_FP16_TO_FP: | |||
663 | case ISD::STRICT_FP_TO_FP16: | |||
664 | #define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ | |||
665 | case ISD::STRICT_##DAGN: | |||
666 | #include "llvm/IR/ConstrainedOps.def" | |||
667 | return true; | |||
668 | } | |||
669 | } | |||
670 | ||||
671 | /// Test if this node has a post-isel opcode, directly | |||
672 | /// corresponding to a MachineInstr opcode. | |||
673 | bool isMachineOpcode() const { return NodeType < 0; } | |||
674 | ||||
675 | /// This may only be called if isMachineOpcode returns | |||
676 | /// true. It returns the MachineInstr opcode value that the node's opcode | |||
677 | /// corresponds to. | |||
678 | unsigned getMachineOpcode() const { | |||
679 | assert(isMachineOpcode() && "Not a MachineInstr opcode!")((isMachineOpcode() && "Not a MachineInstr opcode!") ? static_cast<void> (0) : __assert_fail ("isMachineOpcode() && \"Not a MachineInstr opcode!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 679, __PRETTY_FUNCTION__)); | |||
680 | return ~NodeType; | |||
681 | } | |||
682 | ||||
683 | bool getHasDebugValue() const { return SDNodeBits.HasDebugValue; } | |||
684 | void setHasDebugValue(bool b) { SDNodeBits.HasDebugValue = b; } | |||
685 | ||||
686 | bool isDivergent() const { return SDNodeBits.IsDivergent; } | |||
687 | ||||
688 | /// Return true if there are no uses of this node. | |||
689 | bool use_empty() const { return UseList == nullptr; } | |||
690 | ||||
691 | /// Return true if there is exactly one use of this node. | |||
692 | bool hasOneUse() const { return hasSingleElement(uses()); } | |||
693 | ||||
694 | /// Return the number of uses of this node. This method takes | |||
695 | /// time proportional to the number of uses. | |||
696 | size_t use_size() const { return std::distance(use_begin(), use_end()); } | |||
697 | ||||
698 | /// Return the unique node id. | |||
699 | int getNodeId() const { return NodeId; } | |||
700 | ||||
701 | /// Set unique node id. | |||
702 | void setNodeId(int Id) { NodeId = Id; } | |||
703 | ||||
704 | /// Return the node ordering. | |||
705 | unsigned getIROrder() const { return IROrder; } | |||
706 | ||||
707 | /// Set the node ordering. | |||
708 | void setIROrder(unsigned Order) { IROrder = Order; } | |||
709 | ||||
710 | /// Return the source location info. | |||
711 | const DebugLoc &getDebugLoc() const { return debugLoc; } | |||
712 | ||||
713 | /// Set source location info. Try to avoid this, putting | |||
714 | /// it in the constructor is preferable. | |||
715 | void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); } | |||
716 | ||||
717 | /// This class provides iterator support for SDUse | |||
718 | /// operands that use a specific SDNode. | |||
719 | class use_iterator { | |||
720 | friend class SDNode; | |||
721 | ||||
722 | SDUse *Op = nullptr; | |||
723 | ||||
724 | explicit use_iterator(SDUse *op) : Op(op) {} | |||
725 | ||||
726 | public: | |||
727 | using iterator_category = std::forward_iterator_tag; | |||
728 | using value_type = SDUse; | |||
729 | using difference_type = std::ptrdiff_t; | |||
730 | using pointer = value_type *; | |||
731 | using reference = value_type &; | |||
732 | ||||
733 | use_iterator() = default; | |||
734 | use_iterator(const use_iterator &I) : Op(I.Op) {} | |||
735 | ||||
736 | bool operator==(const use_iterator &x) const { | |||
737 | return Op == x.Op; | |||
738 | } | |||
739 | bool operator!=(const use_iterator &x) const { | |||
740 | return !operator==(x); | |||
741 | } | |||
742 | ||||
743 | /// Return true if this iterator is at the end of uses list. | |||
744 | bool atEnd() const { return Op == nullptr; } | |||
745 | ||||
746 | // Iterator traversal: forward iteration only. | |||
747 | use_iterator &operator++() { // Preincrement | |||
748 | assert(Op && "Cannot increment end iterator!")((Op && "Cannot increment end iterator!") ? static_cast <void> (0) : __assert_fail ("Op && \"Cannot increment end iterator!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 748, __PRETTY_FUNCTION__)); | |||
749 | Op = Op->getNext(); | |||
750 | return *this; | |||
751 | } | |||
752 | ||||
753 | use_iterator operator++(int) { // Postincrement | |||
754 | use_iterator tmp = *this; ++*this; return tmp; | |||
755 | } | |||
756 | ||||
757 | /// Retrieve a pointer to the current user node. | |||
758 | SDNode *operator*() const { | |||
759 | assert(Op && "Cannot dereference end iterator!")((Op && "Cannot dereference end iterator!") ? static_cast <void> (0) : __assert_fail ("Op && \"Cannot dereference end iterator!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 759, __PRETTY_FUNCTION__)); | |||
760 | return Op->getUser(); | |||
761 | } | |||
762 | ||||
763 | SDNode *operator->() const { return operator*(); } | |||
764 | ||||
765 | SDUse &getUse() const { return *Op; } | |||
766 | ||||
767 | /// Retrieve the operand # of this use in its user. | |||
768 | unsigned getOperandNo() const { | |||
769 | assert(Op && "Cannot dereference end iterator!")((Op && "Cannot dereference end iterator!") ? static_cast <void> (0) : __assert_fail ("Op && \"Cannot dereference end iterator!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 769, __PRETTY_FUNCTION__)); | |||
770 | return (unsigned)(Op - Op->getUser()->OperandList); | |||
771 | } | |||
772 | }; | |||
773 | ||||
774 | /// Provide iteration support to walk over all uses of an SDNode. | |||
775 | use_iterator use_begin() const { | |||
776 | return use_iterator(UseList); | |||
777 | } | |||
778 | ||||
779 | static use_iterator use_end() { return use_iterator(nullptr); } | |||
780 | ||||
781 | inline iterator_range<use_iterator> uses() { | |||
782 | return make_range(use_begin(), use_end()); | |||
783 | } | |||
784 | inline iterator_range<use_iterator> uses() const { | |||
785 | return make_range(use_begin(), use_end()); | |||
786 | } | |||
787 | ||||
788 | /// Return true if there are exactly NUSES uses of the indicated value. | |||
789 | /// This method ignores uses of other values defined by this operation. | |||
790 | bool hasNUsesOfValue(unsigned NUses, unsigned Value) const; | |||
791 | ||||
792 | /// Return true if there are any use of the indicated value. | |||
793 | /// This method ignores uses of other values defined by this operation. | |||
794 | bool hasAnyUseOfValue(unsigned Value) const; | |||
795 | ||||
796 | /// Return true if this node is the only use of N. | |||
797 | bool isOnlyUserOf(const SDNode *N) const; | |||
798 | ||||
799 | /// Return true if this node is an operand of N. | |||
800 | bool isOperandOf(const SDNode *N) const; | |||
801 | ||||
802 | /// Return true if this node is a predecessor of N. | |||
803 | /// NOTE: Implemented on top of hasPredecessor and every bit as | |||
804 | /// expensive. Use carefully. | |||
805 | bool isPredecessorOf(const SDNode *N) const { | |||
806 | return N->hasPredecessor(this); | |||
807 | } | |||
808 | ||||
809 | /// Return true if N is a predecessor of this node. | |||
810 | /// N is either an operand of this node, or can be reached by recursively | |||
811 | /// traversing up the operands. | |||
812 | /// NOTE: This is an expensive method. Use it carefully. | |||
813 | bool hasPredecessor(const SDNode *N) const; | |||
814 | ||||
815 | /// Returns true if N is a predecessor of any node in Worklist. This | |||
816 | /// helper keeps Visited and Worklist sets externally to allow unions | |||
817 | /// searches to be performed in parallel, caching of results across | |||
818 | /// queries and incremental addition to Worklist. Stops early if N is | |||
819 | /// found but will resume. Remember to clear Visited and Worklists | |||
820 | /// if DAG changes. MaxSteps gives a maximum number of nodes to visit before | |||
821 | /// giving up. The TopologicalPrune flag signals that positive NodeIds are | |||
822 | /// topologically ordered (Operands have strictly smaller node id) and search | |||
823 | /// can be pruned leveraging this. | |||
824 | static bool hasPredecessorHelper(const SDNode *N, | |||
825 | SmallPtrSetImpl<const SDNode *> &Visited, | |||
826 | SmallVectorImpl<const SDNode *> &Worklist, | |||
827 | unsigned int MaxSteps = 0, | |||
828 | bool TopologicalPrune = false) { | |||
829 | SmallVector<const SDNode *, 8> DeferredNodes; | |||
830 | if (Visited.count(N)) | |||
831 | return true; | |||
832 | ||||
833 | // Node Id's are assigned in three places: As a topological | |||
834 | // ordering (> 0), during legalization (results in values set to | |||
835 | // 0), new nodes (set to -1). If N has a topolgical id then we | |||
836 | // know that all nodes with ids smaller than it cannot be | |||
837 | // successors and we need not check them. Filter out all node | |||
838 | // that can't be matches. We add them to the worklist before exit | |||
839 | // in case of multiple calls. Note that during selection the topological id | |||
840 | // may be violated if a node's predecessor is selected before it. We mark | |||
841 | // this at selection negating the id of unselected successors and | |||
842 | // restricting topological pruning to positive ids. | |||
843 | ||||
844 | int NId = N->getNodeId(); | |||
845 | // If we Invalidated the Id, reconstruct original NId. | |||
846 | if (NId < -1) | |||
847 | NId = -(NId + 1); | |||
848 | ||||
849 | bool Found = false; | |||
850 | while (!Worklist.empty()) { | |||
851 | const SDNode *M = Worklist.pop_back_val(); | |||
852 | int MId = M->getNodeId(); | |||
853 | if (TopologicalPrune && M->getOpcode() != ISD::TokenFactor && (NId > 0) && | |||
854 | (MId > 0) && (MId < NId)) { | |||
855 | DeferredNodes.push_back(M); | |||
856 | continue; | |||
857 | } | |||
858 | for (const SDValue &OpV : M->op_values()) { | |||
859 | SDNode *Op = OpV.getNode(); | |||
860 | if (Visited.insert(Op).second) | |||
861 | Worklist.push_back(Op); | |||
862 | if (Op == N) | |||
863 | Found = true; | |||
864 | } | |||
865 | if (Found) | |||
866 | break; | |||
867 | if (MaxSteps != 0 && Visited.size() >= MaxSteps) | |||
868 | break; | |||
869 | } | |||
870 | // Push deferred nodes back on worklist. | |||
871 | Worklist.append(DeferredNodes.begin(), DeferredNodes.end()); | |||
872 | // If we bailed early, conservatively return found. | |||
873 | if (MaxSteps != 0 && Visited.size() >= MaxSteps) | |||
874 | return true; | |||
875 | return Found; | |||
876 | } | |||
877 | ||||
878 | /// Return true if all the users of N are contained in Nodes. | |||
879 | /// NOTE: Requires at least one match, but doesn't require them all. | |||
880 | static bool areOnlyUsersOf(ArrayRef<const SDNode *> Nodes, const SDNode *N); | |||
881 | ||||
882 | /// Return the number of values used by this operation. | |||
883 | unsigned getNumOperands() const { return NumOperands; } | |||
884 | ||||
885 | /// Return the maximum number of operands that a SDNode can hold. | |||
886 | static constexpr size_t getMaxNumOperands() { | |||
887 | return std::numeric_limits<decltype(SDNode::NumOperands)>::max(); | |||
888 | } | |||
889 | ||||
890 | /// Helper method returns the integer value of a ConstantSDNode operand. | |||
891 | inline uint64_t getConstantOperandVal(unsigned Num) const; | |||
892 | ||||
893 | /// Helper method returns the APInt of a ConstantSDNode operand. | |||
894 | inline const APInt &getConstantOperandAPInt(unsigned Num) const; | |||
895 | ||||
896 | const SDValue &getOperand(unsigned Num) const { | |||
897 | assert(Num < NumOperands && "Invalid child # of SDNode!")((Num < NumOperands && "Invalid child # of SDNode!" ) ? static_cast<void> (0) : __assert_fail ("Num < NumOperands && \"Invalid child # of SDNode!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 897, __PRETTY_FUNCTION__)); | |||
898 | return OperandList[Num]; | |||
899 | } | |||
900 | ||||
901 | using op_iterator = SDUse *; | |||
902 | ||||
903 | op_iterator op_begin() const { return OperandList; } | |||
904 | op_iterator op_end() const { return OperandList+NumOperands; } | |||
905 | ArrayRef<SDUse> ops() const { return makeArrayRef(op_begin(), op_end()); } | |||
906 | ||||
907 | /// Iterator for directly iterating over the operand SDValue's. | |||
908 | struct value_op_iterator | |||
909 | : iterator_adaptor_base<value_op_iterator, op_iterator, | |||
910 | std::random_access_iterator_tag, SDValue, | |||
911 | ptrdiff_t, value_op_iterator *, | |||
912 | value_op_iterator *> { | |||
913 | explicit value_op_iterator(SDUse *U = nullptr) | |||
914 | : iterator_adaptor_base(U) {} | |||
915 | ||||
916 | const SDValue &operator*() const { return I->get(); } | |||
917 | }; | |||
918 | ||||
919 | iterator_range<value_op_iterator> op_values() const { | |||
920 | return make_range(value_op_iterator(op_begin()), | |||
921 | value_op_iterator(op_end())); | |||
922 | } | |||
923 | ||||
924 | SDVTList getVTList() const { | |||
925 | SDVTList X = { ValueList, NumValues }; | |||
926 | return X; | |||
927 | } | |||
928 | ||||
929 | /// If this node has a glue operand, return the node | |||
930 | /// to which the glue operand points. Otherwise return NULL. | |||
931 | SDNode *getGluedNode() const { | |||
932 | if (getNumOperands() != 0 && | |||
933 | getOperand(getNumOperands()-1).getValueType() == MVT::Glue) | |||
934 | return getOperand(getNumOperands()-1).getNode(); | |||
935 | return nullptr; | |||
936 | } | |||
937 | ||||
938 | /// If this node has a glue value with a user, return | |||
939 | /// the user (there is at most one). Otherwise return NULL. | |||
940 | SDNode *getGluedUser() const { | |||
941 | for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI) | |||
942 | if (UI.getUse().get().getValueType() == MVT::Glue) | |||
943 | return *UI; | |||
944 | return nullptr; | |||
945 | } | |||
946 | ||||
947 | SDNodeFlags getFlags() const { return Flags; } | |||
948 | void setFlags(SDNodeFlags NewFlags) { Flags = NewFlags; } | |||
949 | ||||
950 | /// Clear any flags in this node that aren't also set in Flags. | |||
951 | /// If Flags is not in a defined state then this has no effect. | |||
952 | void intersectFlagsWith(const SDNodeFlags Flags); | |||
953 | ||||
954 | /// Return the number of values defined/returned by this operator. | |||
955 | unsigned getNumValues() const { return NumValues; } | |||
956 | ||||
957 | /// Return the type of a specified result. | |||
958 | EVT getValueType(unsigned ResNo) const { | |||
959 | assert(ResNo < NumValues && "Illegal result number!")((ResNo < NumValues && "Illegal result number!") ? static_cast<void> (0) : __assert_fail ("ResNo < NumValues && \"Illegal result number!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 959, __PRETTY_FUNCTION__)); | |||
960 | return ValueList[ResNo]; | |||
961 | } | |||
962 | ||||
963 | /// Return the type of a specified result as a simple type. | |||
964 | MVT getSimpleValueType(unsigned ResNo) const { | |||
965 | return getValueType(ResNo).getSimpleVT(); | |||
966 | } | |||
967 | ||||
968 | /// Returns MVT::getSizeInBits(getValueType(ResNo)). | |||
969 | /// | |||
970 | /// If the value type is a scalable vector type, the scalable property will | |||
971 | /// be set and the runtime size will be a positive integer multiple of the | |||
972 | /// base size. | |||
973 | TypeSize getValueSizeInBits(unsigned ResNo) const { | |||
974 | return getValueType(ResNo).getSizeInBits(); | |||
975 | } | |||
976 | ||||
977 | using value_iterator = const EVT *; | |||
978 | ||||
979 | value_iterator value_begin() const { return ValueList; } | |||
980 | value_iterator value_end() const { return ValueList+NumValues; } | |||
981 | iterator_range<value_iterator> values() const { | |||
982 | return llvm::make_range(value_begin(), value_end()); | |||
983 | } | |||
984 | ||||
985 | /// Return the opcode of this operation for printing. | |||
986 | std::string getOperationName(const SelectionDAG *G = nullptr) const; | |||
987 | static const char* getIndexedModeName(ISD::MemIndexedMode AM); | |||
988 | void print_types(raw_ostream &OS, const SelectionDAG *G) const; | |||
989 | void print_details(raw_ostream &OS, const SelectionDAG *G) const; | |||
990 | void print(raw_ostream &OS, const SelectionDAG *G = nullptr) const; | |||
991 | void printr(raw_ostream &OS, const SelectionDAG *G = nullptr) const; | |||
992 | ||||
993 | /// Print a SelectionDAG node and all children down to | |||
994 | /// the leaves. The given SelectionDAG allows target-specific nodes | |||
995 | /// to be printed in human-readable form. Unlike printr, this will | |||
996 | /// print the whole DAG, including children that appear multiple | |||
997 | /// times. | |||
998 | /// | |||
999 | void printrFull(raw_ostream &O, const SelectionDAG *G = nullptr) const; | |||
1000 | ||||
1001 | /// Print a SelectionDAG node and children up to | |||
1002 | /// depth "depth." The given SelectionDAG allows target-specific | |||
1003 | /// nodes to be printed in human-readable form. Unlike printr, this | |||
1004 | /// will print children that appear multiple times wherever they are | |||
1005 | /// used. | |||
1006 | /// | |||
1007 | void printrWithDepth(raw_ostream &O, const SelectionDAG *G = nullptr, | |||
1008 | unsigned depth = 100) const; | |||
1009 | ||||
1010 | /// Dump this node, for debugging. | |||
1011 | void dump() const; | |||
1012 | ||||
1013 | /// Dump (recursively) this node and its use-def subgraph. | |||
1014 | void dumpr() const; | |||
1015 | ||||
1016 | /// Dump this node, for debugging. | |||
1017 | /// The given SelectionDAG allows target-specific nodes to be printed | |||
1018 | /// in human-readable form. | |||
1019 | void dump(const SelectionDAG *G) const; | |||
1020 | ||||
1021 | /// Dump (recursively) this node and its use-def subgraph. | |||
1022 | /// The given SelectionDAG allows target-specific nodes to be printed | |||
1023 | /// in human-readable form. | |||
1024 | void dumpr(const SelectionDAG *G) const; | |||
1025 | ||||
1026 | /// printrFull to dbgs(). The given SelectionDAG allows | |||
1027 | /// target-specific nodes to be printed in human-readable form. | |||
1028 | /// Unlike dumpr, this will print the whole DAG, including children | |||
1029 | /// that appear multiple times. | |||
1030 | void dumprFull(const SelectionDAG *G = nullptr) const; | |||
1031 | ||||
1032 | /// printrWithDepth to dbgs(). The given | |||
1033 | /// SelectionDAG allows target-specific nodes to be printed in | |||
1034 | /// human-readable form. Unlike dumpr, this will print children | |||
1035 | /// that appear multiple times wherever they are used. | |||
1036 | /// | |||
1037 | void dumprWithDepth(const SelectionDAG *G = nullptr, | |||
1038 | unsigned depth = 100) const; | |||
1039 | ||||
1040 | /// Gather unique data for the node. | |||
1041 | void Profile(FoldingSetNodeID &ID) const; | |||
1042 | ||||
1043 | /// This method should only be used by the SDUse class. | |||
1044 | void addUse(SDUse &U) { U.addToList(&UseList); } | |||
1045 | ||||
1046 | protected: | |||
1047 | static SDVTList getSDVTList(EVT VT) { | |||
1048 | SDVTList Ret = { getValueTypeList(VT), 1 }; | |||
1049 | return Ret; | |||
1050 | } | |||
1051 | ||||
1052 | /// Create an SDNode. | |||
1053 | /// | |||
1054 | /// SDNodes are created without any operands, and never own the operand | |||
1055 | /// storage. To add operands, see SelectionDAG::createOperands. | |||
1056 | SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) | |||
1057 | : NodeType(Opc), ValueList(VTs.VTs), NumValues(VTs.NumVTs), | |||
1058 | IROrder(Order), debugLoc(std::move(dl)) { | |||
1059 | memset(&RawSDNodeBits, 0, sizeof(RawSDNodeBits)); | |||
1060 | assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor")((debugLoc.hasTrivialDestructor() && "Expected trivial destructor" ) ? static_cast<void> (0) : __assert_fail ("debugLoc.hasTrivialDestructor() && \"Expected trivial destructor\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1060, __PRETTY_FUNCTION__)); | |||
1061 | assert(NumValues == VTs.NumVTs &&((NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!" ) ? static_cast<void> (0) : __assert_fail ("NumValues == VTs.NumVTs && \"NumValues wasn't wide enough for its operands!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1062, __PRETTY_FUNCTION__)) | |||
1062 | "NumValues wasn't wide enough for its operands!")((NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!" ) ? static_cast<void> (0) : __assert_fail ("NumValues == VTs.NumVTs && \"NumValues wasn't wide enough for its operands!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1062, __PRETTY_FUNCTION__)); | |||
1063 | } | |||
1064 | ||||
1065 | /// Release the operands and set this node to have zero operands. | |||
1066 | void DropOperands(); | |||
1067 | }; | |||
1068 | ||||
1069 | /// Wrapper class for IR location info (IR ordering and DebugLoc) to be passed | |||
1070 | /// into SDNode creation functions. | |||
1071 | /// When an SDNode is created from the DAGBuilder, the DebugLoc is extracted | |||
1072 | /// from the original Instruction, and IROrder is the ordinal position of | |||
1073 | /// the instruction. | |||
1074 | /// When an SDNode is created after the DAG is being built, both DebugLoc and | |||
1075 | /// the IROrder are propagated from the original SDNode. | |||
1076 | /// So SDLoc class provides two constructors besides the default one, one to | |||
1077 | /// be used by the DAGBuilder, the other to be used by others. | |||
1078 | class SDLoc { | |||
1079 | private: | |||
1080 | DebugLoc DL; | |||
1081 | int IROrder = 0; | |||
1082 | ||||
1083 | public: | |||
1084 | SDLoc() = default; | |||
1085 | SDLoc(const SDNode *N) : DL(N->getDebugLoc()), IROrder(N->getIROrder()) {} | |||
1086 | SDLoc(const SDValue V) : SDLoc(V.getNode()) {} | |||
1087 | SDLoc(const Instruction *I, int Order) : IROrder(Order) { | |||
1088 | assert(Order >= 0 && "bad IROrder")((Order >= 0 && "bad IROrder") ? static_cast<void > (0) : __assert_fail ("Order >= 0 && \"bad IROrder\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1088, __PRETTY_FUNCTION__)); | |||
1089 | if (I) | |||
1090 | DL = I->getDebugLoc(); | |||
1091 | } | |||
1092 | ||||
1093 | unsigned getIROrder() const { return IROrder; } | |||
1094 | const DebugLoc &getDebugLoc() const { return DL; } | |||
1095 | }; | |||
1096 | ||||
1097 | // Define inline functions from the SDValue class. | |||
1098 | ||||
1099 | inline SDValue::SDValue(SDNode *node, unsigned resno) | |||
1100 | : Node(node), ResNo(resno) { | |||
1101 | // Explicitly check for !ResNo to avoid use-after-free, because there are | |||
1102 | // callers that use SDValue(N, 0) with a deleted N to indicate successful | |||
1103 | // combines. | |||
1104 | assert((!Node || !ResNo || ResNo < Node->getNumValues()) &&(((!Node || !ResNo || ResNo < Node->getNumValues()) && "Invalid result number for the given node!") ? static_cast< void> (0) : __assert_fail ("(!Node || !ResNo || ResNo < Node->getNumValues()) && \"Invalid result number for the given node!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1105, __PRETTY_FUNCTION__)) | |||
1105 | "Invalid result number for the given node!")(((!Node || !ResNo || ResNo < Node->getNumValues()) && "Invalid result number for the given node!") ? static_cast< void> (0) : __assert_fail ("(!Node || !ResNo || ResNo < Node->getNumValues()) && \"Invalid result number for the given node!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1105, __PRETTY_FUNCTION__)); | |||
1106 | assert(ResNo < -2U && "Cannot use result numbers reserved for DenseMaps.")((ResNo < -2U && "Cannot use result numbers reserved for DenseMaps." ) ? static_cast<void> (0) : __assert_fail ("ResNo < -2U && \"Cannot use result numbers reserved for DenseMaps.\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1106, __PRETTY_FUNCTION__)); | |||
1107 | } | |||
1108 | ||||
1109 | inline unsigned SDValue::getOpcode() const { | |||
1110 | return Node->getOpcode(); | |||
1111 | } | |||
1112 | ||||
1113 | inline EVT SDValue::getValueType() const { | |||
1114 | return Node->getValueType(ResNo); | |||
| ||||
1115 | } | |||
1116 | ||||
1117 | inline unsigned SDValue::getNumOperands() const { | |||
1118 | return Node->getNumOperands(); | |||
1119 | } | |||
1120 | ||||
1121 | inline const SDValue &SDValue::getOperand(unsigned i) const { | |||
1122 | return Node->getOperand(i); | |||
1123 | } | |||
1124 | ||||
1125 | inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { | |||
1126 | return Node->getConstantOperandVal(i); | |||
1127 | } | |||
1128 | ||||
1129 | inline const APInt &SDValue::getConstantOperandAPInt(unsigned i) const { | |||
1130 | return Node->getConstantOperandAPInt(i); | |||
1131 | } | |||
1132 | ||||
1133 | inline bool SDValue::isTargetOpcode() const { | |||
1134 | return Node->isTargetOpcode(); | |||
1135 | } | |||
1136 | ||||
1137 | inline bool SDValue::isTargetMemoryOpcode() const { | |||
1138 | return Node->isTargetMemoryOpcode(); | |||
1139 | } | |||
1140 | ||||
1141 | inline bool SDValue::isMachineOpcode() const { | |||
1142 | return Node->isMachineOpcode(); | |||
1143 | } | |||
1144 | ||||
1145 | inline unsigned SDValue::getMachineOpcode() const { | |||
1146 | return Node->getMachineOpcode(); | |||
1147 | } | |||
1148 | ||||
1149 | inline bool SDValue::isUndef() const { | |||
1150 | return Node->isUndef(); | |||
1151 | } | |||
1152 | ||||
1153 | inline bool SDValue::use_empty() const { | |||
1154 | return !Node->hasAnyUseOfValue(ResNo); | |||
1155 | } | |||
1156 | ||||
1157 | inline bool SDValue::hasOneUse() const { | |||
1158 | return Node->hasNUsesOfValue(1, ResNo); | |||
1159 | } | |||
1160 | ||||
1161 | inline const DebugLoc &SDValue::getDebugLoc() const { | |||
1162 | return Node->getDebugLoc(); | |||
1163 | } | |||
1164 | ||||
1165 | inline void SDValue::dump() const { | |||
1166 | return Node->dump(); | |||
1167 | } | |||
1168 | ||||
1169 | inline void SDValue::dump(const SelectionDAG *G) const { | |||
1170 | return Node->dump(G); | |||
1171 | } | |||
1172 | ||||
1173 | inline void SDValue::dumpr() const { | |||
1174 | return Node->dumpr(); | |||
1175 | } | |||
1176 | ||||
1177 | inline void SDValue::dumpr(const SelectionDAG *G) const { | |||
1178 | return Node->dumpr(G); | |||
1179 | } | |||
1180 | ||||
1181 | // Define inline functions from the SDUse class. | |||
1182 | ||||
1183 | inline void SDUse::set(const SDValue &V) { | |||
1184 | if (Val.getNode()) removeFromList(); | |||
1185 | Val = V; | |||
1186 | if (V.getNode()) V.getNode()->addUse(*this); | |||
1187 | } | |||
1188 | ||||
1189 | inline void SDUse::setInitial(const SDValue &V) { | |||
1190 | Val = V; | |||
1191 | V.getNode()->addUse(*this); | |||
1192 | } | |||
1193 | ||||
1194 | inline void SDUse::setNode(SDNode *N) { | |||
1195 | if (Val.getNode()) removeFromList(); | |||
1196 | Val.setNode(N); | |||
1197 | if (N) N->addUse(*this); | |||
1198 | } | |||
1199 | ||||
1200 | /// This class is used to form a handle around another node that | |||
1201 | /// is persistent and is updated across invocations of replaceAllUsesWith on its | |||
1202 | /// operand. This node should be directly created by end-users and not added to | |||
1203 | /// the AllNodes list. | |||
1204 | class HandleSDNode : public SDNode { | |||
1205 | SDUse Op; | |||
1206 | ||||
1207 | public: | |||
1208 | explicit HandleSDNode(SDValue X) | |||
1209 | : SDNode(ISD::HANDLENODE, 0, DebugLoc(), getSDVTList(MVT::Other)) { | |||
1210 | // HandleSDNodes are never inserted into the DAG, so they won't be | |||
1211 | // auto-numbered. Use ID 65535 as a sentinel. | |||
1212 | PersistentId = 0xffff; | |||
1213 | ||||
1214 | // Manually set up the operand list. This node type is special in that it's | |||
1215 | // always stack allocated and SelectionDAG does not manage its operands. | |||
1216 | // TODO: This should either (a) not be in the SDNode hierarchy, or (b) not | |||
1217 | // be so special. | |||
1218 | Op.setUser(this); | |||
1219 | Op.setInitial(X); | |||
1220 | NumOperands = 1; | |||
1221 | OperandList = &Op; | |||
1222 | } | |||
1223 | ~HandleSDNode(); | |||
1224 | ||||
1225 | const SDValue &getValue() const { return Op; } | |||
1226 | }; | |||
1227 | ||||
1228 | class AddrSpaceCastSDNode : public SDNode { | |||
1229 | private: | |||
1230 | unsigned SrcAddrSpace; | |||
1231 | unsigned DestAddrSpace; | |||
1232 | ||||
1233 | public: | |||
1234 | AddrSpaceCastSDNode(unsigned Order, const DebugLoc &dl, EVT VT, | |||
1235 | unsigned SrcAS, unsigned DestAS); | |||
1236 | ||||
1237 | unsigned getSrcAddressSpace() const { return SrcAddrSpace; } | |||
1238 | unsigned getDestAddressSpace() const { return DestAddrSpace; } | |||
1239 | ||||
1240 | static bool classof(const SDNode *N) { | |||
1241 | return N->getOpcode() == ISD::ADDRSPACECAST; | |||
1242 | } | |||
1243 | }; | |||
1244 | ||||
1245 | /// This is an abstract virtual class for memory operations. | |||
1246 | class MemSDNode : public SDNode { | |||
1247 | private: | |||
1248 | // VT of in-memory value. | |||
1249 | EVT MemoryVT; | |||
1250 | ||||
1251 | protected: | |||
1252 | /// Memory reference information. | |||
1253 | MachineMemOperand *MMO; | |||
1254 | ||||
1255 | public: | |||
1256 | MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTs, | |||
1257 | EVT memvt, MachineMemOperand *MMO); | |||
1258 | ||||
1259 | bool readMem() const { return MMO->isLoad(); } | |||
1260 | bool writeMem() const { return MMO->isStore(); } | |||
1261 | ||||
1262 | /// Returns alignment and volatility of the memory access | |||
1263 | Align getOriginalAlign() const { return MMO->getBaseAlign(); } | |||
1264 | Align getAlign() const { return MMO->getAlign(); } | |||
1265 | LLVM_ATTRIBUTE_DEPRECATED(unsigned getOriginalAlignment() const,[[deprecated("Use getOriginalAlign() instead")]] unsigned getOriginalAlignment () const | |||
1266 | "Use getOriginalAlign() instead")[[deprecated("Use getOriginalAlign() instead")]] unsigned getOriginalAlignment () const { | |||
1267 | return MMO->getBaseAlign().value(); | |||
1268 | } | |||
1269 | // FIXME: Remove once transition to getAlign is over. | |||
1270 | unsigned getAlignment() const { return MMO->getAlign().value(); } | |||
1271 | ||||
1272 | /// Return the SubclassData value, without HasDebugValue. This contains an | |||
1273 | /// encoding of the volatile flag, as well as bits used by subclasses. This | |||
1274 | /// function should only be used to compute a FoldingSetNodeID value. | |||
1275 | /// The HasDebugValue bit is masked out because CSE map needs to match | |||
1276 | /// nodes with debug info with nodes without debug info. Same is about | |||
1277 | /// isDivergent bit. | |||
1278 | unsigned getRawSubclassData() const { | |||
1279 | uint16_t Data; | |||
1280 | union { | |||
1281 | char RawSDNodeBits[sizeof(uint16_t)]; | |||
1282 | SDNodeBitfields SDNodeBits; | |||
1283 | }; | |||
1284 | memcpy(&RawSDNodeBits, &this->RawSDNodeBits, sizeof(this->RawSDNodeBits)); | |||
1285 | SDNodeBits.HasDebugValue = 0; | |||
1286 | SDNodeBits.IsDivergent = false; | |||
1287 | memcpy(&Data, &RawSDNodeBits, sizeof(RawSDNodeBits)); | |||
1288 | return Data; | |||
1289 | } | |||
1290 | ||||
1291 | bool isVolatile() const { return MemSDNodeBits.IsVolatile; } | |||
1292 | bool isNonTemporal() const { return MemSDNodeBits.IsNonTemporal; } | |||
1293 | bool isDereferenceable() const { return MemSDNodeBits.IsDereferenceable; } | |||
1294 | bool isInvariant() const { return MemSDNodeBits.IsInvariant; } | |||
1295 | ||||
1296 | // Returns the offset from the location of the access. | |||
1297 | int64_t getSrcValueOffset() const { return MMO->getOffset(); } | |||
1298 | ||||
1299 | /// Returns the AA info that describes the dereference. | |||
1300 | AAMDNodes getAAInfo() const { return MMO->getAAInfo(); } | |||
1301 | ||||
1302 | /// Returns the Ranges that describes the dereference. | |||
1303 | const MDNode *getRanges() const { return MMO->getRanges(); } | |||
1304 | ||||
1305 | /// Returns the synchronization scope ID for this memory operation. | |||
1306 | SyncScope::ID getSyncScopeID() const { return MMO->getSyncScopeID(); } | |||
1307 | ||||
1308 | /// Return the atomic ordering requirements for this memory operation. For | |||
1309 | /// cmpxchg atomic operations, return the atomic ordering requirements when | |||
1310 | /// store occurs. | |||
1311 | AtomicOrdering getOrdering() const { return MMO->getOrdering(); } | |||
1312 | ||||
1313 | /// Return true if the memory operation ordering is Unordered or higher. | |||
1314 | bool isAtomic() const { return MMO->isAtomic(); } | |||
1315 | ||||
1316 | /// Returns true if the memory operation doesn't imply any ordering | |||
1317 | /// constraints on surrounding memory operations beyond the normal memory | |||
1318 | /// aliasing rules. | |||
1319 | bool isUnordered() const { return MMO->isUnordered(); } | |||
1320 | ||||
1321 | /// Returns true if the memory operation is neither atomic or volatile. | |||
1322 | bool isSimple() const { return !isAtomic() && !isVolatile(); } | |||
1323 | ||||
1324 | /// Return the type of the in-memory value. | |||
1325 | EVT getMemoryVT() const { return MemoryVT; } | |||
1326 | ||||
1327 | /// Return a MachineMemOperand object describing the memory | |||
1328 | /// reference performed by operation. | |||
1329 | MachineMemOperand *getMemOperand() const { return MMO; } | |||
1330 | ||||
1331 | const MachinePointerInfo &getPointerInfo() const { | |||
1332 | return MMO->getPointerInfo(); | |||
1333 | } | |||
1334 | ||||
1335 | /// Return the address space for the associated pointer | |||
1336 | unsigned getAddressSpace() const { | |||
1337 | return getPointerInfo().getAddrSpace(); | |||
1338 | } | |||
1339 | ||||
1340 | /// Update this MemSDNode's MachineMemOperand information | |||
1341 | /// to reflect the alignment of NewMMO, if it has a greater alignment. | |||
1342 | /// This must only be used when the new alignment applies to all users of | |||
1343 | /// this MachineMemOperand. | |||
1344 | void refineAlignment(const MachineMemOperand *NewMMO) { | |||
1345 | MMO->refineAlignment(NewMMO); | |||
1346 | } | |||
1347 | ||||
1348 | const SDValue &getChain() const { return getOperand(0); } | |||
1349 | ||||
1350 | const SDValue &getBasePtr() const { | |||
1351 | switch (getOpcode()) { | |||
1352 | case ISD::STORE: | |||
1353 | case ISD::MSTORE: | |||
1354 | return getOperand(2); | |||
1355 | case ISD::MGATHER: | |||
1356 | case ISD::MSCATTER: | |||
1357 | return getOperand(3); | |||
1358 | default: | |||
1359 | return getOperand(1); | |||
1360 | } | |||
1361 | } | |||
1362 | ||||
1363 | // Methods to support isa and dyn_cast | |||
1364 | static bool classof(const SDNode *N) { | |||
1365 | // For some targets, we lower some target intrinsics to a MemIntrinsicNode | |||
1366 | // with either an intrinsic or a target opcode. | |||
1367 | return N->getOpcode() == ISD::LOAD || | |||
1368 | N->getOpcode() == ISD::STORE || | |||
1369 | N->getOpcode() == ISD::PREFETCH || | |||
1370 | N->getOpcode() == ISD::ATOMIC_CMP_SWAP || | |||
1371 | N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS || | |||
1372 | N->getOpcode() == ISD::ATOMIC_SWAP || | |||
1373 | N->getOpcode() == ISD::ATOMIC_LOAD_ADD || | |||
1374 | N->getOpcode() == ISD::ATOMIC_LOAD_SUB || | |||
1375 | N->getOpcode() == ISD::ATOMIC_LOAD_AND || | |||
1376 | N->getOpcode() == ISD::ATOMIC_LOAD_CLR || | |||
1377 | N->getOpcode() == ISD::ATOMIC_LOAD_OR || | |||
1378 | N->getOpcode() == ISD::ATOMIC_LOAD_XOR || | |||
1379 | N->getOpcode() == ISD::ATOMIC_LOAD_NAND || | |||
1380 | N->getOpcode() == ISD::ATOMIC_LOAD_MIN || | |||
1381 | N->getOpcode() == ISD::ATOMIC_LOAD_MAX || | |||
1382 | N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || | |||
1383 | N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || | |||
1384 | N->getOpcode() == ISD::ATOMIC_LOAD_FADD || | |||
1385 | N->getOpcode() == ISD::ATOMIC_LOAD_FSUB || | |||
1386 | N->getOpcode() == ISD::ATOMIC_LOAD || | |||
1387 | N->getOpcode() == ISD::ATOMIC_STORE || | |||
1388 | N->getOpcode() == ISD::MLOAD || | |||
1389 | N->getOpcode() == ISD::MSTORE || | |||
1390 | N->getOpcode() == ISD::MGATHER || | |||
1391 | N->getOpcode() == ISD::MSCATTER || | |||
1392 | N->isMemIntrinsic() || | |||
1393 | N->isTargetMemoryOpcode(); | |||
1394 | } | |||
1395 | }; | |||
1396 | ||||
1397 | /// This is an SDNode representing atomic operations. | |||
1398 | class AtomicSDNode : public MemSDNode { | |||
1399 | public: | |||
1400 | AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL, | |||
1401 | EVT MemVT, MachineMemOperand *MMO) | |||
1402 | : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { | |||
1403 | assert(((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE) ||((((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE ) || MMO->isAtomic()) && "then why are we using an AtomicSDNode?" ) ? static_cast<void> (0) : __assert_fail ("((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE) || MMO->isAtomic()) && \"then why are we using an AtomicSDNode?\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1404, __PRETTY_FUNCTION__)) | |||
1404 | MMO->isAtomic()) && "then why are we using an AtomicSDNode?")((((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE ) || MMO->isAtomic()) && "then why are we using an AtomicSDNode?" ) ? static_cast<void> (0) : __assert_fail ("((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE) || MMO->isAtomic()) && \"then why are we using an AtomicSDNode?\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1404, __PRETTY_FUNCTION__)); | |||
1405 | } | |||
1406 | ||||
1407 | const SDValue &getBasePtr() const { return getOperand(1); } | |||
1408 | const SDValue &getVal() const { return getOperand(2); } | |||
1409 | ||||
1410 | /// Returns true if this SDNode represents cmpxchg atomic operation, false | |||
1411 | /// otherwise. | |||
1412 | bool isCompareAndSwap() const { | |||
1413 | unsigned Op = getOpcode(); | |||
1414 | return Op == ISD::ATOMIC_CMP_SWAP || | |||
1415 | Op == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS; | |||
1416 | } | |||
1417 | ||||
1418 | /// For cmpxchg atomic operations, return the atomic ordering requirements | |||
1419 | /// when store does not occur. | |||
1420 | AtomicOrdering getFailureOrdering() const { | |||
1421 | assert(isCompareAndSwap() && "Must be cmpxchg operation")((isCompareAndSwap() && "Must be cmpxchg operation") ? static_cast<void> (0) : __assert_fail ("isCompareAndSwap() && \"Must be cmpxchg operation\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1421, __PRETTY_FUNCTION__)); | |||
1422 | return MMO->getFailureOrdering(); | |||
1423 | } | |||
1424 | ||||
1425 | // Methods to support isa and dyn_cast | |||
1426 | static bool classof(const SDNode *N) { | |||
1427 | return N->getOpcode() == ISD::ATOMIC_CMP_SWAP || | |||
1428 | N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS || | |||
1429 | N->getOpcode() == ISD::ATOMIC_SWAP || | |||
1430 | N->getOpcode() == ISD::ATOMIC_LOAD_ADD || | |||
1431 | N->getOpcode() == ISD::ATOMIC_LOAD_SUB || | |||
1432 | N->getOpcode() == ISD::ATOMIC_LOAD_AND || | |||
1433 | N->getOpcode() == ISD::ATOMIC_LOAD_CLR || | |||
1434 | N->getOpcode() == ISD::ATOMIC_LOAD_OR || | |||
1435 | N->getOpcode() == ISD::ATOMIC_LOAD_XOR || | |||
1436 | N->getOpcode() == ISD::ATOMIC_LOAD_NAND || | |||
1437 | N->getOpcode() == ISD::ATOMIC_LOAD_MIN || | |||
1438 | N->getOpcode() == ISD::ATOMIC_LOAD_MAX || | |||
1439 | N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || | |||
1440 | N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || | |||
1441 | N->getOpcode() == ISD::ATOMIC_LOAD_FADD || | |||
1442 | N->getOpcode() == ISD::ATOMIC_LOAD_FSUB || | |||
1443 | N->getOpcode() == ISD::ATOMIC_LOAD || | |||
1444 | N->getOpcode() == ISD::ATOMIC_STORE; | |||
1445 | } | |||
1446 | }; | |||
1447 | ||||
1448 | /// This SDNode is used for target intrinsics that touch | |||
1449 | /// memory and need an associated MachineMemOperand. Its opcode may be | |||
1450 | /// INTRINSIC_VOID, INTRINSIC_W_CHAIN, PREFETCH, or a target-specific opcode | |||
1451 | /// with a value not less than FIRST_TARGET_MEMORY_OPCODE. | |||
1452 | class MemIntrinsicSDNode : public MemSDNode { | |||
1453 | public: | |||
1454 | MemIntrinsicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, | |||
1455 | SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO) | |||
1456 | : MemSDNode(Opc, Order, dl, VTs, MemoryVT, MMO) { | |||
1457 | SDNodeBits.IsMemIntrinsic = true; | |||
1458 | } | |||
1459 | ||||
1460 | // Methods to support isa and dyn_cast | |||
1461 | static bool classof(const SDNode *N) { | |||
1462 | // We lower some target intrinsics to their target opcode | |||
1463 | // early a node with a target opcode can be of this class | |||
1464 | return N->isMemIntrinsic() || | |||
1465 | N->getOpcode() == ISD::PREFETCH || | |||
1466 | N->isTargetMemoryOpcode(); | |||
1467 | } | |||
1468 | }; | |||
1469 | ||||
1470 | /// This SDNode is used to implement the code generator | |||
1471 | /// support for the llvm IR shufflevector instruction. It combines elements | |||
1472 | /// from two input vectors into a new input vector, with the selection and | |||
1473 | /// ordering of elements determined by an array of integers, referred to as | |||
1474 | /// the shuffle mask. For input vectors of width N, mask indices of 0..N-1 | |||
1475 | /// refer to elements from the LHS input, and indices from N to 2N-1 the RHS. | |||
1476 | /// An index of -1 is treated as undef, such that the code generator may put | |||
1477 | /// any value in the corresponding element of the result. | |||
1478 | class ShuffleVectorSDNode : public SDNode { | |||
1479 | // The memory for Mask is owned by the SelectionDAG's OperandAllocator, and | |||
1480 | // is freed when the SelectionDAG object is destroyed. | |||
1481 | const int *Mask; | |||
1482 | ||||
1483 | protected: | |||
1484 | friend class SelectionDAG; | |||
1485 | ||||
1486 | ShuffleVectorSDNode(EVT VT, unsigned Order, const DebugLoc &dl, const int *M) | |||
1487 | : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) {} | |||
1488 | ||||
1489 | public: | |||
1490 | ArrayRef<int> getMask() const { | |||
1491 | EVT VT = getValueType(0); | |||
1492 | return makeArrayRef(Mask, VT.getVectorNumElements()); | |||
1493 | } | |||
1494 | ||||
1495 | int getMaskElt(unsigned Idx) const { | |||
1496 | assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!")((Idx < getValueType(0).getVectorNumElements() && "Idx out of range!" ) ? static_cast<void> (0) : __assert_fail ("Idx < getValueType(0).getVectorNumElements() && \"Idx out of range!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1496, __PRETTY_FUNCTION__)); | |||
1497 | return Mask[Idx]; | |||
1498 | } | |||
1499 | ||||
1500 | bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } | |||
1501 | ||||
1502 | int getSplatIndex() const { | |||
1503 | assert(isSplat() && "Cannot get splat index for non-splat!")((isSplat() && "Cannot get splat index for non-splat!" ) ? static_cast<void> (0) : __assert_fail ("isSplat() && \"Cannot get splat index for non-splat!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1503, __PRETTY_FUNCTION__)); | |||
1504 | EVT VT = getValueType(0); | |||
1505 | for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) | |||
1506 | if (Mask[i] >= 0) | |||
1507 | return Mask[i]; | |||
1508 | ||||
1509 | // We can choose any index value here and be correct because all elements | |||
1510 | // are undefined. Return 0 for better potential for callers to simplify. | |||
1511 | return 0; | |||
1512 | } | |||
1513 | ||||
1514 | static bool isSplatMask(const int *Mask, EVT VT); | |||
1515 | ||||
1516 | /// Change values in a shuffle permute mask assuming | |||
1517 | /// the two vector operands have swapped position. | |||
1518 | static void commuteMask(MutableArrayRef<int> Mask) { | |||
1519 | unsigned NumElems = Mask.size(); | |||
1520 | for (unsigned i = 0; i != NumElems; ++i) { | |||
1521 | int idx = Mask[i]; | |||
1522 | if (idx < 0) | |||
1523 | continue; | |||
1524 | else if (idx < (int)NumElems) | |||
1525 | Mask[i] = idx + NumElems; | |||
1526 | else | |||
1527 | Mask[i] = idx - NumElems; | |||
1528 | } | |||
1529 | } | |||
1530 | ||||
1531 | static bool classof(const SDNode *N) { | |||
1532 | return N->getOpcode() == ISD::VECTOR_SHUFFLE; | |||
1533 | } | |||
1534 | }; | |||
1535 | ||||
1536 | class ConstantSDNode : public SDNode { | |||
1537 | friend class SelectionDAG; | |||
1538 | ||||
1539 | const ConstantInt *Value; | |||
1540 | ||||
1541 | ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, EVT VT) | |||
1542 | : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DebugLoc(), | |||
1543 | getSDVTList(VT)), | |||
1544 | Value(val) { | |||
1545 | ConstantSDNodeBits.IsOpaque = isOpaque; | |||
1546 | } | |||
1547 | ||||
1548 | public: | |||
1549 | const ConstantInt *getConstantIntValue() const { return Value; } | |||
1550 | const APInt &getAPIntValue() const { return Value->getValue(); } | |||
1551 | uint64_t getZExtValue() const { return Value->getZExtValue(); } | |||
1552 | int64_t getSExtValue() const { return Value->getSExtValue(); } | |||
1553 | uint64_t getLimitedValue(uint64_t Limit = UINT64_MAX(18446744073709551615UL)) { | |||
1554 | return Value->getLimitedValue(Limit); | |||
1555 | } | |||
1556 | MaybeAlign getMaybeAlignValue() const { return Value->getMaybeAlignValue(); } | |||
1557 | Align getAlignValue() const { return Value->getAlignValue(); } | |||
1558 | ||||
1559 | bool isOne() const { return Value->isOne(); } | |||
1560 | bool isNullValue() const { return Value->isZero(); } | |||
1561 | bool isAllOnesValue() const { return Value->isMinusOne(); } | |||
1562 | ||||
1563 | bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; } | |||
1564 | ||||
1565 | static bool classof(const SDNode *N) { | |||
1566 | return N->getOpcode() == ISD::Constant || | |||
1567 | N->getOpcode() == ISD::TargetConstant; | |||
1568 | } | |||
1569 | }; | |||
1570 | ||||
1571 | uint64_t SDNode::getConstantOperandVal(unsigned Num) const { | |||
1572 | return cast<ConstantSDNode>(getOperand(Num))->getZExtValue(); | |||
1573 | } | |||
1574 | ||||
1575 | const APInt &SDNode::getConstantOperandAPInt(unsigned Num) const { | |||
1576 | return cast<ConstantSDNode>(getOperand(Num))->getAPIntValue(); | |||
1577 | } | |||
1578 | ||||
1579 | class ConstantFPSDNode : public SDNode { | |||
1580 | friend class SelectionDAG; | |||
1581 | ||||
1582 | const ConstantFP *Value; | |||
1583 | ||||
1584 | ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) | |||
1585 | : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, | |||
1586 | DebugLoc(), getSDVTList(VT)), | |||
1587 | Value(val) {} | |||
1588 | ||||
1589 | public: | |||
1590 | const APFloat& getValueAPF() const { return Value->getValueAPF(); } | |||
1591 | const ConstantFP *getConstantFPValue() const { return Value; } | |||
1592 | ||||
1593 | /// Return true if the value is positive or negative zero. | |||
1594 | bool isZero() const { return Value->isZero(); } | |||
1595 | ||||
1596 | /// Return true if the value is a NaN. | |||
1597 | bool isNaN() const { return Value->isNaN(); } | |||
1598 | ||||
1599 | /// Return true if the value is an infinity | |||
1600 | bool isInfinity() const { return Value->isInfinity(); } | |||
1601 | ||||
1602 | /// Return true if the value is negative. | |||
1603 | bool isNegative() const { return Value->isNegative(); } | |||
1604 | ||||
1605 | /// We don't rely on operator== working on double values, as | |||
1606 | /// it returns true for things that are clearly not equal, like -0.0 and 0.0. | |||
1607 | /// As such, this method can be used to do an exact bit-for-bit comparison of | |||
1608 | /// two floating point values. | |||
1609 | ||||
1610 | /// We leave the version with the double argument here because it's just so | |||
1611 | /// convenient to write "2.0" and the like. Without this function we'd | |||
1612 | /// have to duplicate its logic everywhere it's called. | |||
1613 | bool isExactlyValue(double V) const { | |||
1614 | return Value->getValueAPF().isExactlyValue(V); | |||
1615 | } | |||
1616 | bool isExactlyValue(const APFloat& V) const; | |||
1617 | ||||
1618 | static bool isValueValidForType(EVT VT, const APFloat& Val); | |||
1619 | ||||
1620 | static bool classof(const SDNode *N) { | |||
1621 | return N->getOpcode() == ISD::ConstantFP || | |||
1622 | N->getOpcode() == ISD::TargetConstantFP; | |||
1623 | } | |||
1624 | }; | |||
1625 | ||||
1626 | /// Returns true if \p V is a constant integer zero. | |||
1627 | bool isNullConstant(SDValue V); | |||
1628 | ||||
1629 | /// Returns true if \p V is an FP constant with a value of positive zero. | |||
1630 | bool isNullFPConstant(SDValue V); | |||
1631 | ||||
1632 | /// Returns true if \p V is an integer constant with all bits set. | |||
1633 | bool isAllOnesConstant(SDValue V); | |||
1634 | ||||
1635 | /// Returns true if \p V is a constant integer one. | |||
1636 | bool isOneConstant(SDValue V); | |||
1637 | ||||
1638 | /// Return the non-bitcasted source operand of \p V if it exists. | |||
1639 | /// If \p V is not a bitcasted value, it is returned as-is. | |||
1640 | SDValue peekThroughBitcasts(SDValue V); | |||
1641 | ||||
1642 | /// Return the non-bitcasted and one-use source operand of \p V if it exists. | |||
1643 | /// If \p V is not a bitcasted one-use value, it is returned as-is. | |||
1644 | SDValue peekThroughOneUseBitcasts(SDValue V); | |||
1645 | ||||
1646 | /// Return the non-extracted vector source operand of \p V if it exists. | |||
1647 | /// If \p V is not an extracted subvector, it is returned as-is. | |||
1648 | SDValue peekThroughExtractSubvectors(SDValue V); | |||
1649 | ||||
1650 | /// Returns true if \p V is a bitwise not operation. Assumes that an all ones | |||
1651 | /// constant is canonicalized to be operand 1. | |||
1652 | bool isBitwiseNot(SDValue V, bool AllowUndefs = false); | |||
1653 | ||||
1654 | /// Returns the SDNode if it is a constant splat BuildVector or constant int. | |||
1655 | ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false, | |||
1656 | bool AllowTruncation = false); | |||
1657 | ||||
1658 | /// Returns the SDNode if it is a demanded constant splat BuildVector or | |||
1659 | /// constant int. | |||
1660 | ConstantSDNode *isConstOrConstSplat(SDValue N, const APInt &DemandedElts, | |||
1661 | bool AllowUndefs = false, | |||
1662 | bool AllowTruncation = false); | |||
1663 | ||||
1664 | /// Returns the SDNode if it is a constant splat BuildVector or constant float. | |||
1665 | ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, bool AllowUndefs = false); | |||
1666 | ||||
1667 | /// Returns the SDNode if it is a demanded constant splat BuildVector or | |||
1668 | /// constant float. | |||
1669 | ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, const APInt &DemandedElts, | |||
1670 | bool AllowUndefs = false); | |||
1671 | ||||
1672 | /// Return true if the value is a constant 0 integer or a splatted vector of | |||
1673 | /// a constant 0 integer (with no undefs by default). | |||
1674 | /// Build vector implicit truncation is not an issue for null values. | |||
1675 | bool isNullOrNullSplat(SDValue V, bool AllowUndefs = false); | |||
1676 | ||||
1677 | /// Return true if the value is a constant 1 integer or a splatted vector of a | |||
1678 | /// constant 1 integer (with no undefs). | |||
1679 | /// Does not permit build vector implicit truncation. | |||
1680 | bool isOneOrOneSplat(SDValue V, bool AllowUndefs = false); | |||
1681 | ||||
1682 | /// Return true if the value is a constant -1 integer or a splatted vector of a | |||
1683 | /// constant -1 integer (with no undefs). | |||
1684 | /// Does not permit build vector implicit truncation. | |||
1685 | bool isAllOnesOrAllOnesSplat(SDValue V, bool AllowUndefs = false); | |||
1686 | ||||
1687 | /// Return true if \p V is either a integer or FP constant. | |||
1688 | inline bool isIntOrFPConstant(SDValue V) { | |||
1689 | return isa<ConstantSDNode>(V) || isa<ConstantFPSDNode>(V); | |||
1690 | } | |||
1691 | ||||
1692 | class GlobalAddressSDNode : public SDNode { | |||
1693 | friend class SelectionDAG; | |||
1694 | ||||
1695 | const GlobalValue *TheGlobal; | |||
1696 | int64_t Offset; | |||
1697 | unsigned TargetFlags; | |||
1698 | ||||
1699 | GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, | |||
1700 | const GlobalValue *GA, EVT VT, int64_t o, | |||
1701 | unsigned TF); | |||
1702 | ||||
1703 | public: | |||
1704 | const GlobalValue *getGlobal() const { return TheGlobal; } | |||
1705 | int64_t getOffset() const { return Offset; } | |||
1706 | unsigned getTargetFlags() const { return TargetFlags; } | |||
1707 | // Return the address space this GlobalAddress belongs to. | |||
1708 | unsigned getAddressSpace() const; | |||
1709 | ||||
1710 | static bool classof(const SDNode *N) { | |||
1711 | return N->getOpcode() == ISD::GlobalAddress || | |||
1712 | N->getOpcode() == ISD::TargetGlobalAddress || | |||
1713 | N->getOpcode() == ISD::GlobalTLSAddress || | |||
1714 | N->getOpcode() == ISD::TargetGlobalTLSAddress; | |||
1715 | } | |||
1716 | }; | |||
1717 | ||||
1718 | class FrameIndexSDNode : public SDNode { | |||
1719 | friend class SelectionDAG; | |||
1720 | ||||
1721 | int FI; | |||
1722 | ||||
1723 | FrameIndexSDNode(int fi, EVT VT, bool isTarg) | |||
1724 | : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, | |||
1725 | 0, DebugLoc(), getSDVTList(VT)), FI(fi) { | |||
1726 | } | |||
1727 | ||||
1728 | public: | |||
1729 | int getIndex() const { return FI; } | |||
1730 | ||||
1731 | static bool classof(const SDNode *N) { | |||
1732 | return N->getOpcode() == ISD::FrameIndex || | |||
1733 | N->getOpcode() == ISD::TargetFrameIndex; | |||
1734 | } | |||
1735 | }; | |||
1736 | ||||
1737 | /// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate | |||
1738 | /// the offet and size that are started/ended in the underlying FrameIndex. | |||
1739 | class LifetimeSDNode : public SDNode { | |||
1740 | friend class SelectionDAG; | |||
1741 | int64_t Size; | |||
1742 | int64_t Offset; // -1 if offset is unknown. | |||
1743 | ||||
1744 | LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, | |||
1745 | SDVTList VTs, int64_t Size, int64_t Offset) | |||
1746 | : SDNode(Opcode, Order, dl, VTs), Size(Size), Offset(Offset) {} | |||
1747 | public: | |||
1748 | int64_t getFrameIndex() const { | |||
1749 | return cast<FrameIndexSDNode>(getOperand(1))->getIndex(); | |||
1750 | } | |||
1751 | ||||
1752 | bool hasOffset() const { return Offset >= 0; } | |||
1753 | int64_t getOffset() const { | |||
1754 | assert(hasOffset() && "offset is unknown")((hasOffset() && "offset is unknown") ? static_cast< void> (0) : __assert_fail ("hasOffset() && \"offset is unknown\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1754, __PRETTY_FUNCTION__)); | |||
1755 | return Offset; | |||
1756 | } | |||
1757 | int64_t getSize() const { | |||
1758 | assert(hasOffset() && "offset is unknown")((hasOffset() && "offset is unknown") ? static_cast< void> (0) : __assert_fail ("hasOffset() && \"offset is unknown\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1758, __PRETTY_FUNCTION__)); | |||
1759 | return Size; | |||
1760 | } | |||
1761 | ||||
1762 | // Methods to support isa and dyn_cast | |||
1763 | static bool classof(const SDNode *N) { | |||
1764 | return N->getOpcode() == ISD::LIFETIME_START || | |||
1765 | N->getOpcode() == ISD::LIFETIME_END; | |||
1766 | } | |||
1767 | }; | |||
1768 | ||||
1769 | /// This SDNode is used for PSEUDO_PROBE values, which are the function guid and | |||
1770 | /// the index of the basic block being probed. A pseudo probe serves as a place | |||
1771 | /// holder and will be removed at the end of compilation. It does not have any | |||
1772 | /// operand because we do not want the instruction selection to deal with any. | |||
1773 | class PseudoProbeSDNode : public SDNode { | |||
1774 | friend class SelectionDAG; | |||
1775 | uint64_t Guid; | |||
1776 | uint64_t Index; | |||
1777 | uint32_t Attributes; | |||
1778 | ||||
1779 | PseudoProbeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &Dl, | |||
1780 | SDVTList VTs, uint64_t Guid, uint64_t Index, uint32_t Attr) | |||
1781 | : SDNode(Opcode, Order, Dl, VTs), Guid(Guid), Index(Index), | |||
1782 | Attributes(Attr) {} | |||
1783 | ||||
1784 | public: | |||
1785 | uint64_t getGuid() const { return Guid; } | |||
1786 | uint64_t getIndex() const { return Index; } | |||
1787 | uint32_t getAttributes() const { return Attributes; } | |||
1788 | ||||
1789 | // Methods to support isa and dyn_cast | |||
1790 | static bool classof(const SDNode *N) { | |||
1791 | return N->getOpcode() == ISD::PSEUDO_PROBE; | |||
1792 | } | |||
1793 | }; | |||
1794 | ||||
1795 | class JumpTableSDNode : public SDNode { | |||
1796 | friend class SelectionDAG; | |||
1797 | ||||
1798 | int JTI; | |||
1799 | unsigned TargetFlags; | |||
1800 | ||||
1801 | JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned TF) | |||
1802 | : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, | |||
1803 | 0, DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { | |||
1804 | } | |||
1805 | ||||
1806 | public: | |||
1807 | int getIndex() const { return JTI; } | |||
1808 | unsigned getTargetFlags() const { return TargetFlags; } | |||
1809 | ||||
1810 | static bool classof(const SDNode *N) { | |||
1811 | return N->getOpcode() == ISD::JumpTable || | |||
1812 | N->getOpcode() == ISD::TargetJumpTable; | |||
1813 | } | |||
1814 | }; | |||
1815 | ||||
1816 | class ConstantPoolSDNode : public SDNode { | |||
1817 | friend class SelectionDAG; | |||
1818 | ||||
1819 | union { | |||
1820 | const Constant *ConstVal; | |||
1821 | MachineConstantPoolValue *MachineCPVal; | |||
1822 | } Val; | |||
1823 | int Offset; // It's a MachineConstantPoolValue if top bit is set. | |||
1824 | Align Alignment; // Minimum alignment requirement of CP. | |||
1825 | unsigned TargetFlags; | |||
1826 | ||||
1827 | ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o, | |||
1828 | Align Alignment, unsigned TF) | |||
1829 | : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, | |||
1830 | DebugLoc(), getSDVTList(VT)), | |||
1831 | Offset(o), Alignment(Alignment), TargetFlags(TF) { | |||
1832 | assert(Offset >= 0 && "Offset is too large")((Offset >= 0 && "Offset is too large") ? static_cast <void> (0) : __assert_fail ("Offset >= 0 && \"Offset is too large\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1832, __PRETTY_FUNCTION__)); | |||
1833 | Val.ConstVal = c; | |||
1834 | } | |||
1835 | ||||
1836 | ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, EVT VT, int o, | |||
1837 | Align Alignment, unsigned TF) | |||
1838 | : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, | |||
1839 | DebugLoc(), getSDVTList(VT)), | |||
1840 | Offset(o), Alignment(Alignment), TargetFlags(TF) { | |||
1841 | assert(Offset >= 0 && "Offset is too large")((Offset >= 0 && "Offset is too large") ? static_cast <void> (0) : __assert_fail ("Offset >= 0 && \"Offset is too large\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1841, __PRETTY_FUNCTION__)); | |||
1842 | Val.MachineCPVal = v; | |||
1843 | Offset |= 1 << (sizeof(unsigned)*CHAR_BIT8-1); | |||
1844 | } | |||
1845 | ||||
1846 | public: | |||
1847 | bool isMachineConstantPoolEntry() const { | |||
1848 | return Offset < 0; | |||
1849 | } | |||
1850 | ||||
1851 | const Constant *getConstVal() const { | |||
1852 | assert(!isMachineConstantPoolEntry() && "Wrong constantpool type")((!isMachineConstantPoolEntry() && "Wrong constantpool type" ) ? static_cast<void> (0) : __assert_fail ("!isMachineConstantPoolEntry() && \"Wrong constantpool type\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1852, __PRETTY_FUNCTION__)); | |||
1853 | return Val.ConstVal; | |||
1854 | } | |||
1855 | ||||
1856 | MachineConstantPoolValue *getMachineCPVal() const { | |||
1857 | assert(isMachineConstantPoolEntry() && "Wrong constantpool type")((isMachineConstantPoolEntry() && "Wrong constantpool type" ) ? static_cast<void> (0) : __assert_fail ("isMachineConstantPoolEntry() && \"Wrong constantpool type\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 1857, __PRETTY_FUNCTION__)); | |||
1858 | return Val.MachineCPVal; | |||
1859 | } | |||
1860 | ||||
1861 | int getOffset() const { | |||
1862 | return Offset & ~(1 << (sizeof(unsigned)*CHAR_BIT8-1)); | |||
1863 | } | |||
1864 | ||||
1865 | // Return the alignment of this constant pool object, which is either 0 (for | |||
1866 | // default alignment) or the desired value. | |||
1867 | Align getAlign() const { return Alignment; } | |||
1868 | unsigned getTargetFlags() const { return TargetFlags; } | |||
1869 | ||||
1870 | Type *getType() const; | |||
1871 | ||||
1872 | static bool classof(const SDNode *N) { | |||
1873 | return N->getOpcode() == ISD::ConstantPool || | |||
1874 | N->getOpcode() == ISD::TargetConstantPool; | |||
1875 | } | |||
1876 | }; | |||
1877 | ||||
1878 | /// Completely target-dependent object reference. | |||
1879 | class TargetIndexSDNode : public SDNode { | |||
1880 | friend class SelectionDAG; | |||
1881 | ||||
1882 | unsigned TargetFlags; | |||
1883 | int Index; | |||
1884 | int64_t Offset; | |||
1885 | ||||
1886 | public: | |||
1887 | TargetIndexSDNode(int Idx, EVT VT, int64_t Ofs, unsigned TF) | |||
1888 | : SDNode(ISD::TargetIndex, 0, DebugLoc(), getSDVTList(VT)), | |||
1889 | TargetFlags(TF), Index(Idx), Offset(Ofs) {} | |||
1890 | ||||
1891 | unsigned getTargetFlags() const { return TargetFlags; } | |||
1892 | int getIndex() const { return Index; } | |||
1893 | int64_t getOffset() const { return Offset; } | |||
1894 | ||||
1895 | static bool classof(const SDNode *N) { | |||
1896 | return N->getOpcode() == ISD::TargetIndex; | |||
1897 | } | |||
1898 | }; | |||
1899 | ||||
1900 | class BasicBlockSDNode : public SDNode { | |||
1901 | friend class SelectionDAG; | |||
1902 | ||||
1903 | MachineBasicBlock *MBB; | |||
1904 | ||||
1905 | /// Debug info is meaningful and potentially useful here, but we create | |||
1906 | /// blocks out of order when they're jumped to, which makes it a bit | |||
1907 | /// harder. Let's see if we need it first. | |||
1908 | explicit BasicBlockSDNode(MachineBasicBlock *mbb) | |||
1909 | : SDNode(ISD::BasicBlock, 0, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) | |||
1910 | {} | |||
1911 | ||||
1912 | public: | |||
1913 | MachineBasicBlock *getBasicBlock() const { return MBB; } | |||
1914 | ||||
1915 | static bool classof(const SDNode *N) { | |||
1916 | return N->getOpcode() == ISD::BasicBlock; | |||
1917 | } | |||
1918 | }; | |||
1919 | ||||
1920 | /// A "pseudo-class" with methods for operating on BUILD_VECTORs. | |||
1921 | class BuildVectorSDNode : public SDNode { | |||
1922 | public: | |||
1923 | // These are constructed as SDNodes and then cast to BuildVectorSDNodes. | |||
1924 | explicit BuildVectorSDNode() = delete; | |||
1925 | ||||
1926 | /// Check if this is a constant splat, and if so, find the | |||
1927 | /// smallest element size that splats the vector. If MinSplatBits is | |||
1928 | /// nonzero, the element size must be at least that large. Note that the | |||
1929 | /// splat element may be the entire vector (i.e., a one element vector). | |||
1930 | /// Returns the splat element value in SplatValue. Any undefined bits in | |||
1931 | /// that value are zero, and the corresponding bits in the SplatUndef mask | |||
1932 | /// are set. The SplatBitSize value is set to the splat element size in | |||
1933 | /// bits. HasAnyUndefs is set to true if any bits in the vector are | |||
1934 | /// undefined. isBigEndian describes the endianness of the target. | |||
1935 | bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, | |||
1936 | unsigned &SplatBitSize, bool &HasAnyUndefs, | |||
1937 | unsigned MinSplatBits = 0, | |||
1938 | bool isBigEndian = false) const; | |||
1939 | ||||
1940 | /// Returns the demanded splatted value or a null value if this is not a | |||
1941 | /// splat. | |||
1942 | /// | |||
1943 | /// The DemandedElts mask indicates the elements that must be in the splat. | |||
1944 | /// If passed a non-null UndefElements bitvector, it will resize it to match | |||
1945 | /// the vector width and set the bits where elements are undef. | |||
1946 | SDValue getSplatValue(const APInt &DemandedElts, | |||
1947 | BitVector *UndefElements = nullptr) const; | |||
1948 | ||||
1949 | /// Returns the splatted value or a null value if this is not a splat. | |||
1950 | /// | |||
1951 | /// If passed a non-null UndefElements bitvector, it will resize it to match | |||
1952 | /// the vector width and set the bits where elements are undef. | |||
1953 | SDValue getSplatValue(BitVector *UndefElements = nullptr) const; | |||
1954 | ||||
1955 | /// Find the shortest repeating sequence of values in the build vector. | |||
1956 | /// | |||
1957 | /// e.g. { u, X, u, X, u, u, X, u } -> { X } | |||
1958 | /// { X, Y, u, Y, u, u, X, u } -> { X, Y } | |||
1959 | /// | |||
1960 | /// Currently this must be a power-of-2 build vector. | |||
1961 | /// The DemandedElts mask indicates the elements that must be present, | |||
1962 | /// undemanded elements in Sequence may be null (SDValue()). If passed a | |||
1963 | /// non-null UndefElements bitvector, it will resize it to match the original | |||
1964 | /// vector width and set the bits where elements are undef. If result is | |||
1965 | /// false, Sequence will be empty. | |||
1966 | bool getRepeatedSequence(const APInt &DemandedElts, | |||
1967 | SmallVectorImpl<SDValue> &Sequence, | |||
1968 | BitVector *UndefElements = nullptr) const; | |||
1969 | ||||
1970 | /// Find the shortest repeating sequence of values in the build vector. | |||
1971 | /// | |||
1972 | /// e.g. { u, X, u, X, u, u, X, u } -> { X } | |||
1973 | /// { X, Y, u, Y, u, u, X, u } -> { X, Y } | |||
1974 | /// | |||
1975 | /// Currently this must be a power-of-2 build vector. | |||
1976 | /// If passed a non-null UndefElements bitvector, it will resize it to match | |||
1977 | /// the original vector width and set the bits where elements are undef. | |||
1978 | /// If result is false, Sequence will be empty. | |||
1979 | bool getRepeatedSequence(SmallVectorImpl<SDValue> &Sequence, | |||
1980 | BitVector *UndefElements = nullptr) const; | |||
1981 | ||||
1982 | /// Returns the demanded splatted constant or null if this is not a constant | |||
1983 | /// splat. | |||
1984 | /// | |||
1985 | /// The DemandedElts mask indicates the elements that must be in the splat. | |||
1986 | /// If passed a non-null UndefElements bitvector, it will resize it to match | |||
1987 | /// the vector width and set the bits where elements are undef. | |||
1988 | ConstantSDNode * | |||
1989 | getConstantSplatNode(const APInt &DemandedElts, | |||
1990 | BitVector *UndefElements = nullptr) const; | |||
1991 | ||||
1992 | /// Returns the splatted constant or null if this is not a constant | |||
1993 | /// splat. | |||
1994 | /// | |||
1995 | /// If passed a non-null UndefElements bitvector, it will resize it to match | |||
1996 | /// the vector width and set the bits where elements are undef. | |||
1997 | ConstantSDNode * | |||
1998 | getConstantSplatNode(BitVector *UndefElements = nullptr) const; | |||
1999 | ||||
2000 | /// Returns the demanded splatted constant FP or null if this is not a | |||
2001 | /// constant FP splat. | |||
2002 | /// | |||
2003 | /// The DemandedElts mask indicates the elements that must be in the splat. | |||
2004 | /// If passed a non-null UndefElements bitvector, it will resize it to match | |||
2005 | /// the vector width and set the bits where elements are undef. | |||
2006 | ConstantFPSDNode * | |||
2007 | getConstantFPSplatNode(const APInt &DemandedElts, | |||
2008 | BitVector *UndefElements = nullptr) const; | |||
2009 | ||||
2010 | /// Returns the splatted constant FP or null if this is not a constant | |||
2011 | /// FP splat. | |||
2012 | /// | |||
2013 | /// If passed a non-null UndefElements bitvector, it will resize it to match | |||
2014 | /// the vector width and set the bits where elements are undef. | |||
2015 | ConstantFPSDNode * | |||
2016 | getConstantFPSplatNode(BitVector *UndefElements = nullptr) const; | |||
2017 | ||||
2018 | /// If this is a constant FP splat and the splatted constant FP is an | |||
2019 | /// exact power or 2, return the log base 2 integer value. Otherwise, | |||
2020 | /// return -1. | |||
2021 | /// | |||
2022 | /// The BitWidth specifies the necessary bit precision. | |||
2023 | int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements, | |||
2024 | uint32_t BitWidth) const; | |||
2025 | ||||
2026 | bool isConstant() const; | |||
2027 | ||||
2028 | static bool classof(const SDNode *N) { | |||
2029 | return N->getOpcode() == ISD::BUILD_VECTOR; | |||
2030 | } | |||
2031 | }; | |||
2032 | ||||
2033 | /// An SDNode that holds an arbitrary LLVM IR Value. This is | |||
2034 | /// used when the SelectionDAG needs to make a simple reference to something | |||
2035 | /// in the LLVM IR representation. | |||
2036 | /// | |||
2037 | class SrcValueSDNode : public SDNode { | |||
2038 | friend class SelectionDAG; | |||
2039 | ||||
2040 | const Value *V; | |||
2041 | ||||
2042 | /// Create a SrcValue for a general value. | |||
2043 | explicit SrcValueSDNode(const Value *v) | |||
2044 | : SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} | |||
2045 | ||||
2046 | public: | |||
2047 | /// Return the contained Value. | |||
2048 | const Value *getValue() const { return V; } | |||
2049 | ||||
2050 | static bool classof(const SDNode *N) { | |||
2051 | return N->getOpcode() == ISD::SRCVALUE; | |||
2052 | } | |||
2053 | }; | |||
2054 | ||||
2055 | class MDNodeSDNode : public SDNode { | |||
2056 | friend class SelectionDAG; | |||
2057 | ||||
2058 | const MDNode *MD; | |||
2059 | ||||
2060 | explicit MDNodeSDNode(const MDNode *md) | |||
2061 | : SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md) | |||
2062 | {} | |||
2063 | ||||
2064 | public: | |||
2065 | const MDNode *getMD() const { return MD; } | |||
2066 | ||||
2067 | static bool classof(const SDNode *N) { | |||
2068 | return N->getOpcode() == ISD::MDNODE_SDNODE; | |||
2069 | } | |||
2070 | }; | |||
2071 | ||||
2072 | class RegisterSDNode : public SDNode { | |||
2073 | friend class SelectionDAG; | |||
2074 | ||||
2075 | Register Reg; | |||
2076 | ||||
2077 | RegisterSDNode(Register reg, EVT VT) | |||
2078 | : SDNode(ISD::Register, 0, DebugLoc(), getSDVTList(VT)), Reg(reg) {} | |||
2079 | ||||
2080 | public: | |||
2081 | Register getReg() const { return Reg; } | |||
2082 | ||||
2083 | static bool classof(const SDNode *N) { | |||
2084 | return N->getOpcode() == ISD::Register; | |||
2085 | } | |||
2086 | }; | |||
2087 | ||||
2088 | class RegisterMaskSDNode : public SDNode { | |||
2089 | friend class SelectionDAG; | |||
2090 | ||||
2091 | // The memory for RegMask is not owned by the node. | |||
2092 | const uint32_t *RegMask; | |||
2093 | ||||
2094 | RegisterMaskSDNode(const uint32_t *mask) | |||
2095 | : SDNode(ISD::RegisterMask, 0, DebugLoc(), getSDVTList(MVT::Untyped)), | |||
2096 | RegMask(mask) {} | |||
2097 | ||||
2098 | public: | |||
2099 | const uint32_t *getRegMask() const { return RegMask; } | |||
2100 | ||||
2101 | static bool classof(const SDNode *N) { | |||
2102 | return N->getOpcode() == ISD::RegisterMask; | |||
2103 | } | |||
2104 | }; | |||
2105 | ||||
2106 | class BlockAddressSDNode : public SDNode { | |||
2107 | friend class SelectionDAG; | |||
2108 | ||||
2109 | const BlockAddress *BA; | |||
2110 | int64_t Offset; | |||
2111 | unsigned TargetFlags; | |||
2112 | ||||
2113 | BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, | |||
2114 | int64_t o, unsigned Flags) | |||
2115 | : SDNode(NodeTy, 0, DebugLoc(), getSDVTList(VT)), | |||
2116 | BA(ba), Offset(o), TargetFlags(Flags) {} | |||
2117 | ||||
2118 | public: | |||
2119 | const BlockAddress *getBlockAddress() const { return BA; } | |||
2120 | int64_t getOffset() const { return Offset; } | |||
2121 | unsigned getTargetFlags() const { return TargetFlags; } | |||
2122 | ||||
2123 | static bool classof(const SDNode *N) { | |||
2124 | return N->getOpcode() == ISD::BlockAddress || | |||
2125 | N->getOpcode() == ISD::TargetBlockAddress; | |||
2126 | } | |||
2127 | }; | |||
2128 | ||||
2129 | class LabelSDNode : public SDNode { | |||
2130 | friend class SelectionDAG; | |||
2131 | ||||
2132 | MCSymbol *Label; | |||
2133 | ||||
2134 | LabelSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, MCSymbol *L) | |||
2135 | : SDNode(Opcode, Order, dl, getSDVTList(MVT::Other)), Label(L) { | |||
2136 | assert(LabelSDNode::classof(this) && "not a label opcode")((LabelSDNode::classof(this) && "not a label opcode") ? static_cast<void> (0) : __assert_fail ("LabelSDNode::classof(this) && \"not a label opcode\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2136, __PRETTY_FUNCTION__)); | |||
2137 | } | |||
2138 | ||||
2139 | public: | |||
2140 | MCSymbol *getLabel() const { return Label; } | |||
2141 | ||||
2142 | static bool classof(const SDNode *N) { | |||
2143 | return N->getOpcode() == ISD::EH_LABEL || | |||
2144 | N->getOpcode() == ISD::ANNOTATION_LABEL; | |||
2145 | } | |||
2146 | }; | |||
2147 | ||||
2148 | class ExternalSymbolSDNode : public SDNode { | |||
2149 | friend class SelectionDAG; | |||
2150 | ||||
2151 | const char *Symbol; | |||
2152 | unsigned TargetFlags; | |||
2153 | ||||
2154 | ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned TF, EVT VT) | |||
2155 | : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, 0, | |||
2156 | DebugLoc(), getSDVTList(VT)), | |||
2157 | Symbol(Sym), TargetFlags(TF) {} | |||
2158 | ||||
2159 | public: | |||
2160 | const char *getSymbol() const { return Symbol; } | |||
2161 | unsigned getTargetFlags() const { return TargetFlags; } | |||
2162 | ||||
2163 | static bool classof(const SDNode *N) { | |||
2164 | return N->getOpcode() == ISD::ExternalSymbol || | |||
2165 | N->getOpcode() == ISD::TargetExternalSymbol; | |||
2166 | } | |||
2167 | }; | |||
2168 | ||||
2169 | class MCSymbolSDNode : public SDNode { | |||
2170 | friend class SelectionDAG; | |||
2171 | ||||
2172 | MCSymbol *Symbol; | |||
2173 | ||||
2174 | MCSymbolSDNode(MCSymbol *Symbol, EVT VT) | |||
2175 | : SDNode(ISD::MCSymbol, 0, DebugLoc(), getSDVTList(VT)), Symbol(Symbol) {} | |||
2176 | ||||
2177 | public: | |||
2178 | MCSymbol *getMCSymbol() const { return Symbol; } | |||
2179 | ||||
2180 | static bool classof(const SDNode *N) { | |||
2181 | return N->getOpcode() == ISD::MCSymbol; | |||
2182 | } | |||
2183 | }; | |||
2184 | ||||
2185 | class CondCodeSDNode : public SDNode { | |||
2186 | friend class SelectionDAG; | |||
2187 | ||||
2188 | ISD::CondCode Condition; | |||
2189 | ||||
2190 | explicit CondCodeSDNode(ISD::CondCode Cond) | |||
2191 | : SDNode(ISD::CONDCODE, 0, DebugLoc(), getSDVTList(MVT::Other)), | |||
2192 | Condition(Cond) {} | |||
2193 | ||||
2194 | public: | |||
2195 | ISD::CondCode get() const { return Condition; } | |||
2196 | ||||
2197 | static bool classof(const SDNode *N) { | |||
2198 | return N->getOpcode() == ISD::CONDCODE; | |||
2199 | } | |||
2200 | }; | |||
2201 | ||||
2202 | /// This class is used to represent EVT's, which are used | |||
2203 | /// to parameterize some operations. | |||
2204 | class VTSDNode : public SDNode { | |||
2205 | friend class SelectionDAG; | |||
2206 | ||||
2207 | EVT ValueType; | |||
2208 | ||||
2209 | explicit VTSDNode(EVT VT) | |||
2210 | : SDNode(ISD::VALUETYPE, 0, DebugLoc(), getSDVTList(MVT::Other)), | |||
2211 | ValueType(VT) {} | |||
2212 | ||||
2213 | public: | |||
2214 | EVT getVT() const { return ValueType; } | |||
2215 | ||||
2216 | static bool classof(const SDNode *N) { | |||
2217 | return N->getOpcode() == ISD::VALUETYPE; | |||
2218 | } | |||
2219 | }; | |||
2220 | ||||
2221 | /// Base class for LoadSDNode and StoreSDNode | |||
2222 | class LSBaseSDNode : public MemSDNode { | |||
2223 | public: | |||
2224 | LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, const DebugLoc &dl, | |||
2225 | SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT, | |||
2226 | MachineMemOperand *MMO) | |||
2227 | : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { | |||
2228 | LSBaseSDNodeBits.AddressingMode = AM; | |||
2229 | assert(getAddressingMode() == AM && "Value truncated")((getAddressingMode() == AM && "Value truncated") ? static_cast <void> (0) : __assert_fail ("getAddressingMode() == AM && \"Value truncated\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2229, __PRETTY_FUNCTION__)); | |||
2230 | } | |||
2231 | ||||
2232 | const SDValue &getOffset() const { | |||
2233 | return getOperand(getOpcode() == ISD::LOAD ? 2 : 3); | |||
2234 | } | |||
2235 | ||||
2236 | /// Return the addressing mode for this load or store: | |||
2237 | /// unindexed, pre-inc, pre-dec, post-inc, or post-dec. | |||
2238 | ISD::MemIndexedMode getAddressingMode() const { | |||
2239 | return static_cast<ISD::MemIndexedMode>(LSBaseSDNodeBits.AddressingMode); | |||
2240 | } | |||
2241 | ||||
2242 | /// Return true if this is a pre/post inc/dec load/store. | |||
2243 | bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; } | |||
2244 | ||||
2245 | /// Return true if this is NOT a pre/post inc/dec load/store. | |||
2246 | bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } | |||
2247 | ||||
2248 | static bool classof(const SDNode *N) { | |||
2249 | return N->getOpcode() == ISD::LOAD || | |||
2250 | N->getOpcode() == ISD::STORE; | |||
2251 | } | |||
2252 | }; | |||
2253 | ||||
2254 | /// This class is used to represent ISD::LOAD nodes. | |||
2255 | class LoadSDNode : public LSBaseSDNode { | |||
2256 | friend class SelectionDAG; | |||
2257 | ||||
2258 | LoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, | |||
2259 | ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, | |||
2260 | MachineMemOperand *MMO) | |||
2261 | : LSBaseSDNode(ISD::LOAD, Order, dl, VTs, AM, MemVT, MMO) { | |||
2262 | LoadSDNodeBits.ExtTy = ETy; | |||
2263 | assert(readMem() && "Load MachineMemOperand is not a load!")((readMem() && "Load MachineMemOperand is not a load!" ) ? static_cast<void> (0) : __assert_fail ("readMem() && \"Load MachineMemOperand is not a load!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2263, __PRETTY_FUNCTION__)); | |||
2264 | assert(!writeMem() && "Load MachineMemOperand is a store!")((!writeMem() && "Load MachineMemOperand is a store!" ) ? static_cast<void> (0) : __assert_fail ("!writeMem() && \"Load MachineMemOperand is a store!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2264, __PRETTY_FUNCTION__)); | |||
2265 | } | |||
2266 | ||||
2267 | public: | |||
2268 | /// Return whether this is a plain node, | |||
2269 | /// or one of the varieties of value-extending loads. | |||
2270 | ISD::LoadExtType getExtensionType() const { | |||
2271 | return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy); | |||
2272 | } | |||
2273 | ||||
2274 | const SDValue &getBasePtr() const { return getOperand(1); } | |||
2275 | const SDValue &getOffset() const { return getOperand(2); } | |||
2276 | ||||
2277 | static bool classof(const SDNode *N) { | |||
2278 | return N->getOpcode() == ISD::LOAD; | |||
2279 | } | |||
2280 | }; | |||
2281 | ||||
2282 | /// This class is used to represent ISD::STORE nodes. | |||
2283 | class StoreSDNode : public LSBaseSDNode { | |||
2284 | friend class SelectionDAG; | |||
2285 | ||||
2286 | StoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, | |||
2287 | ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, | |||
2288 | MachineMemOperand *MMO) | |||
2289 | : LSBaseSDNode(ISD::STORE, Order, dl, VTs, AM, MemVT, MMO) { | |||
2290 | StoreSDNodeBits.IsTruncating = isTrunc; | |||
2291 | assert(!readMem() && "Store MachineMemOperand is a load!")((!readMem() && "Store MachineMemOperand is a load!") ? static_cast<void> (0) : __assert_fail ("!readMem() && \"Store MachineMemOperand is a load!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2291, __PRETTY_FUNCTION__)); | |||
2292 | assert(writeMem() && "Store MachineMemOperand is not a store!")((writeMem() && "Store MachineMemOperand is not a store!" ) ? static_cast<void> (0) : __assert_fail ("writeMem() && \"Store MachineMemOperand is not a store!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2292, __PRETTY_FUNCTION__)); | |||
2293 | } | |||
2294 | ||||
2295 | public: | |||
2296 | /// Return true if the op does a truncation before store. | |||
2297 | /// For integers this is the same as doing a TRUNCATE and storing the result. | |||
2298 | /// For floats, it is the same as doing an FP_ROUND and storing the result. | |||
2299 | bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } | |||
2300 | void setTruncatingStore(bool Truncating) { | |||
2301 | StoreSDNodeBits.IsTruncating = Truncating; | |||
2302 | } | |||
2303 | ||||
2304 | const SDValue &getValue() const { return getOperand(1); } | |||
2305 | const SDValue &getBasePtr() const { return getOperand(2); } | |||
2306 | const SDValue &getOffset() const { return getOperand(3); } | |||
2307 | ||||
2308 | static bool classof(const SDNode *N) { | |||
2309 | return N->getOpcode() == ISD::STORE; | |||
2310 | } | |||
2311 | }; | |||
2312 | ||||
2313 | /// This base class is used to represent MLOAD and MSTORE nodes | |||
2314 | class MaskedLoadStoreSDNode : public MemSDNode { | |||
2315 | public: | |||
2316 | friend class SelectionDAG; | |||
2317 | ||||
2318 | MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, | |||
2319 | const DebugLoc &dl, SDVTList VTs, | |||
2320 | ISD::MemIndexedMode AM, EVT MemVT, | |||
2321 | MachineMemOperand *MMO) | |||
2322 | : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { | |||
2323 | LSBaseSDNodeBits.AddressingMode = AM; | |||
2324 | assert(getAddressingMode() == AM && "Value truncated")((getAddressingMode() == AM && "Value truncated") ? static_cast <void> (0) : __assert_fail ("getAddressingMode() == AM && \"Value truncated\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2324, __PRETTY_FUNCTION__)); | |||
2325 | } | |||
2326 | ||||
2327 | // MaskedLoadSDNode (Chain, ptr, offset, mask, passthru) | |||
2328 | // MaskedStoreSDNode (Chain, data, ptr, offset, mask) | |||
2329 | // Mask is a vector of i1 elements | |||
2330 | const SDValue &getOffset() const { | |||
2331 | return getOperand(getOpcode() == ISD::MLOAD ? 2 : 3); | |||
2332 | } | |||
2333 | const SDValue &getMask() const { | |||
2334 | return getOperand(getOpcode() == ISD::MLOAD ? 3 : 4); | |||
2335 | } | |||
2336 | ||||
2337 | /// Return the addressing mode for this load or store: | |||
2338 | /// unindexed, pre-inc, pre-dec, post-inc, or post-dec. | |||
2339 | ISD::MemIndexedMode getAddressingMode() const { | |||
2340 | return static_cast<ISD::MemIndexedMode>(LSBaseSDNodeBits.AddressingMode); | |||
2341 | } | |||
2342 | ||||
2343 | /// Return true if this is a pre/post inc/dec load/store. | |||
2344 | bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; } | |||
2345 | ||||
2346 | /// Return true if this is NOT a pre/post inc/dec load/store. | |||
2347 | bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } | |||
2348 | ||||
2349 | static bool classof(const SDNode *N) { | |||
2350 | return N->getOpcode() == ISD::MLOAD || | |||
2351 | N->getOpcode() == ISD::MSTORE; | |||
2352 | } | |||
2353 | }; | |||
2354 | ||||
2355 | /// This class is used to represent an MLOAD node | |||
2356 | class MaskedLoadSDNode : public MaskedLoadStoreSDNode { | |||
2357 | public: | |||
2358 | friend class SelectionDAG; | |||
2359 | ||||
2360 | MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, | |||
2361 | ISD::MemIndexedMode AM, ISD::LoadExtType ETy, | |||
2362 | bool IsExpanding, EVT MemVT, MachineMemOperand *MMO) | |||
2363 | : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, VTs, AM, MemVT, MMO) { | |||
2364 | LoadSDNodeBits.ExtTy = ETy; | |||
2365 | LoadSDNodeBits.IsExpanding = IsExpanding; | |||
2366 | } | |||
2367 | ||||
2368 | ISD::LoadExtType getExtensionType() const { | |||
2369 | return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy); | |||
2370 | } | |||
2371 | ||||
2372 | const SDValue &getBasePtr() const { return getOperand(1); } | |||
2373 | const SDValue &getOffset() const { return getOperand(2); } | |||
2374 | const SDValue &getMask() const { return getOperand(3); } | |||
2375 | const SDValue &getPassThru() const { return getOperand(4); } | |||
2376 | ||||
2377 | static bool classof(const SDNode *N) { | |||
2378 | return N->getOpcode() == ISD::MLOAD; | |||
2379 | } | |||
2380 | ||||
2381 | bool isExpandingLoad() const { return LoadSDNodeBits.IsExpanding; } | |||
2382 | }; | |||
2383 | ||||
2384 | /// This class is used to represent an MSTORE node | |||
2385 | class MaskedStoreSDNode : public MaskedLoadStoreSDNode { | |||
2386 | public: | |||
2387 | friend class SelectionDAG; | |||
2388 | ||||
2389 | MaskedStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, | |||
2390 | ISD::MemIndexedMode AM, bool isTrunc, bool isCompressing, | |||
2391 | EVT MemVT, MachineMemOperand *MMO) | |||
2392 | : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, VTs, AM, MemVT, MMO) { | |||
2393 | StoreSDNodeBits.IsTruncating = isTrunc; | |||
2394 | StoreSDNodeBits.IsCompressing = isCompressing; | |||
2395 | } | |||
2396 | ||||
2397 | /// Return true if the op does a truncation before store. | |||
2398 | /// For integers this is the same as doing a TRUNCATE and storing the result. | |||
2399 | /// For floats, it is the same as doing an FP_ROUND and storing the result. | |||
2400 | bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } | |||
2401 | ||||
2402 | /// Returns true if the op does a compression to the vector before storing. | |||
2403 | /// The node contiguously stores the active elements (integers or floats) | |||
2404 | /// in src (those with their respective bit set in writemask k) to unaligned | |||
2405 | /// memory at base_addr. | |||
2406 | bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; } | |||
2407 | ||||
2408 | const SDValue &getValue() const { return getOperand(1); } | |||
2409 | const SDValue &getBasePtr() const { return getOperand(2); } | |||
2410 | const SDValue &getOffset() const { return getOperand(3); } | |||
2411 | const SDValue &getMask() const { return getOperand(4); } | |||
2412 | ||||
2413 | static bool classof(const SDNode *N) { | |||
2414 | return N->getOpcode() == ISD::MSTORE; | |||
2415 | } | |||
2416 | }; | |||
2417 | ||||
2418 | /// This is a base class used to represent | |||
2419 | /// MGATHER and MSCATTER nodes | |||
2420 | /// | |||
2421 | class MaskedGatherScatterSDNode : public MemSDNode { | |||
2422 | public: | |||
2423 | friend class SelectionDAG; | |||
2424 | ||||
2425 | MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, | |||
2426 | const DebugLoc &dl, SDVTList VTs, EVT MemVT, | |||
2427 | MachineMemOperand *MMO, ISD::MemIndexType IndexType) | |||
2428 | : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { | |||
2429 | LSBaseSDNodeBits.AddressingMode = IndexType; | |||
2430 | assert(getIndexType() == IndexType && "Value truncated")((getIndexType() == IndexType && "Value truncated") ? static_cast<void> (0) : __assert_fail ("getIndexType() == IndexType && \"Value truncated\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2430, __PRETTY_FUNCTION__)); | |||
2431 | } | |||
2432 | ||||
2433 | /// How is Index applied to BasePtr when computing addresses. | |||
2434 | ISD::MemIndexType getIndexType() const { | |||
2435 | return static_cast<ISD::MemIndexType>(LSBaseSDNodeBits.AddressingMode); | |||
2436 | } | |||
2437 | void setIndexType(ISD::MemIndexType IndexType) { | |||
2438 | LSBaseSDNodeBits.AddressingMode = IndexType; | |||
2439 | } | |||
2440 | bool isIndexScaled() const { | |||
2441 | return (getIndexType() == ISD::SIGNED_SCALED) || | |||
2442 | (getIndexType() == ISD::UNSIGNED_SCALED); | |||
2443 | } | |||
2444 | bool isIndexSigned() const { | |||
2445 | return (getIndexType() == ISD::SIGNED_SCALED) || | |||
2446 | (getIndexType() == ISD::SIGNED_UNSCALED); | |||
2447 | } | |||
2448 | ||||
2449 | // In the both nodes address is Op1, mask is Op2: | |||
2450 | // MaskedGatherSDNode (Chain, passthru, mask, base, index, scale) | |||
2451 | // MaskedScatterSDNode (Chain, value, mask, base, index, scale) | |||
2452 | // Mask is a vector of i1 elements | |||
2453 | const SDValue &getBasePtr() const { return getOperand(3); } | |||
2454 | const SDValue &getIndex() const { return getOperand(4); } | |||
2455 | const SDValue &getMask() const { return getOperand(2); } | |||
2456 | const SDValue &getScale() const { return getOperand(5); } | |||
2457 | ||||
2458 | static bool classof(const SDNode *N) { | |||
2459 | return N->getOpcode() == ISD::MGATHER || | |||
2460 | N->getOpcode() == ISD::MSCATTER; | |||
2461 | } | |||
2462 | }; | |||
2463 | ||||
2464 | /// This class is used to represent an MGATHER node | |||
2465 | /// | |||
2466 | class MaskedGatherSDNode : public MaskedGatherScatterSDNode { | |||
2467 | public: | |||
2468 | friend class SelectionDAG; | |||
2469 | ||||
2470 | MaskedGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, | |||
2471 | EVT MemVT, MachineMemOperand *MMO, | |||
2472 | ISD::MemIndexType IndexType, ISD::LoadExtType ETy) | |||
2473 | : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO, | |||
2474 | IndexType) { | |||
2475 | LoadSDNodeBits.ExtTy = ETy; | |||
2476 | } | |||
2477 | ||||
2478 | const SDValue &getPassThru() const { return getOperand(1); } | |||
2479 | ||||
2480 | ISD::LoadExtType getExtensionType() const { | |||
2481 | return ISD::LoadExtType(LoadSDNodeBits.ExtTy); | |||
2482 | } | |||
2483 | ||||
2484 | static bool classof(const SDNode *N) { | |||
2485 | return N->getOpcode() == ISD::MGATHER; | |||
2486 | } | |||
2487 | }; | |||
2488 | ||||
2489 | /// This class is used to represent an MSCATTER node | |||
2490 | /// | |||
2491 | class MaskedScatterSDNode : public MaskedGatherScatterSDNode { | |||
2492 | public: | |||
2493 | friend class SelectionDAG; | |||
2494 | ||||
2495 | MaskedScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, | |||
2496 | EVT MemVT, MachineMemOperand *MMO, | |||
2497 | ISD::MemIndexType IndexType, bool IsTrunc) | |||
2498 | : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO, | |||
2499 | IndexType) { | |||
2500 | StoreSDNodeBits.IsTruncating = IsTrunc; | |||
2501 | } | |||
2502 | ||||
2503 | /// Return true if the op does a truncation before store. | |||
2504 | /// For integers this is the same as doing a TRUNCATE and storing the result. | |||
2505 | /// For floats, it is the same as doing an FP_ROUND and storing the result. | |||
2506 | bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } | |||
2507 | ||||
2508 | const SDValue &getValue() const { return getOperand(1); } | |||
2509 | ||||
2510 | static bool classof(const SDNode *N) { | |||
2511 | return N->getOpcode() == ISD::MSCATTER; | |||
2512 | } | |||
2513 | }; | |||
2514 | ||||
2515 | /// An SDNode that represents everything that will be needed | |||
2516 | /// to construct a MachineInstr. These nodes are created during the | |||
2517 | /// instruction selection proper phase. | |||
2518 | /// | |||
2519 | /// Note that the only supported way to set the `memoperands` is by calling the | |||
2520 | /// `SelectionDAG::setNodeMemRefs` function as the memory management happens | |||
2521 | /// inside the DAG rather than in the node. | |||
2522 | class MachineSDNode : public SDNode { | |||
2523 | private: | |||
2524 | friend class SelectionDAG; | |||
2525 | ||||
2526 | MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs) | |||
2527 | : SDNode(Opc, Order, DL, VTs) {} | |||
2528 | ||||
2529 | // We use a pointer union between a single `MachineMemOperand` pointer and | |||
2530 | // a pointer to an array of `MachineMemOperand` pointers. This is null when | |||
2531 | // the number of these is zero, the single pointer variant used when the | |||
2532 | // number is one, and the array is used for larger numbers. | |||
2533 | // | |||
2534 | // The array is allocated via the `SelectionDAG`'s allocator and so will | |||
2535 | // always live until the DAG is cleaned up and doesn't require ownership here. | |||
2536 | // | |||
2537 | // We can't use something simpler like `TinyPtrVector` here because `SDNode` | |||
2538 | // subclasses aren't managed in a conforming C++ manner. See the comments on | |||
2539 | // `SelectionDAG::MorphNodeTo` which details what all goes on, but the | |||
2540 | // constraint here is that these don't manage memory with their constructor or | |||
2541 | // destructor and can be initialized to a good state even if they start off | |||
2542 | // uninitialized. | |||
2543 | PointerUnion<MachineMemOperand *, MachineMemOperand **> MemRefs = {}; | |||
2544 | ||||
2545 | // Note that this could be folded into the above `MemRefs` member if doing so | |||
2546 | // is advantageous at some point. We don't need to store this in most cases. | |||
2547 | // However, at the moment this doesn't appear to make the allocation any | |||
2548 | // smaller and makes the code somewhat simpler to read. | |||
2549 | int NumMemRefs = 0; | |||
2550 | ||||
2551 | public: | |||
2552 | using mmo_iterator = ArrayRef<MachineMemOperand *>::const_iterator; | |||
2553 | ||||
2554 | ArrayRef<MachineMemOperand *> memoperands() const { | |||
2555 | // Special case the common cases. | |||
2556 | if (NumMemRefs == 0) | |||
2557 | return {}; | |||
2558 | if (NumMemRefs == 1) | |||
2559 | return makeArrayRef(MemRefs.getAddrOfPtr1(), 1); | |||
2560 | ||||
2561 | // Otherwise we have an actual array. | |||
2562 | return makeArrayRef(MemRefs.get<MachineMemOperand **>(), NumMemRefs); | |||
2563 | } | |||
2564 | mmo_iterator memoperands_begin() const { return memoperands().begin(); } | |||
2565 | mmo_iterator memoperands_end() const { return memoperands().end(); } | |||
2566 | bool memoperands_empty() const { return memoperands().empty(); } | |||
2567 | ||||
2568 | /// Clear out the memory reference descriptor list. | |||
2569 | void clearMemRefs() { | |||
2570 | MemRefs = nullptr; | |||
2571 | NumMemRefs = 0; | |||
2572 | } | |||
2573 | ||||
2574 | static bool classof(const SDNode *N) { | |||
2575 | return N->isMachineOpcode(); | |||
2576 | } | |||
2577 | }; | |||
2578 | ||||
2579 | /// An SDNode that records if a register contains a value that is guaranteed to | |||
2580 | /// be aligned accordingly. | |||
2581 | class AssertAlignSDNode : public SDNode { | |||
2582 | Align Alignment; | |||
2583 | ||||
2584 | public: | |||
2585 | AssertAlignSDNode(unsigned Order, const DebugLoc &DL, EVT VT, Align A) | |||
2586 | : SDNode(ISD::AssertAlign, Order, DL, getSDVTList(VT)), Alignment(A) {} | |||
2587 | ||||
2588 | Align getAlign() const { return Alignment; } | |||
2589 | ||||
2590 | static bool classof(const SDNode *N) { | |||
2591 | return N->getOpcode() == ISD::AssertAlign; | |||
2592 | } | |||
2593 | }; | |||
2594 | ||||
2595 | class SDNodeIterator { | |||
2596 | const SDNode *Node; | |||
2597 | unsigned Operand; | |||
2598 | ||||
2599 | SDNodeIterator(const SDNode *N, unsigned Op) : Node(N), Operand(Op) {} | |||
2600 | ||||
2601 | public: | |||
2602 | using iterator_category = std::forward_iterator_tag; | |||
2603 | using value_type = SDNode; | |||
2604 | using difference_type = std::ptrdiff_t; | |||
2605 | using pointer = value_type *; | |||
2606 | using reference = value_type &; | |||
2607 | ||||
2608 | bool operator==(const SDNodeIterator& x) const { | |||
2609 | return Operand == x.Operand; | |||
2610 | } | |||
2611 | bool operator!=(const SDNodeIterator& x) const { return !operator==(x); } | |||
2612 | ||||
2613 | pointer operator*() const { | |||
2614 | return Node->getOperand(Operand).getNode(); | |||
2615 | } | |||
2616 | pointer operator->() const { return operator*(); } | |||
2617 | ||||
2618 | SDNodeIterator& operator++() { // Preincrement | |||
2619 | ++Operand; | |||
2620 | return *this; | |||
2621 | } | |||
2622 | SDNodeIterator operator++(int) { // Postincrement | |||
2623 | SDNodeIterator tmp = *this; ++*this; return tmp; | |||
2624 | } | |||
2625 | size_t operator-(SDNodeIterator Other) const { | |||
2626 | assert(Node == Other.Node &&((Node == Other.Node && "Cannot compare iterators of two different nodes!" ) ? static_cast<void> (0) : __assert_fail ("Node == Other.Node && \"Cannot compare iterators of two different nodes!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2627, __PRETTY_FUNCTION__)) | |||
2627 | "Cannot compare iterators of two different nodes!")((Node == Other.Node && "Cannot compare iterators of two different nodes!" ) ? static_cast<void> (0) : __assert_fail ("Node == Other.Node && \"Cannot compare iterators of two different nodes!\"" , "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/llvm/include/llvm/CodeGen/SelectionDAGNodes.h" , 2627, __PRETTY_FUNCTION__)); | |||
2628 | return Operand - Other.Operand; | |||
2629 | } | |||
2630 | ||||
2631 | static SDNodeIterator begin(const SDNode *N) { return SDNodeIterator(N, 0); } | |||
2632 | static SDNodeIterator end (const SDNode *N) { | |||
2633 | return SDNodeIterator(N, N->getNumOperands()); | |||
2634 | } | |||
2635 | ||||
2636 | unsigned getOperand() const { return Operand; } | |||
2637 | const SDNode *getNode() const { return Node; } | |||
2638 | }; | |||
2639 | ||||
2640 | template <> struct GraphTraits<SDNode*> { | |||
2641 | using NodeRef = SDNode *; | |||
2642 | using ChildIteratorType = SDNodeIterator; | |||
2643 | ||||
2644 | static NodeRef getEntryNode(SDNode *N) { return N; } | |||
2645 | ||||
2646 | static ChildIteratorType child_begin(NodeRef N) { | |||
2647 | return SDNodeIterator::begin(N); | |||
2648 | } | |||
2649 | ||||
2650 | static ChildIteratorType child_end(NodeRef N) { | |||
2651 | return SDNodeIterator::end(N); | |||
2652 | } | |||
2653 | }; | |||
2654 | ||||
2655 | /// A representation of the largest SDNode, for use in sizeof(). | |||
2656 | /// | |||
2657 | /// This needs to be a union because the largest node differs on 32 bit systems | |||
2658 | /// with 4 and 8 byte pointer alignment, respectively. | |||
2659 | using LargestSDNode = AlignedCharArrayUnion<AtomicSDNode, TargetIndexSDNode, | |||
2660 | BlockAddressSDNode, | |||
2661 | GlobalAddressSDNode, | |||
2662 | PseudoProbeSDNode>; | |||
2663 | ||||
2664 | /// The SDNode class with the greatest alignment requirement. | |||
2665 | using MostAlignedSDNode = GlobalAddressSDNode; | |||
2666 | ||||
2667 | namespace ISD { | |||
2668 | ||||
2669 | /// Returns true if the specified node is a non-extending and unindexed load. | |||
2670 | inline bool isNormalLoad(const SDNode *N) { | |||
2671 | const LoadSDNode *Ld = dyn_cast<LoadSDNode>(N); | |||
2672 | return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD && | |||
2673 | Ld->getAddressingMode() == ISD::UNINDEXED; | |||
2674 | } | |||
2675 | ||||
2676 | /// Returns true if the specified node is a non-extending load. | |||
2677 | inline bool isNON_EXTLoad(const SDNode *N) { | |||
2678 | return isa<LoadSDNode>(N) && | |||
2679 | cast<LoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD; | |||
2680 | } | |||
2681 | ||||
2682 | /// Returns true if the specified node is a EXTLOAD. | |||
2683 | inline bool isEXTLoad(const SDNode *N) { | |||
2684 | return isa<LoadSDNode>(N) && | |||
2685 | cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD; | |||
2686 | } | |||
2687 | ||||
2688 | /// Returns true if the specified node is a SEXTLOAD. | |||
2689 | inline bool isSEXTLoad(const SDNode *N) { | |||
2690 | return isa<LoadSDNode>(N) && | |||
2691 | cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD; | |||
2692 | } | |||
2693 | ||||
2694 | /// Returns true if the specified node is a ZEXTLOAD. | |||
2695 | inline bool isZEXTLoad(const SDNode *N) { | |||
2696 | return isa<LoadSDNode>(N) && | |||
2697 | cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD; | |||
2698 | } | |||
2699 | ||||
2700 | /// Returns true if the specified node is an unindexed load. | |||
2701 | inline bool isUNINDEXEDLoad(const SDNode *N) { | |||
2702 | return isa<LoadSDNode>(N) && | |||
2703 | cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; | |||
2704 | } | |||
2705 | ||||
2706 | /// Returns true if the specified node is a non-truncating | |||
2707 | /// and unindexed store. | |||
2708 | inline bool isNormalStore(const SDNode *N) { | |||
2709 | const StoreSDNode *St = dyn_cast<StoreSDNode>(N); | |||
2710 | return St && !St->isTruncatingStore() && | |||
2711 | St->getAddressingMode() == ISD::UNINDEXED; | |||
2712 | } | |||
2713 | ||||
2714 | /// Returns true if the specified node is a non-truncating store. | |||
2715 | inline bool isNON_TRUNCStore(const SDNode *N) { | |||
2716 | return isa<StoreSDNode>(N) && !cast<StoreSDNode>(N)->isTruncatingStore(); | |||
2717 | } | |||
2718 | ||||
2719 | /// Returns true if the specified node is a truncating store. | |||
2720 | inline bool isTRUNCStore(const SDNode *N) { | |||
2721 | return isa<StoreSDNode>(N) && cast<StoreSDNode>(N)->isTruncatingStore(); | |||
2722 | } | |||
2723 | ||||
2724 | /// Returns true if the specified node is an unindexed store. | |||
2725 | inline bool isUNINDEXEDStore(const SDNode *N) { | |||
2726 | return isa<StoreSDNode>(N) && | |||
2727 | cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; | |||
2728 | } | |||
2729 | ||||
2730 | /// Attempt to match a unary predicate against a scalar/splat constant or | |||
2731 | /// every element of a constant BUILD_VECTOR. | |||
2732 | /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. | |||
2733 | bool matchUnaryPredicate(SDValue Op, | |||
2734 | std::function<bool(ConstantSDNode *)> Match, | |||
2735 | bool AllowUndefs = false); | |||
2736 | ||||
2737 | /// Attempt to match a binary predicate against a pair of scalar/splat | |||
2738 | /// constants or every element of a pair of constant BUILD_VECTORs. | |||
2739 | /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. | |||
2740 | /// If AllowTypeMismatch is true then RetType + ArgTypes don't need to match. | |||
2741 | bool matchBinaryPredicate( | |||
2742 | SDValue LHS, SDValue RHS, | |||
2743 | std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match, | |||
2744 | bool AllowUndefs = false, bool AllowTypeMismatch = false); | |||
2745 | ||||
2746 | /// Returns true if the specified value is the overflow result from one | |||
2747 | /// of the overflow intrinsic nodes. | |||
2748 | inline bool isOverflowIntrOpRes(SDValue Op) { | |||
2749 | unsigned Opc = Op.getOpcode(); | |||
2750 | return (Op.getResNo() == 1 && | |||
2751 | (Opc == ISD::SADDO || Opc == ISD::UADDO || Opc == ISD::SSUBO || | |||
2752 | Opc == ISD::USUBO || Opc == ISD::SMULO || Opc == ISD::UMULO)); | |||
2753 | } | |||
2754 | ||||
2755 | } // end namespace ISD | |||
2756 | ||||
2757 | } // end namespace llvm | |||
2758 | ||||
2759 | #endif // LLVM_CODEGEN_SELECTIONDAGNODES_H |