LLVM 24.0.0git
AArch64ISelDAGToDAG.cpp
Go to the documentation of this file.
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 "AArch64.h"
14#include "AArch64ExpandImm.h"
18#include "llvm/ADT/APSInt.h"
22#include "llvm/IR/Function.h" // To access function attributes.
23#include "llvm/IR/GlobalValue.h"
24#include "llvm/IR/Intrinsics.h"
25#include "llvm/IR/IntrinsicsAArch64.h"
27#include "llvm/Support/Debug.h"
32
33using namespace llvm;
34using namespace llvm::SDPatternMatch;
35
36#define DEBUG_TYPE "aarch64-isel"
37#define PASS_NAME "AArch64 Instruction Selection"
38
39// https://github.com/llvm/llvm-project/issues/114425
40#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
41#pragma inline_depth(0)
42#endif
43
44//===--------------------------------------------------------------------===//
45/// AArch64DAGToDAGISel - AArch64 specific code to select AArch64 machine
46/// instructions for SelectionDAG operations.
47///
48namespace {
49
50class AArch64DAGToDAGISel : public SelectionDAGISel {
51
52 /// Subtarget - Keep a pointer to the AArch64Subtarget around so that we can
53 /// make the right decision when generating code for different targets.
54 const AArch64Subtarget *Subtarget;
55
56public:
57 AArch64DAGToDAGISel() = delete;
58
59 explicit AArch64DAGToDAGISel(AArch64TargetMachine &tm,
60 CodeGenOptLevel OptLevel)
61 : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr) {}
62
63 bool runOnMachineFunction(MachineFunction &MF) override {
64 Subtarget = &MF.getSubtarget<AArch64Subtarget>();
66 }
67
68 void Select(SDNode *Node) override;
69 void PreprocessISelDAG() override;
70
71 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
72 /// inline asm expressions.
73 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
74 InlineAsm::ConstraintCode ConstraintID,
75 std::vector<SDValue> &OutOps) override;
76
77 template <signed Low, signed High, signed Scale>
78 bool SelectRDVLImm(SDValue N, SDValue &Imm);
79
80 template <signed Low, signed High>
81 bool SelectRDSVLShiftImm(SDValue N, SDValue &Imm);
82
83 bool SelectArithExtendedRegister(SDValue N, SDValue &Reg, SDValue &Shift);
84 bool SelectArithUXTXRegister(SDValue N, SDValue &Reg, SDValue &Shift);
85 bool SelectArithImmed(SDValue N, SDValue &Val, SDValue &Shift);
86 bool SelectNegArithImmed(SDValue N, SDValue &Val, SDValue &Shift);
87 bool SelectArithShiftedRegister(SDValue N, SDValue &Reg, SDValue &Shift) {
88 return SelectShiftedRegister(N, false, Reg, Shift);
89 }
90 bool SelectLogicalShiftedRegister(SDValue N, SDValue &Reg, SDValue &Shift) {
91 return SelectShiftedRegister(N, true, Reg, Shift);
92 }
93 template <unsigned ShiftWidth>
94 bool SelectShiftMask(SDValue N, SDValue &ShAmt);
95
96 bool SelectAddrModeIndexed7S8(SDValue N, SDValue &Base, SDValue &OffImm) {
97 return SelectAddrModeIndexed7S(N, 1, Base, OffImm);
98 }
99 bool SelectAddrModeIndexed7S16(SDValue N, SDValue &Base, SDValue &OffImm) {
100 return SelectAddrModeIndexed7S(N, 2, Base, OffImm);
101 }
102 bool SelectAddrModeIndexed7S32(SDValue N, SDValue &Base, SDValue &OffImm) {
103 return SelectAddrModeIndexed7S(N, 4, Base, OffImm);
104 }
105 bool SelectAddrModeIndexed7S64(SDValue N, SDValue &Base, SDValue &OffImm) {
106 return SelectAddrModeIndexed7S(N, 8, Base, OffImm);
107 }
108 bool SelectAddrModeIndexed7S128(SDValue N, SDValue &Base, SDValue &OffImm) {
109 return SelectAddrModeIndexed7S(N, 16, Base, OffImm);
110 }
111 bool SelectAddrModeIndexedS9S128(SDValue N, SDValue &Base, SDValue &OffImm) {
112 return SelectAddrModeIndexedBitWidth(N, true, 9, 16, Base, OffImm);
113 }
114 bool SelectAddrModeIndexedU6S128(SDValue N, SDValue &Base, SDValue &OffImm) {
115 return SelectAddrModeIndexedBitWidth(N, false, 6, 16, Base, OffImm);
116 }
117 bool SelectAddrModeIndexed8(SDValue N, SDValue &Base, SDValue &OffImm) {
118 return SelectAddrModeIndexed(N, 1, Base, OffImm);
119 }
120 bool SelectAddrModeIndexed16(SDValue N, SDValue &Base, SDValue &OffImm) {
121 return SelectAddrModeIndexed(N, 2, Base, OffImm);
122 }
123 bool SelectAddrModeIndexed32(SDValue N, SDValue &Base, SDValue &OffImm) {
124 return SelectAddrModeIndexed(N, 4, Base, OffImm);
125 }
126 bool SelectAddrModeIndexed64(SDValue N, SDValue &Base, SDValue &OffImm) {
127 return SelectAddrModeIndexed(N, 8, Base, OffImm);
128 }
129 bool SelectAddrModeIndexed128(SDValue N, SDValue &Base, SDValue &OffImm) {
130 return SelectAddrModeIndexed(N, 16, Base, OffImm);
131 }
132 bool SelectAddrModeUnscaled8(SDValue N, SDValue &Base, SDValue &OffImm) {
133 return SelectAddrModeUnscaled(N, 1, Base, OffImm);
134 }
135 bool SelectAddrModeUnscaled16(SDValue N, SDValue &Base, SDValue &OffImm) {
136 return SelectAddrModeUnscaled(N, 2, Base, OffImm);
137 }
138 bool SelectAddrModeUnscaled32(SDValue N, SDValue &Base, SDValue &OffImm) {
139 return SelectAddrModeUnscaled(N, 4, Base, OffImm);
140 }
141 bool SelectAddrModeUnscaled64(SDValue N, SDValue &Base, SDValue &OffImm) {
142 return SelectAddrModeUnscaled(N, 8, Base, OffImm);
143 }
144 bool SelectAddrModeUnscaled128(SDValue N, SDValue &Base, SDValue &OffImm) {
145 return SelectAddrModeUnscaled(N, 16, Base, OffImm);
146 }
147 template <unsigned Size, unsigned Max>
148 bool SelectAddrModeIndexedUImm(SDValue N, SDValue &Base, SDValue &OffImm) {
149 // Test if there is an appropriate addressing mode and check if the
150 // immediate fits.
151 bool Found = SelectAddrModeIndexed(N, Size, Base, OffImm);
152 if (Found) {
153 if (auto *CI = dyn_cast<ConstantSDNode>(OffImm)) {
154 int64_t C = CI->getSExtValue();
155 if (C <= Max)
156 return true;
157 }
158 }
159
160 // Otherwise, base only, materialize address in register.
161 Base = N;
162 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i64);
163 return true;
164 }
165
166 template<int Width>
167 bool SelectAddrModeWRO(SDValue N, SDValue &Base, SDValue &Offset,
168 SDValue &SignExtend, SDValue &DoShift) {
169 return SelectAddrModeWRO(N, Width / 8, Base, Offset, SignExtend, DoShift);
170 }
171
172 template<int Width>
173 bool SelectAddrModeXRO(SDValue N, SDValue &Base, SDValue &Offset,
174 SDValue &SignExtend, SDValue &DoShift) {
175 return SelectAddrModeXRO(N, Width / 8, Base, Offset, SignExtend, DoShift);
176 }
177
178 bool SelectExtractHigh(SDValue N, SDValue &Res) {
179 if (Subtarget->isLittleEndian() && N->getOpcode() == ISD::BITCAST)
180 N = N->getOperand(0);
181 if (N->getOpcode() != ISD::EXTRACT_SUBVECTOR ||
182 !isa<ConstantSDNode>(N->getOperand(1)))
183 return false;
184 EVT VT = N->getValueType(0);
185 EVT LVT = N->getOperand(0).getValueType();
186 unsigned Index = N->getConstantOperandVal(1);
187 if (!VT.is64BitVector() || !LVT.is128BitVector() ||
188 Index != VT.getVectorNumElements())
189 return false;
190 Res = N->getOperand(0);
191 return true;
192 }
193
194 bool SelectRoundingVLShr(SDValue N, SDValue &Res1, SDValue &Res2) {
195 if (N.getOpcode() != AArch64ISD::VLSHR)
196 return false;
197 SDValue Op = N->getOperand(0);
198 EVT VT = Op.getValueType();
199 unsigned ShtAmt = N->getConstantOperandVal(1);
200 if (ShtAmt > VT.getScalarSizeInBits() / 2 || Op.getOpcode() != ISD::ADD)
201 return false;
202
203 APInt Imm;
204 if (Op.getOperand(1).getOpcode() == AArch64ISD::MOVIshift)
206 Op.getOperand(1).getConstantOperandVal(0)
207 << Op.getOperand(1).getConstantOperandVal(1));
208 else if (Op.getOperand(1).getOpcode() == AArch64ISD::DUP &&
209 isa<ConstantSDNode>(Op.getOperand(1).getOperand(0)))
211 Op.getOperand(1).getConstantOperandVal(0));
212 else
213 return false;
214
215 if (Imm != 1ULL << (ShtAmt - 1))
216 return false;
217
218 Res1 = Op.getOperand(0);
219 Res2 = CurDAG->getTargetConstant(ShtAmt, SDLoc(N), MVT::i32);
220 return true;
221 }
222
223 bool SelectDupZeroOrUndef(SDValue N) {
224 switch(N->getOpcode()) {
225 case ISD::UNDEF:
226 case ISD::POISON:
227 return true;
228 case AArch64ISD::DUP:
229 case ISD::SPLAT_VECTOR: {
230 auto Opnd0 = N->getOperand(0);
231 if (isNullConstant(Opnd0))
232 return true;
233 if (isNullFPConstant(Opnd0))
234 return true;
235 break;
236 }
237 default:
238 break;
239 }
240
241 return false;
242 }
243
244 bool SelectAny(SDValue) { return true; }
245
246 bool SelectDupZero(SDValue N) {
247 switch(N->getOpcode()) {
248 case AArch64ISD::DUP:
249 case ISD::SPLAT_VECTOR: {
250 auto Opnd0 = N->getOperand(0);
251 if (isNullConstant(Opnd0))
252 return true;
253 if (isNullFPConstant(Opnd0))
254 return true;
255 break;
256 }
257 }
258
259 return false;
260 }
261
262 template <MVT::SimpleValueType VT, bool Negate>
263 bool SelectSVEAddSubImm(SDValue N, SDValue &Imm, SDValue &Shift) {
264 return SelectSVEAddSubImm(N, VT, Imm, Shift, Negate);
265 }
266
267 template <MVT::SimpleValueType VT, bool Negate>
268 bool SelectSVEAddSubSSatImm(SDValue N, SDValue &Imm, SDValue &Shift) {
269 return SelectSVEAddSubSSatImm(N, VT, Imm, Shift, Negate);
270 }
271
272 template <MVT::SimpleValueType VT>
273 bool SelectSVECpyDupImm(SDValue N, SDValue &Imm, SDValue &Shift) {
274 return SelectSVECpyDupImm(N, VT, Imm, Shift);
275 }
276
277 template <MVT::SimpleValueType VT, bool Invert = false>
278 bool SelectSVELogicalImm(SDValue N, SDValue &Imm) {
279 return SelectSVELogicalImm(N, VT, Imm, Invert);
280 }
281
282 template <MVT::SimpleValueType VT>
283 bool SelectSVEArithImm(SDValue N, SDValue &Imm) {
284 return SelectSVEArithImm(N, VT, Imm);
285 }
286
287 template <unsigned Low, unsigned High, bool AllowSaturation = false>
288 bool SelectSVEShiftImm(SDValue N, SDValue &Imm) {
289 return SelectSVEShiftImm(N, Low, High, AllowSaturation, Imm);
290 }
291
292 bool SelectSVEShiftSplatImmR(SDValue N, SDValue &Imm) {
293 if (N->getOpcode() != ISD::SPLAT_VECTOR)
294 return false;
295
296 EVT EltVT = N->getValueType(0).getVectorElementType();
297 return SelectSVEShiftImm(N->getOperand(0), /* Low */ 1,
298 /* High */ EltVT.getFixedSizeInBits(),
299 /* AllowSaturation */ true, Imm);
300 }
301
302 // Returns a suitable CNT/INC/DEC/RDVL multiplier to calculate VSCALE*N.
303 template<signed Min, signed Max, signed Scale, bool Shift>
304 bool SelectCntImm(SDValue N, SDValue &Imm) {
306 return false;
307
308 int64_t MulImm = cast<ConstantSDNode>(N)->getSExtValue();
309 if (Shift)
310 MulImm = 1LL << MulImm;
311
312 if ((MulImm % std::abs(Scale)) != 0)
313 return false;
314
315 MulImm /= Scale;
316 if ((MulImm >= Min) && (MulImm <= Max)) {
317 Imm = CurDAG->getTargetConstant(MulImm, SDLoc(N), MVT::i32);
318 return true;
319 }
320
321 return false;
322 }
323
324 template <signed Max, signed Scale>
325 bool SelectEXTImm(SDValue N, SDValue &Imm) {
327 return false;
328
329 int64_t MulImm = cast<ConstantSDNode>(N)->getSExtValue();
330
331 if (MulImm >= 0 && MulImm <= Max) {
332 MulImm *= Scale;
333 Imm = CurDAG->getTargetConstant(MulImm, SDLoc(N), MVT::i32);
334 return true;
335 }
336
337 return false;
338 }
339
340 template <unsigned BaseReg, unsigned Max>
341 bool ImmToReg(SDValue N, SDValue &Imm) {
342 if (auto *CI = dyn_cast<ConstantSDNode>(N)) {
343 uint64_t C = CI->getZExtValue();
344
345 if (C > Max)
346 return false;
347
348 Imm = CurDAG->getRegister(BaseReg + C, MVT::Other);
349 return true;
350 }
351 return false;
352 }
353
354 /// Form sequences of consecutive 64/128-bit registers for use in NEON
355 /// instructions making use of a vector-list (e.g. ldN, tbl). Vecs must have
356 /// between 1 and 4 elements. If it contains a single element that is returned
357 /// unchanged; otherwise a REG_SEQUENCE value is returned.
360 // Form a sequence of SVE registers for instructions using list of vectors,
361 // e.g. structured loads and stores (ldN, stN).
362 SDValue createZTuple(ArrayRef<SDValue> Vecs);
363
364 // Similar to above, except the register must start at a multiple of the
365 // tuple, e.g. z2 for a 2-tuple, or z8 for a 4-tuple.
366 SDValue createZMulTuple(ArrayRef<SDValue> Regs);
367
368 /// Generic helper for the createDTuple/createQTuple
369 /// functions. Those should almost always be called instead.
370 SDValue createTuple(ArrayRef<SDValue> Vecs, const unsigned RegClassIDs[],
371 const unsigned SubRegs[]);
372
373 void SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc, bool isExt);
374
375 bool tryIndexedLoad(SDNode *N);
376
377 void SelectPtrauthAuth(SDNode *N);
378 void SelectPtrauthResign(SDNode *N);
379 void SelectPtrauthResignWithPC(SDNode *N);
380
381 bool trySelectStackSlotTagP(SDNode *N);
382 void SelectTagP(SDNode *N);
383
384 void SelectLoad(SDNode *N, unsigned NumVecs, unsigned Opc,
385 unsigned SubRegIdx);
386 void SelectPostLoad(SDNode *N, unsigned NumVecs, unsigned Opc,
387 unsigned SubRegIdx);
388 void SelectLoadLane(SDNode *N, unsigned NumVecs, unsigned Opc);
389 void SelectPostLoadLane(SDNode *N, unsigned NumVecs, unsigned Opc);
390 void SelectPredicatedLoad(SDNode *N, unsigned NumVecs, unsigned Scale,
391 unsigned Opc_rr, unsigned Opc_ri,
392 bool IsIntr = false);
393 void SelectContiguousMultiVectorLoad(SDNode *N, unsigned NumVecs,
394 unsigned Scale, unsigned Opc_ri,
395 unsigned Opc_rr);
396 void SelectDestructiveMultiIntrinsic(SDNode *N, unsigned NumVecs,
397 bool IsZmMulti, unsigned Opcode,
398 bool HasPred = false);
399 void SelectPExtPair(SDNode *N, unsigned Opc);
400 void SelectWhilePair(SDNode *N, unsigned Opc);
401 void SelectCVTIntrinsic(SDNode *N, unsigned NumVecs, unsigned Opcode);
402 void SelectCVTIntrinsicFP8(SDNode *N, unsigned NumVecs, unsigned Opcode);
403 void SelectClamp(SDNode *N, unsigned NumVecs, unsigned Opcode);
404 void SelectUnaryMultiIntrinsic(SDNode *N, unsigned NumOutVecs,
405 bool IsTupleInput, unsigned Opc);
406 void SelectFrintFromVT(SDNode *N, unsigned NumVecs, unsigned Opcode);
407
408 template <unsigned MaxIdx, unsigned Scale>
409 void SelectMultiVectorMove(SDNode *N, unsigned NumVecs, unsigned BaseReg,
410 unsigned Op);
411 void SelectMultiVectorMoveZ(SDNode *N, unsigned NumVecs,
412 unsigned Op, unsigned MaxIdx, unsigned Scale,
413 unsigned BaseReg = 0);
414 /// SVE Reg+Imm addressing mode.
415 template <int64_t Min, int64_t Max>
416 bool SelectAddrModeIndexedSVE(SDNode *Root, SDValue N, SDValue &Base,
417 SDValue &OffImm);
418 /// SVE Reg+Reg address mode.
419 template <unsigned Scale>
420 bool SelectSVERegRegAddrMode(SDValue N, SDValue &Base, SDValue &Offset) {
421 return SelectSVERegRegAddrMode(N, Scale, Base, Offset);
422 }
423
424 void SelectMultiVectorLutiLane(SDNode *Node, unsigned NumOutVecs,
425 unsigned Opc, uint32_t MaxImm);
426 void SelectMultiVectorLuti6LaneX4(SDNode *Node, unsigned NumIndexVecs);
427
428 void SelectMultiVectorLuti(SDNode *Node, unsigned NumOutVecs, unsigned Opc,
429 unsigned NumInVecs);
430
431 template <unsigned MaxIdx, unsigned Scale>
432 bool SelectSMETileSlice(SDValue N, SDValue &Vector, SDValue &Offset) {
433 return SelectSMETileSlice(N, MaxIdx, Vector, Offset, Scale);
434 }
435
436 void SelectStore(SDNode *N, unsigned NumVecs, unsigned Opc);
437 void SelectPostStore(SDNode *N, unsigned NumVecs, unsigned Opc);
438 void SelectStoreLane(SDNode *N, unsigned NumVecs, unsigned Opc);
439 void SelectPostStoreLane(SDNode *N, unsigned NumVecs, unsigned Opc);
440 void SelectPredicatedStore(SDNode *N, unsigned NumVecs, unsigned Scale,
441 unsigned Opc_rr, unsigned Opc_ri);
442 std::tuple<unsigned, SDValue, SDValue>
443 findAddrModeSVELoadStore(SDNode *N, unsigned Opc_rr, unsigned Opc_ri,
444 const SDValue &OldBase, const SDValue &OldOffset,
445 unsigned Scale);
446
447 bool tryBitfieldExtractOp(SDNode *N);
448 bool tryBitfieldInsertOp(SDNode *N);
449 bool tryBitfieldInsertInZeroOp(SDNode *N);
450
451 bool tryReadRegister(SDNode *N);
452 bool tryWriteRegister(SDNode *N);
453
454 bool trySelectCastFixedLengthToScalableVector(SDNode *N);
455 bool trySelectCastScalableToFixedLengthVector(SDNode *N);
456
457 bool trySelectXAR(SDNode *N);
458
459 bool tryFoldCselToFMaxMin(SDNode *N);
460
461// Include the pieces autogenerated from the target description.
462#include "AArch64GenDAGISel.inc"
463
464private:
465 bool SelectShiftedRegister(SDValue N, bool AllowROR, SDValue &Reg,
466 SDValue &Shift);
467 bool SelectShiftedRegisterFromAnd(SDValue N, SDValue &Reg, SDValue &Shift);
468 bool SelectAddrModeIndexed7S(SDValue N, unsigned Size, SDValue &Base,
469 SDValue &OffImm) {
470 return SelectAddrModeIndexedBitWidth(N, true, 7, Size, Base, OffImm);
471 }
472 bool SelectAddrModeIndexedBitWidth(SDValue N, bool IsSignedImm, unsigned BW,
473 unsigned Size, SDValue &Base,
474 SDValue &OffImm);
475 bool SelectAddrModeIndexed(SDValue N, unsigned Size, SDValue &Base,
476 SDValue &OffImm);
477 bool SelectAddrModeUnscaled(SDValue N, unsigned Size, SDValue &Base,
478 SDValue &OffImm);
479 bool SelectAddrModeWRO(SDValue N, unsigned Size, SDValue &Base,
480 SDValue &Offset, SDValue &SignExtend,
481 SDValue &DoShift);
482 bool SelectAddrModeXRO(SDValue N, unsigned Size, SDValue &Base,
483 SDValue &Offset, SDValue &SignExtend,
484 SDValue &DoShift);
485 bool isWorthNegatingImm(SDValue V) const;
486 bool isWorthFoldingALU(SDValue V, bool LSL = false) const;
487 bool isWorthFoldingAddr(SDValue V, unsigned Size) const;
488 bool SelectExtendedSHL(SDValue N, unsigned Size, bool WantExtend,
489 SDValue &Offset, SDValue &SignExtend);
490
491 template<unsigned RegWidth>
492 bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos) {
493 return SelectCVTFixedPosOperand(N, FixedPos, RegWidth);
494 }
495 bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos, unsigned Width);
496
497 template <unsigned RegWidth>
498 bool SelectCVTFixedPointVec(SDValue N, SDValue &FixedPos) {
499 return SelectCVTFixedPointVec(N, FixedPos, RegWidth);
500 }
501 bool SelectCVTFixedPointVec(SDValue N, SDValue &FixedPos, unsigned Width);
502
503 template<unsigned RegWidth>
504 bool SelectCVTFixedPosRecipOperand(SDValue N, SDValue &FixedPos) {
505 return SelectCVTFixedPosRecipOperand(N, FixedPos, RegWidth);
506 }
507
508 bool SelectCVTFixedPosRecipOperand(SDValue N, SDValue &FixedPos,
509 unsigned Width);
510
511 template <unsigned FloatWidth>
512 bool SelectCVTFixedPosRecipOperandVec(SDValue N, SDValue &FixedPos) {
513 return SelectCVTFixedPosRecipOperandVec(N, FixedPos, FloatWidth);
514 }
515
516 bool SelectCVTFixedPosRecipOperandVec(SDValue N, SDValue &FixedPos,
517 unsigned Width);
518
519 bool SelectCMP_SWAP(SDNode *N);
520
521 AArch64MemoryHint decodeMemoryHintFlags(MachineMemOperand *MMO) const;
522 bool isAtomicMemoryHint(SDNode *N, AArch64MemoryHint Hint) const;
523
524 bool SelectSVEAddSubImm(SDValue N, MVT VT, SDValue &Imm, SDValue &Shift,
525 bool Negate);
526 bool SelectSVEAddSubImm(SDLoc DL, APInt Value, MVT VT, SDValue &Imm,
527 SDValue &Shift, bool Negate);
528 bool SelectSVEAddSubSSatImm(SDValue N, MVT VT, SDValue &Imm, SDValue &Shift,
529 bool Negate);
530 bool SelectSVECpyDupImm(SDValue N, MVT VT, SDValue &Imm, SDValue &Shift);
531 bool SelectSVELogicalImm(SDValue N, MVT VT, SDValue &Imm, bool Invert);
532
533 // Match `<NEON Splat> SVEImm` (where <NEON Splat> could be fmov, movi, etc).
534 bool SelectNEONSplatOfSVELogicalImm(SDValue N, SDValue &Imm);
535 bool SelectNEONSplatOfSVEAddSubImm(SDValue N, SDValue &Imm, SDValue &Shift);
536 bool SelectNEONSplatOfSVEArithSImm(SDValue N, SDValue &Imm);
537 bool SelectNEONSplatOfSImm8(SDValue N, SDValue &Imm);
538 bool SelectNEONSplatOfUImm8(SDValue N, SDValue &Imm);
539
540 bool SelectSVESignedArithImm(SDLoc DL, APInt Value, SDValue &Imm);
541 bool SelectSVESignedArithImm(SDValue N, SDValue &Imm);
542 bool SelectSVEShiftImm(SDValue N, uint64_t Low, uint64_t High,
543 bool AllowSaturation, SDValue &Imm);
544
545 bool SelectSVEArithImm(SDValue N, MVT VT, SDValue &Imm);
546 bool SelectSVERegRegAddrMode(SDValue N, unsigned Scale, SDValue &Base,
547 SDValue &Offset);
548 bool SelectSMETileSlice(SDValue N, unsigned MaxSize, SDValue &Vector,
549 SDValue &Offset, unsigned Scale = 1);
550
551 bool SelectAllActivePredicate(SDValue N);
552 bool SelectAnyPredicate(SDValue N);
553
554 bool SelectCmpBranchUImm6Operand(SDNode *P, SDValue N, SDValue &Imm);
555
556 template <bool MatchCBB>
557 bool SelectCmpBranchExtOperand(SDValue N, SDValue &Reg, SDValue &ExtType);
558};
559
560class AArch64DAGToDAGISelLegacy : public SelectionDAGISelLegacy {
561public:
562 static char ID;
563 explicit AArch64DAGToDAGISelLegacy(AArch64TargetMachine &tm,
564 CodeGenOptLevel OptLevel)
566 ID, std::make_unique<AArch64DAGToDAGISel>(tm, OptLevel)) {}
567};
568} // end anonymous namespace
569
570char AArch64DAGToDAGISelLegacy::ID = 0;
571
572INITIALIZE_PASS(AArch64DAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
573
576 std::make_unique<AArch64DAGToDAGISel>(TM, TM.getOptLevel())) {}
577
578/// addBitcastHints - This method adds bitcast hints to the operands of a node
579/// to help instruction selector determine which operands are in Neon registers.
581 SDLoc DL(&N);
582 auto getFloatVT = [&](EVT VT) {
583 EVT ScalarVT = VT.getScalarType();
584 assert((ScalarVT == MVT::i32 || ScalarVT == MVT::i64) && "Unexpected VT");
585 return VT.changeElementType(*(DAG.getContext()),
586 ScalarVT == MVT::i32 ? MVT::f32 : MVT::f64);
587 };
589 NewOps.reserve(N.getNumOperands());
590
591 for (unsigned I = 0, E = N.getNumOperands(); I < E; ++I) {
592 auto bitcasted = DAG.getBitcast(getFloatVT(N.getOperand(I).getValueType()),
593 N.getOperand(I));
594 NewOps.push_back(bitcasted);
595 }
596 EVT OrigVT = N.getValueType(0);
597 SDValue OpNode = DAG.getNode(N.getOpcode(), DL, getFloatVT(OrigVT), NewOps);
598 return DAG.getBitcast(OrigVT, OpNode);
599}
600
601/// isIntImmediate - This method tests to see if the node is a constant
602/// operand. If so Imm will receive the 64-bit value.
603static bool isIntImmediate(const SDNode *N, uint64_t &Imm) {
605 Imm = C->getZExtValue();
606 return true;
607 }
608 return false;
609}
610
611// isIntImmediate - This method tests to see if a constant operand.
612// If so Imm will receive the value.
614 return isIntImmediate(N.getNode(), Imm);
615}
616
617// isOpcWithIntImmediate - This method tests to see if the node is a specific
618// opcode and that it has a immediate integer right operand.
619// If so Imm will receive the 32 bit value.
620static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc,
621 uint64_t &Imm) {
622 return N->getOpcode() == Opc &&
623 isIntImmediate(N->getOperand(1).getNode(), Imm);
624}
625
626// isIntImmediateEq - This method tests to see if N is a constant operand that
627// is equivalent to 'ImmExpected'.
628#ifndef NDEBUG
629static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected) {
631 if (!isIntImmediate(N.getNode(), Imm))
632 return false;
633 return Imm == ImmExpected;
634}
635#endif
636
637static APInt DecodeFMOVImm(uint64_t Imm, unsigned RegWidth) {
638 assert(RegWidth == 32 || RegWidth == 64);
639 if (RegWidth == 32)
640 return APInt(RegWidth,
643}
644
645// Decodes the raw integer splat value from a NEON splat operation.
646static std::optional<APInt> DecodeNEONSplat(SDValue N,
647 const AArch64Subtarget *Subtarget) {
648 assert(N.getValueType().isInteger() && "Only integers are supported");
649 if (N->getOpcode() == AArch64ISD::NVCAST ||
650 (N->getOpcode() == ISD::BITCAST && Subtarget->isLittleEndian()))
651 N = N->getOperand(0);
652 unsigned SplatWidth = N.getScalarValueSizeInBits();
653 if (N.getOpcode() == AArch64ISD::FMOV)
654 return DecodeFMOVImm(N.getConstantOperandVal(0), SplatWidth);
655 if (N->getOpcode() == AArch64ISD::MOVI)
656 return APInt(SplatWidth, N.getConstantOperandVal(0));
657 if (N->getOpcode() == AArch64ISD::MOVIshift)
658 return APInt(SplatWidth, N.getConstantOperandVal(0)
659 << N.getConstantOperandVal(1));
660 if (N->getOpcode() == AArch64ISD::MVNIshift)
661 return ~APInt(SplatWidth, N.getConstantOperandVal(0)
662 << N.getConstantOperandVal(1));
663 if (N->getOpcode() == AArch64ISD::MOVIedit)
665 N.getConstantOperandVal(0)));
666 if (N->getOpcode() == AArch64ISD::DUP)
667 if (auto *Const = dyn_cast<ConstantSDNode>(N->getOperand(0)))
668 return Const->getAPIntValue().trunc(SplatWidth);
669 APInt SplatVal;
670 if (ISD::isConstantSplatVector(N.getNode(), SplatVal))
671 return SplatVal.trunc(SplatWidth);
672 // TODO: Recognize more splat-like NEON operations. See ConstantBuildVector
673 // in AArch64ISelLowering.
674 return std::nullopt;
675}
676
677// If \p N is a NEON splat operation (movi, fmov, etc), return the splat value
678// matching the element size of N.
679static std::optional<APInt>
681 unsigned SplatWidth = N.getScalarValueSizeInBits();
682 if (std::optional<APInt> SplatVal = DecodeNEONSplat(N, Subtarget)) {
683 if (SplatVal->getBitWidth() <= SplatWidth)
684 return APInt::getSplat(SplatWidth, *SplatVal);
685 if (SplatVal->isSplat(SplatWidth))
686 return SplatVal->trunc(SplatWidth);
687 }
688 return std::nullopt;
689}
690
691bool AArch64DAGToDAGISel::SelectNEONSplatOfSVELogicalImm(SDValue N,
692 SDValue &Imm) {
693 std::optional<APInt> ImmVal = GetNEONSplatValue(N, Subtarget);
694 if (!ImmVal)
695 return false;
696 uint64_t Encoding;
697 if (!AArch64_AM::isSVELogicalImm(N.getScalarValueSizeInBits(),
698 ImmVal->getZExtValue(), Encoding))
699 return false;
700
701 Imm = CurDAG->getTargetConstant(Encoding, SDLoc(N), MVT::i64);
702 return true;
703}
704
705bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEAddSubImm(SDValue N, SDValue &Imm,
706 SDValue &Shift) {
707 if (std::optional<APInt> ImmVal = GetNEONSplatValue(N, Subtarget))
708 return SelectSVEAddSubImm(SDLoc(N), *ImmVal,
709 N.getValueType().getScalarType().getSimpleVT(),
710 Imm, Shift,
711 /*Negate=*/false);
712 return false;
713}
714
715bool AArch64DAGToDAGISel::SelectNEONSplatOfSVEArithSImm(SDValue N,
716 SDValue &Imm) {
717 if (std::optional<APInt> ImmVal = GetNEONSplatValue(N, Subtarget))
718 return SelectSVESignedArithImm(SDLoc(N), *ImmVal, Imm);
719 return false;
720}
721
722bool AArch64DAGToDAGISel::SelectNEONSplatOfSImm8(SDValue N, SDValue &Imm) {
723 std::optional<APInt> ImmAPIntVal = GetNEONSplatValue(N, Subtarget);
724 if (!ImmAPIntVal)
725 return false;
726
727 int64_t ImmVal = ImmAPIntVal->getSExtValue();
728 if (ImmVal < -128 || ImmVal > 127)
729 return false;
730
731 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(N), MVT::i32);
732 return true;
733}
734
735bool AArch64DAGToDAGISel::SelectNEONSplatOfUImm8(SDValue N, SDValue &Imm) {
736 std::optional<APInt> ImmAPIntVal = GetNEONSplatValue(N, Subtarget);
737 if (!ImmAPIntVal)
738 return false;
739
740 uint64_t ImmVal = ImmAPIntVal->getZExtValue();
741 if (ImmVal > 255)
742 return false;
743
744 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(N), MVT::i32);
745 return true;
746}
747
748bool AArch64DAGToDAGISel::SelectInlineAsmMemoryOperand(
749 const SDValue &Op, const InlineAsm::ConstraintCode ConstraintID,
750 std::vector<SDValue> &OutOps) {
751 switch(ConstraintID) {
752 default:
753 llvm_unreachable("Unexpected asm memory constraint");
754 case InlineAsm::ConstraintCode::m:
755 case InlineAsm::ConstraintCode::o:
756 case InlineAsm::ConstraintCode::Q:
757 // We need to make sure that this one operand does not end up in XZR, thus
758 // require the address to be in a pointer register.
759 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
760 const TargetRegisterClass *TRC =
762 SDLoc dl(Op);
763 SDValue RC = CurDAG->getTargetConstant(TRC->getID(), dl, MVT::i64);
764 SDValue NewOp =
765 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
766 dl, Op.getValueType(),
767 Op, RC), 0);
768 OutOps.push_back(NewOp);
769 return false;
770 }
771 return true;
772}
773
774// Returns true if every use of N is a variable shift (SHL/SRL/SRA/ROTR) that
775// uses N as its shift-amount operand. When that holds, folding N into the
776// shift amount (e.g. generating a NEG or MVN) is safe even with multiple
777// uses, because each shift only reads the low bits of the amount.
779 return all_of(N.getNode()->users(), [&](SDNode *User) {
780 switch (User->getOpcode()) {
781 case ISD::SHL:
782 case ISD::SRL:
783 case ISD::SRA:
784 case ISD::ROTR:
785 return User->getOperand(1).getNode() == N.getNode();
786 case ISD::ANY_EXTEND:
787 case ISD::ZERO_EXTEND:
788 case ISD::SIGN_EXTEND:
789 // A 32-bit shift amount may be widened to i64 before it reaches the
790 // shift; look through the extend to the ultimate users.
791 return allUsesAreShiftAmounts(SDValue(User, 0));
792 default:
793 return false;
794 }
795 });
796}
797
798template <unsigned ShiftWidth>
799bool AArch64DAGToDAGISel::SelectShiftMask(SDValue N, SDValue &ShAmt) {
800 // AArch64 shift instructions only use the low log2(ShiftWidth) bits of the
801 // shift amount. The matcher may run on a node wider or narrower than the
802 // shift result (an i32 amount widened to i64, or an i64 modulus reduced to
803 // an i32 subtract), so the redundancy threshold and modulus come from the
804 // ShiftWidth template parameter, while the NEG/NOT opcode follows the node's
805 // own type. Return false if nothing was combined so other patterns (e.g.
806 // zext/sext GPR32 -> SUBREG_TO_REG) can match.
807 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1)) &&
808 (N.getValueType() == MVT::i32 || N.getValueType() == MVT::i64)) {
809 uint64_t Mask = N.getConstantOperandVal(1);
810 // Remove AND if the mask covers at least the low log2(ShiftWidth) bits.
811 if ((unsigned)llvm::countr_one(Mask) >= Log2_32(ShiftWidth)) {
812 ShAmt = N.getOperand(0);
813 return true;
814 }
815 }
816 // If shifting by X+/-N where N == 0 mod ShiftWidth, then just shift by X
817 // to avoid the ADD/SUB. The low log2(ShiftWidth) bits are unchanged, so the
818 // shift can use X directly; the original ADD/SUB stays for any other users.
819 if ((N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) &&
820 (N.getValueType() == MVT::i32 || N.getValueType() == MVT::i64)) {
822 if (isIntImmediate(N.getOperand(1).getNode(), Imm) &&
823 (Imm % ShiftWidth == 0)) {
824 ShAmt = N.getOperand(0);
825 return true;
826 }
827 }
828
829 // If shifting by N-X where N == 0 mod ShiftWidth, then just shift by -X
830 // to generate a NEG instead of a SUB from a constant.
831 if (N.getOpcode() == ISD::SUB && allUsesAreShiftAmounts(N) &&
832 (N.getValueType() == MVT::i32 || N.getValueType() == MVT::i64)) {
834 if (isIntImmediate(N.getOperand(0).getNode(), Imm) && Imm != 0 &&
835 (Imm % ShiftWidth == 0)) {
836 SDLoc DL(N);
837 EVT VT = N.getValueType();
838 bool Is32 = VT == MVT::i32;
839 unsigned NegOpc = Is32 ? AArch64::SUBWrr : AArch64::SUBXrr;
840 unsigned ZeroReg = Is32 ? AArch64::WZR : AArch64::XZR;
841 SDValue Zero =
842 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, ZeroReg, VT);
843 MachineSDNode *Neg =
844 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1));
845 ShAmt = SDValue(Neg, 0);
846 return true;
847 }
848 }
849
850 // If shifting by N-X where N == -1 mod ShiftWidth, then just shift by ~X
851 // to generate a NOT (MVN) instead of a SUB from a constant.
852 if (N.getOpcode() == ISD::SUB && allUsesAreShiftAmounts(N) &&
853 (N.getValueType() == MVT::i32 || N.getValueType() == MVT::i64)) {
855 if (isIntImmediate(N.getOperand(0).getNode(), Imm) &&
856 (Imm % ShiftWidth == ShiftWidth - 1)) {
857 SDLoc DL(N);
858 EVT VT = N.getValueType();
859 bool Is32 = VT == MVT::i32;
860 unsigned NotOpc = Is32 ? AArch64::ORNWrr : AArch64::ORNXrr;
861 unsigned ZeroReg = Is32 ? AArch64::WZR : AArch64::XZR;
862 SDValue Zero =
863 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, ZeroReg, VT);
864 MachineSDNode *Not =
865 CurDAG->getMachineNode(NotOpc, DL, VT, Zero, N.getOperand(1));
866 ShAmt = SDValue(Not, 0);
867 return true;
868 }
869 }
870
871 return false;
872}
873
874/// SelectArithImmed - Select an immediate value that can be represented as
875/// a 12-bit value shifted left by either 0 or 12. If so, return true with
876/// Val set to the 12-bit value and Shift set to the shifter operand.
877bool AArch64DAGToDAGISel::SelectArithImmed(SDValue N, SDValue &Val,
878 SDValue &Shift) {
879 // This function is called from the addsub_shifted_imm ComplexPattern,
880 // which lists [imm] as the list of opcode it's interested in, however
881 // we still need to check whether the operand is actually an immediate
882 // here because the ComplexPattern opcode list is only used in
883 // root-level opcode matching.
884 if (!isa<ConstantSDNode>(N.getNode()))
885 return false;
886
887 uint64_t Immed = N.getNode()->getAsZExtVal();
888
890 return false;
891
892 unsigned ShiftAmt = AArch64_AM::getArithImmedShift(Immed);
893 Immed >>= ShiftAmt;
894
895 unsigned ShVal = AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt);
896 SDLoc dl(N);
897 Val = CurDAG->getTargetConstant(Immed, dl, MVT::i32);
898 Shift = CurDAG->getTargetConstant(ShVal, dl, MVT::i32);
899 return true;
900}
901
902/// SelectNegArithImmed - As above, but negates the value before trying to
903/// select it.
904bool AArch64DAGToDAGISel::SelectNegArithImmed(SDValue N, SDValue &Val,
905 SDValue &Shift) {
906 // This function is called from the addsub_shifted_imm ComplexPattern,
907 // which lists [imm] as the list of opcode it's interested in, however
908 // we still need to check whether the operand is actually an immediate
909 // here because the ComplexPattern opcode list is only used in
910 // root-level opcode matching.
911 if (!isa<ConstantSDNode>(N.getNode()))
912 return false;
913
914 // The immediate operand must be a 24-bit zero-extended immediate.
915 uint64_t Immed = N.getNode()->getAsZExtVal();
916
917 // This negation is almost always valid, but "cmp wN, #0" and "cmn wN, #0"
918 // have the opposite effect on the C flag, so this pattern mustn't match under
919 // those circumstances.
920 if (Immed == 0)
921 return false;
922
923 if (N.getValueType() == MVT::i32)
924 Immed = ~((uint32_t)Immed) + 1;
925 else
926 Immed = ~Immed + 1ULL;
927 if (Immed & 0xFFFFFFFFFF000000ULL)
928 return false;
929
930 Immed &= 0xFFFFFFULL;
931 return SelectArithImmed(CurDAG->getConstant(Immed, SDLoc(N), MVT::i32), Val,
932 Shift);
933}
934
935/// getShiftTypeForNode - Translate a shift node to the corresponding
936/// ShiftType value.
938 switch (N.getOpcode()) {
939 default:
941 case ISD::SHL:
942 return AArch64_AM::LSL;
943 case ISD::SRL:
944 return AArch64_AM::LSR;
945 case ISD::SRA:
946 return AArch64_AM::ASR;
947 case ISD::ROTR:
948 return AArch64_AM::ROR;
949 }
950}
951
953 return isa<MemSDNode>(*N) || N->getOpcode() == AArch64ISD::PREFETCH;
954}
955
956/// Determine whether it is worth it to fold SHL into the addressing
957/// mode.
959 assert(V.getOpcode() == ISD::SHL && "invalid opcode");
960 // It is worth folding logical shift of up to three places.
961 auto *CSD = dyn_cast<ConstantSDNode>(V.getOperand(1));
962 if (!CSD)
963 return false;
964 unsigned ShiftVal = CSD->getZExtValue();
965 if (ShiftVal > 3)
966 return false;
967
968 // Check if this particular node is reused in any non-memory related
969 // operation. If yes, do not try to fold this node into the address
970 // computation, since the computation will be kept.
971 const SDNode *Node = V.getNode();
972 for (SDNode *UI : Node->users())
973 if (!isMemOpOrPrefetch(UI))
974 for (SDNode *UII : UI->users())
975 if (!isMemOpOrPrefetch(UII))
976 return false;
977 return true;
978}
979
980/// Determine whether it is worth to fold V into an extended register addressing
981/// mode.
982bool AArch64DAGToDAGISel::isWorthFoldingAddr(SDValue V, unsigned Size) const {
983 // Trivial if we are optimizing for code size or if there is only
984 // one use of the value.
985 if (CurDAG->shouldOptForSize() || V.hasOneUse())
986 return true;
987
988 // If a subtarget has a slow shift, folding a shift into multiple loads
989 // costs additional micro-ops.
990 if (Subtarget->hasAddrLSLSlow14() && (Size == 2 || Size == 16))
991 return false;
992
993 // Check whether we're going to emit the address arithmetic anyway because
994 // it's used by a non-address operation.
995 if (V.getOpcode() == ISD::SHL && isWorthFoldingSHL(V))
996 return true;
997 if (V.getOpcode() == ISD::ADD) {
998 const SDValue LHS = V.getOperand(0);
999 const SDValue RHS = V.getOperand(1);
1000 if (LHS.getOpcode() == ISD::SHL && isWorthFoldingSHL(LHS))
1001 return true;
1002 if (RHS.getOpcode() == ISD::SHL && isWorthFoldingSHL(RHS))
1003 return true;
1004 }
1005
1006 // It hurts otherwise, since the value will be reused.
1007 return false;
1008}
1009
1010/// and (shl/srl/sra, x, c), mask --> shl (srl/sra, x, c1), c2
1011/// to select more shifted register
1012bool AArch64DAGToDAGISel::SelectShiftedRegisterFromAnd(SDValue N, SDValue &Reg,
1013 SDValue &Shift) {
1014 EVT VT = N.getValueType();
1015 if (VT != MVT::i32 && VT != MVT::i64)
1016 return false;
1017
1018 if (N->getOpcode() != ISD::AND || !N->hasOneUse())
1019 return false;
1020 SDValue LHS = N.getOperand(0);
1021 if (!LHS->hasOneUse())
1022 return false;
1023
1024 unsigned LHSOpcode = LHS->getOpcode();
1025 if (LHSOpcode != ISD::SHL && LHSOpcode != ISD::SRL && LHSOpcode != ISD::SRA)
1026 return false;
1027
1028 ConstantSDNode *ShiftAmtNode = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
1029 if (!ShiftAmtNode)
1030 return false;
1031
1032 uint64_t ShiftAmtC = ShiftAmtNode->getZExtValue();
1033 ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(N.getOperand(1));
1034 if (!RHSC)
1035 return false;
1036
1037 APInt AndMask = RHSC->getAPIntValue();
1038 unsigned LowZBits, MaskLen;
1039 if (!AndMask.isShiftedMask(LowZBits, MaskLen))
1040 return false;
1041
1042 unsigned BitWidth = N.getValueSizeInBits();
1043 SDLoc DL(LHS);
1044 uint64_t NewShiftC;
1045 unsigned NewShiftOp;
1046 if (LHSOpcode == ISD::SHL) {
1047 // LowZBits <= ShiftAmtC will fall into isBitfieldPositioningOp
1048 if (LowZBits <= ShiftAmtC)
1049 return false;
1050
1051 NewShiftC = LowZBits - ShiftAmtC;
1052 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
1053 } else {
1054 if (LowZBits == 0)
1055 return false;
1056
1057 // NewShiftC >= BitWidth will fall into isBitfieldExtractOp
1058 NewShiftC = LowZBits + ShiftAmtC;
1059 if (NewShiftC >= BitWidth)
1060 return false;
1061
1062 // SRA need all high bits
1063 if (LHSOpcode == ISD::SRA && (BitWidth != (LowZBits + MaskLen)))
1064 return false;
1065
1066 if (LHSOpcode == ISD::SRL)
1067 NewShiftOp = VT == MVT::i64 ? AArch64::UBFMXri : AArch64::UBFMWri;
1068 else
1069 NewShiftOp = VT == MVT::i64 ? AArch64::SBFMXri : AArch64::SBFMWri;
1070 }
1071
1072 assert(NewShiftC < BitWidth && "Invalid shift amount");
1073 SDValue NewShiftAmt = CurDAG->getTargetConstant(NewShiftC, DL, VT);
1074 // If the mask doesn't extend to the MSB, extract only the masked field.
1075 unsigned MSB = BitWidth - 1;
1076 if (LowZBits + MaskLen < BitWidth)
1077 MSB = std::min<uint64_t>(NewShiftC + MaskLen, BitWidth) - 1;
1078 SDValue MSBC = CurDAG->getTargetConstant(MSB, DL, VT);
1079 Reg = SDValue(CurDAG->getMachineNode(NewShiftOp, DL, VT, LHS->getOperand(0),
1080 NewShiftAmt, MSBC),
1081 0);
1082 unsigned ShVal = AArch64_AM::getShifterImm(AArch64_AM::LSL, LowZBits);
1083 Shift = CurDAG->getTargetConstant(ShVal, DL, MVT::i32);
1084 return true;
1085}
1086
1087/// getExtendTypeForNode - Translate an extend node to the corresponding
1088/// ExtendType value.
1090getExtendTypeForNode(SDValue N, bool IsLoadStore = false) {
1091 if (N.getOpcode() == ISD::SIGN_EXTEND ||
1092 N.getOpcode() == ISD::SIGN_EXTEND_INREG) {
1093 EVT SrcVT;
1094 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG)
1095 SrcVT = cast<VTSDNode>(N.getOperand(1))->getVT();
1096 else
1097 SrcVT = N.getOperand(0).getValueType();
1098
1099 if (!IsLoadStore && SrcVT == MVT::i8)
1100 return AArch64_AM::SXTB;
1101 else if (!IsLoadStore && SrcVT == MVT::i16)
1102 return AArch64_AM::SXTH;
1103 else if (SrcVT == MVT::i32)
1104 return AArch64_AM::SXTW;
1105 assert(SrcVT != MVT::i64 && "extend from 64-bits?");
1106
1108 } else if (N.getOpcode() == ISD::ZERO_EXTEND ||
1109 N.getOpcode() == ISD::ANY_EXTEND) {
1110 EVT SrcVT = N.getOperand(0).getValueType();
1111 if (!IsLoadStore && SrcVT == MVT::i8)
1112 return AArch64_AM::UXTB;
1113 else if (!IsLoadStore && SrcVT == MVT::i16)
1114 return AArch64_AM::UXTH;
1115 else if (SrcVT == MVT::i32)
1116 return AArch64_AM::UXTW;
1117 assert(SrcVT != MVT::i64 && "extend from 64-bits?");
1118
1120 } else if (N.getOpcode() == ISD::AND) {
1121 ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1));
1122 if (!CSD)
1124 uint64_t AndMask = CSD->getZExtValue();
1125
1126 switch (AndMask) {
1127 default:
1129 case 0xFF:
1130 return !IsLoadStore ? AArch64_AM::UXTB : AArch64_AM::InvalidShiftExtend;
1131 case 0xFFFF:
1132 return !IsLoadStore ? AArch64_AM::UXTH : AArch64_AM::InvalidShiftExtend;
1133 case 0xFFFFFFFF:
1134 return AArch64_AM::UXTW;
1135 }
1136 }
1137
1139}
1140
1141/// Determine whether constant -V is cheaper to materialise than V.
1142bool AArch64DAGToDAGISel::isWorthNegatingImm(SDValue V) const {
1143 assert(isa<ConstantSDNode>(V) && "invalid node");
1144
1145 EVT VT = V.getValueType();
1146 assert((VT == MVT::i32 || VT == MVT::i64) && "invalid type");
1147
1148 // It's only worth negating the constant if it doesn't have other uses.
1149 if (!V.hasOneUse())
1150 return false;
1151
1152 uint64_t Imm = cast<ConstantSDNode>(V)->getZExtValue();
1153 unsigned BitSize = VT.getSizeInBits();
1155 AArch64_IMM::expandMOVImm(Imm, BitSize, OrigCost);
1156 AArch64_IMM::expandMOVImm(-Imm, BitSize, NewCost);
1157 return NewCost.size() < OrigCost.size();
1158}
1159
1160/// Determine whether it is worth to fold V into an extended register of an
1161/// Add/Sub. LSL means we are folding into an `add w0, w1, w2, lsl #N`
1162/// instruction, and the shift should be treated as worth folding even if has
1163/// multiple uses.
1164bool AArch64DAGToDAGISel::isWorthFoldingALU(SDValue V, bool LSL) const {
1165 // Trivial if we are optimizing for code size or if there is only
1166 // one use of the value.
1167 if (CurDAG->shouldOptForSize() || V.hasOneUse())
1168 return true;
1169
1170 // If a subtarget has a fastpath LSL we can fold a logical shift into
1171 // the add/sub and save a cycle.
1172 if (LSL && Subtarget->hasALULSLFast() && V.getOpcode() == ISD::SHL &&
1173 V.getConstantOperandVal(1) <= 4 &&
1175 return true;
1176
1177 // It hurts otherwise, since the value will be reused.
1178 return false;
1179}
1180
1181/// SelectShiftedRegister - Select a "shifted register" operand. If the value
1182/// is not shifted, set the Shift operand to default of "LSL 0". The logical
1183/// instructions allow the shifted register to be rotated, but the arithmetic
1184/// instructions do not. The AllowROR parameter specifies whether ROR is
1185/// supported.
1186bool AArch64DAGToDAGISel::SelectShiftedRegister(SDValue N, bool AllowROR,
1187 SDValue &Reg, SDValue &Shift) {
1188 if (SelectShiftedRegisterFromAnd(N, Reg, Shift))
1189 return true;
1190
1192 if (ShType == AArch64_AM::InvalidShiftExtend)
1193 return false;
1194 if (!AllowROR && ShType == AArch64_AM::ROR)
1195 return false;
1196
1197 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1198 unsigned BitSize = N.getValueSizeInBits();
1199 unsigned Val = RHS->getZExtValue() & (BitSize - 1);
1200 unsigned ShVal = AArch64_AM::getShifterImm(ShType, Val);
1201
1202 Reg = N.getOperand(0);
1203 Shift = CurDAG->getTargetConstant(ShVal, SDLoc(N), MVT::i32);
1204 return isWorthFoldingALU(N, true);
1205 }
1206
1207 return false;
1208}
1209
1210/// Instructions that accept extend modifiers like UXTW expect the register
1211/// being extended to be a GPR32, but the incoming DAG might be acting on a
1212/// GPR64 (either via SEXT_INREG or AND). Extract the appropriate low bits if
1213/// this is the case.
1215 if (N.getValueType() == MVT::i32)
1216 return N;
1217
1218 SDLoc dl(N);
1219 return CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl, MVT::i32, N);
1220}
1221
1222// Returns a suitable CNT/INC/DEC/RDVL multiplier to calculate VSCALE*N.
1223template<signed Low, signed High, signed Scale>
1224bool AArch64DAGToDAGISel::SelectRDVLImm(SDValue N, SDValue &Imm) {
1225 if (!isa<ConstantSDNode>(N))
1226 return false;
1227
1228 int64_t MulImm = cast<ConstantSDNode>(N)->getSExtValue();
1229 if ((MulImm % std::abs(Scale)) == 0) {
1230 int64_t RDVLImm = MulImm / Scale;
1231 if ((RDVLImm >= Low) && (RDVLImm <= High)) {
1232 Imm = CurDAG->getSignedTargetConstant(RDVLImm, SDLoc(N), MVT::i32);
1233 return true;
1234 }
1235 }
1236
1237 return false;
1238}
1239
1240// Returns a suitable RDSVL multiplier from a left shift.
1241template <signed Low, signed High>
1242bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(SDValue N, SDValue &Imm) {
1243 if (!isa<ConstantSDNode>(N))
1244 return false;
1245
1246 int64_t MulImm = 1LL << cast<ConstantSDNode>(N)->getSExtValue();
1247 if (MulImm >= Low && MulImm <= High) {
1248 Imm = CurDAG->getSignedTargetConstant(MulImm, SDLoc(N), MVT::i32);
1249 return true;
1250 }
1251
1252 return false;
1253}
1254
1255/// SelectArithExtendedRegister - Select a "extended register" operand. This
1256/// operand folds in an extend followed by an optional left shift.
1257bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue N, SDValue &Reg,
1258 SDValue &Shift) {
1259 unsigned ShiftVal = 0;
1261
1262 if (N.getOpcode() == ISD::SHL) {
1263 ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1));
1264 if (!CSD)
1265 return false;
1266 ShiftVal = CSD->getZExtValue();
1267 if (ShiftVal > 4)
1268 return false;
1269
1270 Ext = getExtendTypeForNode(N.getOperand(0));
1272 return false;
1273
1274 Reg = N.getOperand(0).getOperand(0);
1275 } else {
1276 Ext = getExtendTypeForNode(N);
1278 return false;
1279
1280 // Don't match sext of vector extracts. These can use SMOV, but if we match
1281 // this as an extended register, we'll always fold the extend into an ALU op
1282 // user of the extend (which results in a UMOV).
1284 SDValue Op = N.getOperand(0);
1285 if (Op->getOpcode() == ISD::ANY_EXTEND)
1286 Op = Op->getOperand(0);
1287 if (Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
1288 Op.getOperand(0).getValueType().isFixedLengthVector())
1289 return false;
1290 }
1291
1292 Reg = N.getOperand(0);
1293
1294 // Don't match if free 32-bit -> 64-bit zext can be used instead. Use the
1295 // isDef32 as a heuristic for when the operand is likely to be a 32bit def.
1296 auto isDef32 = [](SDValue N) {
1297 unsigned Opc = N.getOpcode();
1298 return Opc != ISD::TRUNCATE && Opc != TargetOpcode::EXTRACT_SUBREG &&
1301 Opc != ISD::FREEZE;
1302 };
1303 if (Ext == AArch64_AM::UXTW && Reg->getValueType(0).getSizeInBits() == 32 &&
1304 isDef32(Reg))
1305 return false;
1306 }
1307
1308 // Don't match if the sext can be folded with an asr to form an SBFX.
1309 if (Ext == AArch64_AM::SXTW && Reg.getOpcode() == ISD::SRA &&
1310 Reg.getValueType() == MVT::i32 &&
1311 isa<ConstantSDNode>(Reg.getOperand(1)) && Reg.hasOneUse())
1312 return false;
1313
1314 // AArch64 mandates that the RHS of the operation must use the smallest
1315 // register class that could contain the size being extended from. Thus,
1316 // if we're folding a (sext i8), we need the RHS to be a GPR32, even though
1317 // there might not be an actual 32-bit value in the program. We can
1318 // (harmlessly) synthesize one by injected an EXTRACT_SUBREG here.
1319 assert(Ext != AArch64_AM::UXTX && Ext != AArch64_AM::SXTX);
1320 Reg = narrowIfNeeded(CurDAG, Reg);
1321 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(N),
1322 MVT::i32);
1323 return isWorthFoldingALU(N);
1324}
1325
1326/// SelectArithUXTXRegister - Select a "UXTX register" operand. This
1327/// operand is referred by the instructions have SP operand
1328bool AArch64DAGToDAGISel::SelectArithUXTXRegister(SDValue N, SDValue &Reg,
1329 SDValue &Shift) {
1330 unsigned ShiftVal = 0;
1332
1333 if (N.getOpcode() != ISD::SHL)
1334 return false;
1335
1336 ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1));
1337 if (!CSD)
1338 return false;
1339 ShiftVal = CSD->getZExtValue();
1340 if (ShiftVal > 4)
1341 return false;
1342
1343 Ext = AArch64_AM::UXTX;
1344 Reg = N.getOperand(0);
1345 Shift = CurDAG->getTargetConstant(getArithExtendImm(Ext, ShiftVal), SDLoc(N),
1346 MVT::i32);
1347 return isWorthFoldingALU(N);
1348}
1349
1350/// If there's a use of this ADDlow that's not itself a load/store then we'll
1351/// need to create a real ADD instruction from it anyway and there's no point in
1352/// folding it into the mem op. Theoretically, it shouldn't matter, but there's
1353/// a single pseudo-instruction for an ADRP/ADD pair so over-aggressive folding
1354/// leads to duplicated ADRP instructions.
1356 for (auto *User : N->users()) {
1357 if (User->getOpcode() != ISD::LOAD && User->getOpcode() != ISD::STORE &&
1358 User->getOpcode() != ISD::ATOMIC_LOAD &&
1359 User->getOpcode() != ISD::ATOMIC_STORE)
1360 return false;
1361
1362 // ldar and stlr have much more restrictive addressing modes (just a
1363 // register).
1364 if (isStrongerThanMonotonic(cast<MemSDNode>(User)->getSuccessOrdering()))
1365 return false;
1366 }
1367
1368 return true;
1369}
1370
1371/// Check if the immediate offset is valid as a scaled immediate.
1372static bool isValidAsScaledImmediate(int64_t Offset, unsigned Range,
1373 unsigned Size) {
1374 if ((Offset & (Size - 1)) == 0 && Offset >= 0 &&
1375 Offset < (Range << Log2_32(Size)))
1376 return true;
1377 return false;
1378}
1379
1380/// SelectAddrModeIndexedBitWidth - Select a "register plus scaled (un)signed BW-bit
1381/// immediate" address. The "Size" argument is the size in bytes of the memory
1382/// reference, which determines the scale.
1383bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(SDValue N, bool IsSignedImm,
1384 unsigned BW, unsigned Size,
1385 SDValue &Base,
1386 SDValue &OffImm) {
1387 SDLoc dl(N);
1388 const DataLayout &DL = CurDAG->getDataLayout();
1389 const TargetLowering *TLI = getTargetLowering();
1390 if (N.getOpcode() == ISD::FrameIndex) {
1391 int FI = cast<FrameIndexSDNode>(N)->getIndex();
1392 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
1393 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1394 return true;
1395 }
1396
1397 // As opposed to the (12-bit) Indexed addressing mode below, the 7/9-bit signed
1398 // selected here doesn't support labels/immediates, only base+offset.
1399 if (CurDAG->isBaseWithConstantOffset(N)) {
1400 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1401 if (IsSignedImm) {
1402 int64_t RHSC = RHS->getSExtValue();
1403 unsigned Scale = Log2_32(Size);
1404 int64_t Range = 0x1LL << (BW - 1);
1405
1406 if ((RHSC & (Size - 1)) == 0 && RHSC >= -(Range << Scale) &&
1407 RHSC < (Range << Scale)) {
1408 Base = N.getOperand(0);
1409 if (Base.getOpcode() == ISD::FrameIndex) {
1410 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1411 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
1412 }
1413 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1414 return true;
1415 }
1416 } else {
1417 // unsigned Immediate
1418 uint64_t RHSC = RHS->getZExtValue();
1419 unsigned Scale = Log2_32(Size);
1420 uint64_t Range = 0x1ULL << BW;
1421
1422 if ((RHSC & (Size - 1)) == 0 && RHSC < (Range << Scale)) {
1423 Base = N.getOperand(0);
1424 if (Base.getOpcode() == ISD::FrameIndex) {
1425 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1426 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
1427 }
1428 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1429 return true;
1430 }
1431 }
1432 }
1433 }
1434 // Base only. The address will be materialized into a register before
1435 // the memory is accessed.
1436 // add x0, Xbase, #offset
1437 // stp x1, x2, [x0]
1438 Base = N;
1439 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1440 return true;
1441}
1442
1443/// SelectAddrModeIndexed - Select a "register plus scaled unsigned 12-bit
1444/// immediate" address. The "Size" argument is the size in bytes of the memory
1445/// reference, which determines the scale.
1446bool AArch64DAGToDAGISel::SelectAddrModeIndexed(SDValue N, unsigned Size,
1447 SDValue &Base, SDValue &OffImm) {
1448 SDLoc dl(N);
1449 const DataLayout &DL = CurDAG->getDataLayout();
1450 const TargetLowering *TLI = getTargetLowering();
1451 if (N.getOpcode() == ISD::FrameIndex) {
1452 int FI = cast<FrameIndexSDNode>(N)->getIndex();
1453 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
1454 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1455 return true;
1456 }
1457
1458 if (N.getOpcode() == AArch64ISD::ADDlow && isWorthFoldingADDlow(N)) {
1459 GlobalAddressSDNode *GAN =
1460 dyn_cast<GlobalAddressSDNode>(N.getOperand(1).getNode());
1461 Base = N.getOperand(0);
1462 OffImm = N.getOperand(1);
1463 if (!GAN)
1464 return true;
1465
1466 if (GAN->getOffset() % Size == 0 &&
1468 return true;
1469 }
1470
1471 if (CurDAG->isBaseWithConstantOffset(N)) {
1472 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1473 int64_t RHSC = (int64_t)RHS->getZExtValue();
1474 unsigned Scale = Log2_32(Size);
1475 if (isValidAsScaledImmediate(RHSC, 0x1000, Size)) {
1476 Base = N.getOperand(0);
1477 if (Base.getOpcode() == ISD::FrameIndex) {
1478 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1479 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
1480 }
1481 OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
1482 return true;
1483 }
1484 }
1485 }
1486
1487 // Before falling back to our general case, check if the unscaled
1488 // instructions can handle this. If so, that's preferable.
1489 if (SelectAddrModeUnscaled(N, Size, Base, OffImm))
1490 return false;
1491
1492 // Base only. The address will be materialized into a register before
1493 // the memory is accessed.
1494 // add x0, Xbase, #offset
1495 // ldr x0, [x0]
1496 Base = N;
1497 OffImm = CurDAG->getTargetConstant(0, dl, MVT::i64);
1498 return true;
1499}
1500
1501/// SelectAddrModeUnscaled - Select a "register plus unscaled signed 9-bit
1502/// immediate" address. This should only match when there is an offset that
1503/// is not valid for a scaled immediate addressing mode. The "Size" argument
1504/// is the size in bytes of the memory reference, which is needed here to know
1505/// what is valid for a scaled immediate.
1506bool AArch64DAGToDAGISel::SelectAddrModeUnscaled(SDValue N, unsigned Size,
1507 SDValue &Base,
1508 SDValue &OffImm) {
1509 if (!CurDAG->isBaseWithConstantOffset(N))
1510 return false;
1511 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
1512 int64_t RHSC = RHS->getSExtValue();
1513 if (RHSC >= -256 && RHSC < 256) {
1514 Base = N.getOperand(0);
1515 if (Base.getOpcode() == ISD::FrameIndex) {
1516 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
1517 const TargetLowering *TLI = getTargetLowering();
1518 Base = CurDAG->getTargetFrameIndex(
1519 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
1520 }
1521 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i64);
1522 return true;
1523 }
1524 }
1525 return false;
1526}
1527
1529 SDLoc dl(N);
1530 SDValue ImpDef = SDValue(
1531 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::i64), 0);
1532 return CurDAG->getTargetInsertSubreg(AArch64::sub_32, dl, MVT::i64, ImpDef,
1533 N);
1534}
1535
1536/// Check if the given SHL node (\p N), can be used to form an
1537/// extended register for an addressing mode.
1538bool AArch64DAGToDAGISel::SelectExtendedSHL(SDValue N, unsigned Size,
1539 bool WantExtend, SDValue &Offset,
1540 SDValue &SignExtend) {
1541 assert(N.getOpcode() == ISD::SHL && "Invalid opcode.");
1542 ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1));
1543 if (!CSD || (CSD->getZExtValue() & 0x7) != CSD->getZExtValue())
1544 return false;
1545
1546 SDLoc dl(N);
1547 if (WantExtend) {
1549 getExtendTypeForNode(N.getOperand(0), true);
1551 return false;
1552
1553 Offset = narrowIfNeeded(CurDAG, N.getOperand(0).getOperand(0));
1554 SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl,
1555 MVT::i32);
1556 } else {
1557 Offset = N.getOperand(0);
1558 SignExtend = CurDAG->getTargetConstant(0, dl, MVT::i32);
1559 }
1560
1561 unsigned LegalShiftVal = Log2_32(Size);
1562 unsigned ShiftVal = CSD->getZExtValue();
1563
1564 if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
1565 return false;
1566
1567 return isWorthFoldingAddr(N, Size);
1568}
1569
1570bool AArch64DAGToDAGISel::SelectAddrModeWRO(SDValue N, unsigned Size,
1571 SDValue &Base, SDValue &Offset,
1572 SDValue &SignExtend,
1573 SDValue &DoShift) {
1574 if (N.getOpcode() != ISD::ADD)
1575 return false;
1576 SDValue LHS = N.getOperand(0);
1577 SDValue RHS = N.getOperand(1);
1578 SDLoc dl(N);
1579
1580 // We don't want to match immediate adds here, because they are better lowered
1581 // to the register-immediate addressing modes.
1583 return false;
1584
1585 // Check if this particular node is reused in any non-memory related
1586 // operation. If yes, do not try to fold this node into the address
1587 // computation, since the computation will be kept.
1588 const SDNode *Node = N.getNode();
1589 for (SDNode *UI : Node->users()) {
1590 if (!isMemOpOrPrefetch(UI))
1591 return false;
1592 }
1593
1594 // Remember if it is worth folding N when it produces extended register.
1595 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(N, Size);
1596
1597 // Try to match a shifted extend on the RHS.
1598 if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL &&
1599 SelectExtendedSHL(RHS, Size, true, Offset, SignExtend)) {
1600 Base = LHS;
1601 DoShift = CurDAG->getTargetConstant(true, dl, MVT::i32);
1602 return true;
1603 }
1604
1605 // Try to match a shifted extend on the LHS.
1606 if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL &&
1607 SelectExtendedSHL(LHS, Size, true, Offset, SignExtend)) {
1608 Base = RHS;
1609 DoShift = CurDAG->getTargetConstant(true, dl, MVT::i32);
1610 return true;
1611 }
1612
1613 // There was no shift, whatever else we find.
1614 DoShift = CurDAG->getTargetConstant(false, dl, MVT::i32);
1615
1617 // Try to match an unshifted extend on the LHS.
1618 if (IsExtendedRegisterWorthFolding &&
1619 (Ext = getExtendTypeForNode(LHS, true)) !=
1621 Base = RHS;
1622 Offset = narrowIfNeeded(CurDAG, LHS.getOperand(0));
1623 SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl,
1624 MVT::i32);
1625 if (isWorthFoldingAddr(LHS, Size))
1626 return true;
1627 }
1628
1629 // Try to match an unshifted extend on the RHS.
1630 if (IsExtendedRegisterWorthFolding &&
1631 (Ext = getExtendTypeForNode(RHS, true)) !=
1633 Base = LHS;
1634 Offset = narrowIfNeeded(CurDAG, RHS.getOperand(0));
1635 SignExtend = CurDAG->getTargetConstant(Ext == AArch64_AM::SXTW, dl,
1636 MVT::i32);
1637 if (isWorthFoldingAddr(RHS, Size))
1638 return true;
1639 }
1640
1641 return false;
1642}
1643
1644// Check if the given immediate is preferred by ADD. If an immediate can be
1645// encoded in an ADD, or it can be encoded in an "ADD LSL #12" and can not be
1646// encoded by one MOVZ, return true.
1647static bool isPreferredADD(int64_t ImmOff) {
1648 // Constant in [0x0, 0xfff] can be encoded in ADD.
1649 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
1650 return true;
1651 // Check if it can be encoded in an "ADD LSL #12".
1652 if ((ImmOff & 0xffffffffff000fffLL) == 0x0LL)
1653 // As a single MOVZ is faster than a "ADD of LSL #12", ignore such constant.
1654 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
1655 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
1656 return false;
1657}
1658
1659bool AArch64DAGToDAGISel::SelectAddrModeXRO(SDValue N, unsigned Size,
1660 SDValue &Base, SDValue &Offset,
1661 SDValue &SignExtend,
1662 SDValue &DoShift) {
1663 if (N.getOpcode() != ISD::ADD)
1664 return false;
1665 SDValue LHS = N.getOperand(0);
1666 SDValue RHS = N.getOperand(1);
1667 SDLoc DL(N);
1668
1669 // Check if this particular node is reused in any non-memory related
1670 // operation. If yes, do not try to fold this node into the address
1671 // computation, since the computation will be kept.
1672 const SDNode *Node = N.getNode();
1673 for (SDNode *UI : Node->users()) {
1674 if (!isMemOpOrPrefetch(UI))
1675 return false;
1676 }
1677
1678 // Watch out if RHS is a wide immediate, it can not be selected into
1679 // [BaseReg+Imm] addressing mode. Also it may not be able to be encoded into
1680 // ADD/SUB. Instead it will use [BaseReg + 0] address mode and generate
1681 // instructions like:
1682 // MOV X0, WideImmediate
1683 // ADD X1, BaseReg, X0
1684 // LDR X2, [X1, 0]
1685 // For such situation, using [BaseReg, XReg] addressing mode can save one
1686 // ADD/SUB:
1687 // MOV X0, WideImmediate
1688 // LDR X2, [BaseReg, X0]
1689 if (isa<ConstantSDNode>(RHS)) {
1690 int64_t ImmOff = (int64_t)RHS->getAsZExtVal();
1691 // Skip the immediate can be selected by load/store addressing mode.
1692 // Also skip the immediate can be encoded by a single ADD (SUB is also
1693 // checked by using -ImmOff).
1694 if (isValidAsScaledImmediate(ImmOff, 0x1000, Size) ||
1695 isPreferredADD(ImmOff) || isPreferredADD(-ImmOff))
1696 return false;
1697
1698 SDValue Ops[] = { RHS };
1699 SDNode *MOVI =
1700 CurDAG->getMachineNode(AArch64::MOVi64imm, DL, MVT::i64, Ops);
1701 SDValue MOVIV = SDValue(MOVI, 0);
1702 // This ADD of two X register will be selected into [Reg+Reg] mode.
1703 N = CurDAG->getNode(ISD::ADD, DL, MVT::i64, LHS, MOVIV);
1704 }
1705
1706 // Remember if it is worth folding N when it produces extended register.
1707 bool IsExtendedRegisterWorthFolding = isWorthFoldingAddr(N, Size);
1708
1709 // Try to match a shifted extend on the RHS.
1710 if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL &&
1711 SelectExtendedSHL(RHS, Size, false, Offset, SignExtend)) {
1712 Base = LHS;
1713 DoShift = CurDAG->getTargetConstant(true, DL, MVT::i32);
1714 return true;
1715 }
1716
1717 // Try to match a shifted extend on the LHS.
1718 if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL &&
1719 SelectExtendedSHL(LHS, Size, false, Offset, SignExtend)) {
1720 Base = RHS;
1721 DoShift = CurDAG->getTargetConstant(true, DL, MVT::i32);
1722 return true;
1723 }
1724
1725 // Match any non-shifted, non-extend, non-immediate add expression.
1726 Base = LHS;
1727 Offset = RHS;
1728 SignExtend = CurDAG->getTargetConstant(false, DL, MVT::i32);
1729 DoShift = CurDAG->getTargetConstant(false, DL, MVT::i32);
1730 // Reg1 + Reg2 is free: no check needed.
1731 return true;
1732}
1733
1734SDValue AArch64DAGToDAGISel::createDTuple(ArrayRef<SDValue> Regs) {
1735 static const unsigned RegClassIDs[] = {
1736 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
1737 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
1738 AArch64::dsub2, AArch64::dsub3};
1739
1740 return createTuple(Regs, RegClassIDs, SubRegs);
1741}
1742
1743SDValue AArch64DAGToDAGISel::createQTuple(ArrayRef<SDValue> Regs) {
1744 static const unsigned RegClassIDs[] = {
1745 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
1746 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
1747 AArch64::qsub2, AArch64::qsub3};
1748
1749 return createTuple(Regs, RegClassIDs, SubRegs);
1750}
1751
1752SDValue AArch64DAGToDAGISel::createZTuple(ArrayRef<SDValue> Regs) {
1753 static const unsigned RegClassIDs[] = {AArch64::ZPR2RegClassID,
1754 AArch64::ZPR3RegClassID,
1755 AArch64::ZPR4RegClassID};
1756 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1757 AArch64::zsub2, AArch64::zsub3};
1758
1759 return createTuple(Regs, RegClassIDs, SubRegs);
1760}
1761
1762SDValue AArch64DAGToDAGISel::createZMulTuple(ArrayRef<SDValue> Regs) {
1763 assert(Regs.size() == 2 || Regs.size() == 4);
1764
1765 // The createTuple interface requires 3 RegClassIDs for each possible
1766 // tuple type even though we only have them for ZPR2 and ZPR4.
1767 static const unsigned RegClassIDs[] = {AArch64::ZPR2Mul2RegClassID, 0,
1768 AArch64::ZPR4Mul4RegClassID};
1769 static const unsigned SubRegs[] = {AArch64::zsub0, AArch64::zsub1,
1770 AArch64::zsub2, AArch64::zsub3};
1771 return createTuple(Regs, RegClassIDs, SubRegs);
1772}
1773
1774SDValue AArch64DAGToDAGISel::createTuple(ArrayRef<SDValue> Regs,
1775 const unsigned RegClassIDs[],
1776 const unsigned SubRegs[]) {
1777 // There's no special register-class for a vector-list of 1 element: it's just
1778 // a vector.
1779 if (Regs.size() == 1)
1780 return Regs[0];
1781
1782 assert(Regs.size() >= 2 && Regs.size() <= 4);
1783
1784 SDLoc DL(Regs[0]);
1785
1787
1788 // First operand of REG_SEQUENCE is the desired RegClass.
1789 Ops.push_back(
1790 CurDAG->getTargetConstant(RegClassIDs[Regs.size() - 2], DL, MVT::i32));
1791
1792 // Then we get pairs of source & subregister-position for the components.
1793 for (unsigned i = 0; i < Regs.size(); ++i) {
1794 Ops.push_back(Regs[i]);
1795 Ops.push_back(CurDAG->getTargetConstant(SubRegs[i], DL, MVT::i32));
1796 }
1797
1798 SDNode *N =
1799 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, MVT::Untyped, Ops);
1800 return SDValue(N, 0);
1801}
1802
1803void AArch64DAGToDAGISel::SelectTable(SDNode *N, unsigned NumVecs, unsigned Opc,
1804 bool isExt) {
1805 SDLoc dl(N);
1806 EVT VT = N->getValueType(0);
1807
1808 unsigned ExtOff = isExt;
1809
1810 // Form a REG_SEQUENCE to force register allocation.
1811 unsigned Vec0Off = ExtOff + 1;
1812 SmallVector<SDValue, 4> Regs(N->ops().slice(Vec0Off, NumVecs));
1813 SDValue RegSeq = createQTuple(Regs);
1814
1816 if (isExt)
1817 Ops.push_back(N->getOperand(1));
1818 Ops.push_back(RegSeq);
1819 Ops.push_back(N->getOperand(NumVecs + ExtOff + 1));
1820 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops));
1821}
1822
1823static std::tuple<SDValue, SDValue>
1825 SDLoc DL(Disc);
1826 SDValue AddrDisc;
1827 SDValue ConstDisc;
1828
1829 // If this is a blend, remember the constant and address discriminators.
1830 // Otherwise, it's either a constant discriminator, or a non-blended
1831 // address discriminator.
1832 if (Disc->getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
1833 Disc->getConstantOperandVal(0) == Intrinsic::ptrauth_blend) {
1834 AddrDisc = Disc->getOperand(1);
1835 ConstDisc = Disc->getOperand(2);
1836 } else {
1837 ConstDisc = Disc;
1838 }
1839
1840 // If the constant discriminator (either the blend RHS, or the entire
1841 // discriminator value) isn't a 16-bit constant, bail out, and let the
1842 // discriminator be computed separately.
1843 auto *ConstDiscN = dyn_cast<ConstantSDNode>(ConstDisc);
1844 if (!ConstDiscN || !isUInt<16>(ConstDiscN->getZExtValue()))
1845 return std::make_tuple(DAG->getTargetConstant(0, DL, MVT::i64), Disc);
1846
1847 // If there's no address discriminator, use XZR directly.
1848 if (!AddrDisc)
1849 AddrDisc = DAG->getRegister(AArch64::XZR, MVT::i64);
1850
1851 return std::make_tuple(
1852 DAG->getTargetConstant(ConstDiscN->getZExtValue(), DL, MVT::i64),
1853 AddrDisc);
1854}
1855
1856void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) {
1857 SDLoc DL(N);
1858 // IntrinsicID is operand #0
1859 SDValue Val = N->getOperand(1);
1860 SDValue AUTKey = N->getOperand(2);
1861 SDValue AUTDisc = N->getOperand(3);
1862
1863 unsigned AUTKeyC = cast<ConstantSDNode>(AUTKey)->getZExtValue();
1864 AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64);
1865
1866 SDValue AUTAddrDisc, AUTConstDisc;
1867 std::tie(AUTConstDisc, AUTAddrDisc) =
1868 extractPtrauthBlendDiscriminators(AUTDisc, CurDAG);
1869
1870 if (!Subtarget->isX16X17Safer()) {
1871 std::vector<SDValue> Ops = {Val, AUTKey, AUTConstDisc, AUTAddrDisc};
1872 // Copy deactivation symbol if present.
1873 if (N->getNumOperands() > 4)
1874 Ops.push_back(N->getOperand(4));
1875
1876 SDNode *AUT =
1877 CurDAG->getMachineNode(AArch64::AUTxMxN, DL, MVT::i64, MVT::i64, Ops);
1878 ReplaceNode(N, AUT);
1879 } else {
1880 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL,
1881 AArch64::X16, Val, SDValue());
1882 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.getValue(1)};
1883
1884 SDNode *AUT = CurDAG->getMachineNode(AArch64::AUTx16x17, DL, MVT::i64, Ops);
1885 ReplaceNode(N, AUT);
1886 }
1887}
1888
1889void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *N) {
1890 SDLoc DL(N);
1891 // IntrinsicID is operand #0, if W_CHAIN it is #1
1892 int OffsetBase = N->getOpcode() == ISD::INTRINSIC_W_CHAIN ? 1 : 0;
1893 SDValue Val = N->getOperand(OffsetBase + 1);
1894 SDValue AUTKey = N->getOperand(OffsetBase + 2);
1895 SDValue AUTDisc = N->getOperand(OffsetBase + 3);
1896 SDValue PACKey = N->getOperand(OffsetBase + 4);
1897 SDValue PACDisc = N->getOperand(OffsetBase + 5);
1898 uint32_t IntNum = N->getConstantOperandVal(OffsetBase + 0);
1899 bool HasLoad = IntNum == Intrinsic::ptrauth_resign_load_relative;
1900
1901 unsigned AUTKeyC = cast<ConstantSDNode>(AUTKey)->getZExtValue();
1902 unsigned PACKeyC = cast<ConstantSDNode>(PACKey)->getZExtValue();
1903
1904 AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64);
1905 PACKey = CurDAG->getTargetConstant(PACKeyC, DL, MVT::i64);
1906
1907 SDValue AUTAddrDisc, AUTConstDisc;
1908 std::tie(AUTConstDisc, AUTAddrDisc) =
1909 extractPtrauthBlendDiscriminators(AUTDisc, CurDAG);
1910
1911 SDValue PACAddrDisc, PACConstDisc;
1912 std::tie(PACConstDisc, PACAddrDisc) =
1913 extractPtrauthBlendDiscriminators(PACDisc, CurDAG);
1914
1915 SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL,
1916 AArch64::X16, Val, SDValue());
1917
1918 if (HasLoad) {
1919 SDValue Addend = N->getOperand(OffsetBase + 6);
1920 SDValue IncomingChain = N->getOperand(0);
1921 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc,
1922 PACKey, PACConstDisc, PACAddrDisc,
1923 Addend, IncomingChain, X16Copy.getValue(1)};
1924
1925 SDNode *AUTRELLOADPAC = CurDAG->getMachineNode(AArch64::AUTRELLOADPAC, DL,
1926 MVT::i64, MVT::Other, Ops);
1927 ReplaceNode(N, AUTRELLOADPAC);
1928 } else {
1929 SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey,
1930 PACConstDisc, PACAddrDisc, X16Copy.getValue(1)};
1931
1932 SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC, DL, MVT::i64, Ops);
1933 ReplaceNode(N, AUTPAC);
1934 }
1935}
1936
1937void AArch64DAGToDAGISel::SelectPtrauthResignWithPC(SDNode *N) {
1938 SDLoc DL(N);
1939 SDValue Val = N->getOperand(1);
1940 SDValue AUTKey = N->getOperand(2);
1941 SDValue AUTDisc = N->getOperand(3);
1942 SDValue AUTPC = N->getOperand(4);
1943 SDValue PACKey = N->getOperand(5);
1944 SDValue PACDisc = N->getOperand(6);
1945
1946 unsigned AUTKeyC = cast<ConstantSDNode>(AUTKey)->getZExtValue();
1947 unsigned PACKeyC = cast<ConstantSDNode>(PACKey)->getZExtValue();
1948
1949 AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64);
1950 PACKey = CurDAG->getTargetConstant(PACKeyC, DL, MVT::i64);
1951
1952 SDValue PACAddrDisc, PACConstDisc;
1953 std::tie(PACConstDisc, PACAddrDisc) =
1954 extractPtrauthBlendDiscriminators(PACDisc, CurDAG);
1955
1956 SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL,
1957 AArch64::X17, Val, SDValue());
1958 SDValue X16Copy = CurDAG->getCopyToReg(
1959 CurDAG->getEntryNode(), DL, AArch64::X16, AUTDisc, X17Copy.getValue(1));
1960 SDValue X15Copy = CurDAG->getCopyToReg(
1961 CurDAG->getEntryNode(), DL, AArch64::X15, AUTPC, X16Copy.getValue(1));
1962
1963 SDValue Ops[] = {AUTKey, PACKey, PACConstDisc, PACAddrDisc,
1964 X15Copy.getValue(1)};
1965 SDNode *AUTPCPAC =
1966 CurDAG->getMachineNode(AArch64::AUTPCPAC, DL, MVT::i64, Ops);
1967 ReplaceNode(N, AUTPCPAC);
1968}
1969
1970bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *N) {
1971 LoadSDNode *LD = cast<LoadSDNode>(N);
1972 if (LD->isUnindexed())
1973 return false;
1974 EVT VT = LD->getMemoryVT();
1975 EVT DstVT = N->getValueType(0);
1976 ISD::MemIndexedMode AM = LD->getAddressingMode();
1977 bool IsPre = AM == ISD::PRE_INC || AM == ISD::PRE_DEC;
1978 ConstantSDNode *OffsetOp = cast<ConstantSDNode>(LD->getOffset());
1979 int OffsetVal = (int)OffsetOp->getZExtValue();
1980
1981 // We're not doing validity checking here. That was done when checking
1982 // if we should mark the load as indexed or not. We're just selecting
1983 // the right instruction.
1984 unsigned Opcode = 0;
1985
1986 ISD::LoadExtType ExtType = LD->getExtensionType();
1987 bool InsertTo64 = false;
1988 bool UseLd1 =
1989 (VT.is64BitVector() || VT.is128BitVector()) &&
1990 (!Subtarget->isLittleEndian() || (Subtarget->requiresStrictAlign() &&
1991 LD->getAlign() < VT.getStoreSize()));
1992 if (VT == MVT::i64)
1993 Opcode = IsPre ? AArch64::LDRXpre : AArch64::LDRXpost;
1994 else if (VT == MVT::i32) {
1995 if (ExtType == ISD::NON_EXTLOAD)
1996 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
1997 else if (ExtType == ISD::SEXTLOAD)
1998 Opcode = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
1999 else {
2000 Opcode = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
2001 InsertTo64 = true;
2002 // The result of the load is only i32. It's the subreg_to_reg that makes
2003 // it into an i64.
2004 DstVT = MVT::i32;
2005 }
2006 } else if (VT == MVT::i16) {
2007 if (ExtType == ISD::SEXTLOAD) {
2008 if (DstVT == MVT::i64)
2009 Opcode = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
2010 else
2011 Opcode = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
2012 } else {
2013 Opcode = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
2014 InsertTo64 = DstVT == MVT::i64;
2015 // The result of the load is only i32. It's the subreg_to_reg that makes
2016 // it into an i64.
2017 DstVT = MVT::i32;
2018 }
2019 } else if (VT == MVT::i8) {
2020 if (ExtType == ISD::SEXTLOAD) {
2021 if (DstVT == MVT::i64)
2022 Opcode = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
2023 else
2024 Opcode = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
2025 } else {
2026 Opcode = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
2027 InsertTo64 = DstVT == MVT::i64;
2028 // The result of the load is only i32. It's the subreg_to_reg that makes
2029 // it into an i64.
2030 DstVT = MVT::i32;
2031 }
2032 } else if (VT == MVT::f16) {
2033 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
2034 } else if (VT == MVT::bf16) {
2035 Opcode = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
2036 } else if (VT == MVT::f32) {
2037 Opcode = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
2038 } else if (VT == MVT::f64 || (VT.is64BitVector() && !UseLd1)) {
2039 Opcode = IsPre ? AArch64::LDRDpre : AArch64::LDRDpost;
2040 } else if (VT.is128BitVector() && !UseLd1) {
2041 Opcode = IsPre ? AArch64::LDRQpre : AArch64::LDRQpost;
2042 } else if (VT.is64BitVector() && UseLd1) {
2043 if (IsPre || OffsetVal != 8)
2044 return false;
2045 switch (VT.getScalarSizeInBits()) {
2046 case 8:
2047 Opcode = AArch64::LD1Onev8b_POST;
2048 break;
2049 case 16:
2050 Opcode = AArch64::LD1Onev4h_POST;
2051 break;
2052 case 32:
2053 Opcode = AArch64::LD1Onev2s_POST;
2054 break;
2055 case 64:
2056 Opcode = AArch64::LD1Onev1d_POST;
2057 break;
2058 default:
2059 llvm_unreachable("Expected vector element to be a power of 2");
2060 }
2061 } else if (VT.is128BitVector() && UseLd1) {
2062 if (IsPre || OffsetVal != 16)
2063 return false;
2064 switch (VT.getScalarSizeInBits()) {
2065 case 8:
2066 Opcode = AArch64::LD1Onev16b_POST;
2067 break;
2068 case 16:
2069 Opcode = AArch64::LD1Onev8h_POST;
2070 break;
2071 case 32:
2072 Opcode = AArch64::LD1Onev4s_POST;
2073 break;
2074 case 64:
2075 Opcode = AArch64::LD1Onev2d_POST;
2076 break;
2077 default:
2078 llvm_unreachable("Expected vector element to be a power of 2");
2079 }
2080 } else
2081 return false;
2082 SDValue Chain = LD->getChain();
2083 SDValue Base = LD->getBasePtr();
2084 SDLoc dl(N);
2085 // LD1 encodes an immediate offset by using XZR as the offset register.
2086 SDValue Offset = UseLd1 ? CurDAG->getRegister(AArch64::XZR, MVT::i64)
2087 : CurDAG->getTargetConstant(OffsetVal, dl, MVT::i64);
2088 SDValue Ops[] = { Base, Offset, Chain };
2089 SDNode *Res = CurDAG->getMachineNode(Opcode, dl, MVT::i64, DstVT,
2090 MVT::Other, Ops);
2091
2092 // Transfer memoperands.
2093 MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand();
2094 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Res), {MemOp});
2095
2096 // Either way, we're replacing the node, so tell the caller that.
2097 SDValue LoadedVal = SDValue(Res, 1);
2098 if (InsertTo64) {
2099 SDValue SubReg = CurDAG->getTargetConstant(AArch64::sub_32, dl, MVT::i32);
2100 LoadedVal = SDValue(CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, dl,
2101 MVT::i64, LoadedVal, SubReg),
2102 0);
2103 }
2104
2105 ReplaceUses(SDValue(N, 0), LoadedVal);
2106 ReplaceUses(SDValue(N, 1), SDValue(Res, 0));
2107 ReplaceUses(SDValue(N, 2), SDValue(Res, 2));
2108 CurDAG->RemoveDeadNode(N);
2109 return true;
2110}
2111
2112void AArch64DAGToDAGISel::SelectLoad(SDNode *N, unsigned NumVecs, unsigned Opc,
2113 unsigned SubRegIdx) {
2114 SDLoc dl(N);
2115 EVT VT = N->getValueType(0);
2116 SDValue Chain = N->getOperand(0);
2117
2118 SDValue Ops[] = {N->getOperand(2), // Mem operand;
2119 Chain};
2120
2121 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2122
2123 SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2124 SDValue SuperReg = SDValue(Ld, 0);
2125 for (unsigned i = 0; i < NumVecs; ++i)
2126 ReplaceUses(SDValue(N, i),
2127 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2128
2129 ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 1));
2130
2131 // Transfer memoperands. In the case of AArch64::LD64B, there won't be one,
2132 // because it's too simple to have needed special treatment during lowering.
2133 if (auto *MemIntr = dyn_cast<MemIntrinsicSDNode>(N)) {
2134 MachineMemOperand *MemOp = MemIntr->getMemOperand();
2135 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {MemOp});
2136 }
2137
2138 CurDAG->RemoveDeadNode(N);
2139}
2140
2141void AArch64DAGToDAGISel::SelectPostLoad(SDNode *N, unsigned NumVecs,
2142 unsigned Opc, unsigned SubRegIdx) {
2143 SDLoc dl(N);
2144 EVT VT = N->getValueType(0);
2145 SDValue Chain = N->getOperand(0);
2146
2147 SDValue Ops[] = {N->getOperand(1), // Mem operand
2148 N->getOperand(2), // Incremental
2149 Chain};
2150
2151 const EVT ResTys[] = {MVT::i64, // Type of the write back register
2152 MVT::Untyped, MVT::Other};
2153
2154 SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2155
2156 // Update uses of write back register
2157 ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 0));
2158
2159 // Update uses of vector list
2160 SDValue SuperReg = SDValue(Ld, 1);
2161 if (NumVecs == 1)
2162 ReplaceUses(SDValue(N, 0), SuperReg);
2163 else
2164 for (unsigned i = 0; i < NumVecs; ++i)
2165 ReplaceUses(SDValue(N, i),
2166 CurDAG->getTargetExtractSubreg(SubRegIdx + i, dl, VT, SuperReg));
2167
2168 // Transfer memoperands.
2169 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2170 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {MemOp});
2171
2172 // Update the chain
2173 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(Ld, 2));
2174 CurDAG->RemoveDeadNode(N);
2175}
2176
2177/// Optimize \param OldBase and \param OldOffset selecting the best addressing
2178/// mode. Returns a tuple consisting of an Opcode, an SDValue representing the
2179/// new Base and an SDValue representing the new offset.
2180std::tuple<unsigned, SDValue, SDValue>
2181AArch64DAGToDAGISel::findAddrModeSVELoadStore(SDNode *N, unsigned Opc_rr,
2182 unsigned Opc_ri,
2183 const SDValue &OldBase,
2184 const SDValue &OldOffset,
2185 unsigned Scale) {
2186 SDValue NewBase = OldBase;
2187 SDValue NewOffset = OldOffset;
2188 // Detect a possible Reg+Imm addressing mode.
2189 const bool IsRegImm = SelectAddrModeIndexedSVE</*Min=*/-8, /*Max=*/7>(
2190 N, OldBase, NewBase, NewOffset);
2191
2192 // Detect a possible reg+reg addressing mode, but only if we haven't already
2193 // detected a Reg+Imm one.
2194 const bool IsRegReg =
2195 !IsRegImm && SelectSVERegRegAddrMode(OldBase, Scale, NewBase, NewOffset);
2196
2197 // Select the instruction.
2198 return std::make_tuple(IsRegReg ? Opc_rr : Opc_ri, NewBase, NewOffset);
2199}
2200
2201enum class SelectTypeKind {
2202 Int1 = 0,
2203 Int = 1,
2204 FP = 2,
2206};
2207
2208/// This function selects an opcode from a list of opcodes, which is
2209/// expected to be the opcode for { 8-bit, 16-bit, 32-bit, 64-bit }
2210/// element types, in this order.
2211template <SelectTypeKind Kind>
2212static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef<unsigned> Opcodes) {
2213 // Only match scalable vector VTs
2214 if (!VT.isScalableVector())
2215 return 0;
2216
2217 EVT EltVT = VT.getVectorElementType();
2218 unsigned Key = VT.getVectorMinNumElements();
2219 switch (Kind) {
2221 break;
2223 if (EltVT != MVT::i8 && EltVT != MVT::i16 && EltVT != MVT::i32 &&
2224 EltVT != MVT::i64)
2225 return 0;
2226 break;
2228 if (EltVT != MVT::i1)
2229 return 0;
2230 break;
2231 case SelectTypeKind::FP:
2232 if (EltVT == MVT::bf16)
2233 Key = 16;
2234 else if (EltVT != MVT::bf16 && EltVT != MVT::f16 && EltVT != MVT::f32 &&
2235 EltVT != MVT::f64)
2236 return 0;
2237 break;
2238 }
2239
2240 unsigned Offset;
2241 switch (Key) {
2242 case 16: // 8-bit or bf16
2243 Offset = 0;
2244 break;
2245 case 8: // 16-bit
2246 Offset = 1;
2247 break;
2248 case 4: // 32-bit
2249 Offset = 2;
2250 break;
2251 case 2: // 64-bit
2252 Offset = 3;
2253 break;
2254 default:
2255 return 0;
2256 }
2257
2258 return (Opcodes.size() <= Offset) ? 0 : Opcodes[Offset];
2259}
2260
2261// This function is almost identical to SelectWhilePair, but has an
2262// extra check on the range of the immediate operand.
2263// TODO: Merge these two functions together at some point?
2264void AArch64DAGToDAGISel::SelectPExtPair(SDNode *N, unsigned Opc) {
2265 // Immediate can be either 0 or 1.
2266 if (ConstantSDNode *Imm = dyn_cast<ConstantSDNode>(N->getOperand(2)))
2267 if (Imm->getZExtValue() > 1)
2268 return;
2269
2270 SDLoc DL(N);
2271 EVT VT = N->getValueType(0);
2272 SDValue Ops[] = {N->getOperand(1), N->getOperand(2)};
2273 SDNode *WhilePair = CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Ops);
2274 SDValue SuperReg = SDValue(WhilePair, 0);
2275
2276 for (unsigned I = 0; I < 2; ++I)
2277 ReplaceUses(SDValue(N, I), CurDAG->getTargetExtractSubreg(
2278 AArch64::psub0 + I, DL, VT, SuperReg));
2279
2280 CurDAG->RemoveDeadNode(N);
2281}
2282
2283void AArch64DAGToDAGISel::SelectWhilePair(SDNode *N, unsigned Opc) {
2284 SDLoc DL(N);
2285 EVT VT = N->getValueType(0);
2286
2287 SDValue Ops[] = {N->getOperand(1), N->getOperand(2)};
2288
2289 SDNode *WhilePair = CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Ops);
2290 SDValue SuperReg = SDValue(WhilePair, 0);
2291
2292 for (unsigned I = 0; I < 2; ++I)
2293 ReplaceUses(SDValue(N, I), CurDAG->getTargetExtractSubreg(
2294 AArch64::psub0 + I, DL, VT, SuperReg));
2295
2296 CurDAG->RemoveDeadNode(N);
2297}
2298
2299void AArch64DAGToDAGISel::SelectCVTIntrinsic(SDNode *N, unsigned NumVecs,
2300 unsigned Opcode) {
2301 EVT VT = N->getValueType(0);
2302 SmallVector<SDValue, 4> Regs(N->ops().slice(1, NumVecs));
2303 SDValue Ops = createZTuple(Regs);
2304 SDLoc DL(N);
2305 SDNode *Intrinsic = CurDAG->getMachineNode(Opcode, DL, MVT::Untyped, Ops);
2306 SDValue SuperReg = SDValue(Intrinsic, 0);
2307 for (unsigned i = 0; i < NumVecs; ++i)
2308 ReplaceUses(SDValue(N, i), CurDAG->getTargetExtractSubreg(
2309 AArch64::zsub0 + i, DL, VT, SuperReg));
2310
2311 CurDAG->RemoveDeadNode(N);
2312}
2313
2314void AArch64DAGToDAGISel::SelectCVTIntrinsicFP8(SDNode *N, unsigned NumVecs,
2315 unsigned Opcode) {
2316 SDLoc DL(N);
2317 EVT VT = N->getValueType(0);
2318 SmallVector<SDValue, 4> Ops(N->op_begin() + 2, N->op_end());
2319 Ops.push_back(/*Chain*/ N->getOperand(0));
2320
2321 SDNode *Instruction =
2322 CurDAG->getMachineNode(Opcode, DL, {MVT::Untyped, MVT::Other}, Ops);
2323 SDValue SuperReg = SDValue(Instruction, 0);
2324
2325 for (unsigned i = 0; i < NumVecs; ++i)
2326 ReplaceUses(SDValue(N, i), CurDAG->getTargetExtractSubreg(
2327 AArch64::zsub0 + i, DL, VT, SuperReg));
2328
2329 // Copy chain
2330 unsigned ChainIdx = NumVecs;
2331 ReplaceUses(SDValue(N, ChainIdx), SDValue(Instruction, 1));
2332 CurDAG->RemoveDeadNode(N);
2333}
2334
2335void AArch64DAGToDAGISel::SelectDestructiveMultiIntrinsic(SDNode *N,
2336 unsigned NumVecs,
2337 bool IsZmMulti,
2338 unsigned Opcode,
2339 bool HasPred) {
2340 assert(Opcode != 0 && "Unexpected opcode");
2341
2342 SDLoc DL(N);
2343 EVT VT = N->getValueType(0);
2344 SDUse *OpsIter = N->op_begin() + 1; // Skip intrinsic ID
2346
2347 auto GetMultiVecOperand = [&]() {
2348 SmallVector<SDValue, 4> Regs(OpsIter, OpsIter + NumVecs);
2349 OpsIter += NumVecs;
2350 return createZMulTuple(Regs);
2351 };
2352
2353 if (HasPred)
2354 Ops.push_back(*OpsIter++);
2355
2356 Ops.push_back(GetMultiVecOperand());
2357 if (IsZmMulti)
2358 Ops.push_back(GetMultiVecOperand());
2359 else
2360 Ops.push_back(*OpsIter++);
2361
2362 // Append any remaining operands.
2363 Ops.append(OpsIter, N->op_end());
2364 SDNode *Intrinsic;
2365 Intrinsic = CurDAG->getMachineNode(Opcode, DL, MVT::Untyped, Ops);
2366 SDValue SuperReg = SDValue(Intrinsic, 0);
2367 for (unsigned i = 0; i < NumVecs; ++i)
2368 ReplaceUses(SDValue(N, i), CurDAG->getTargetExtractSubreg(
2369 AArch64::zsub0 + i, DL, VT, SuperReg));
2370
2371 CurDAG->RemoveDeadNode(N);
2372}
2373
2374void AArch64DAGToDAGISel::SelectPredicatedLoad(SDNode *N, unsigned NumVecs,
2375 unsigned Scale, unsigned Opc_ri,
2376 unsigned Opc_rr, bool IsIntr) {
2377 assert(Scale < 5 && "Invalid scaling value.");
2378 SDLoc DL(N);
2379 EVT VT = N->getValueType(0);
2380 SDValue Chain = N->getOperand(0);
2381
2382 // Optimize addressing mode.
2383 SDValue Base, Offset;
2384 unsigned Opc;
2385 std::tie(Opc, Base, Offset) = findAddrModeSVELoadStore(
2386 N, Opc_rr, Opc_ri, N->getOperand(IsIntr ? 3 : 2),
2387 CurDAG->getTargetConstant(0, DL, MVT::i64), Scale);
2388
2389 SDValue Ops[] = {N->getOperand(IsIntr ? 2 : 1), // Predicate
2390 Base, // Memory operand
2391 Offset, Chain};
2392
2393 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2394
2395 SDNode *Load = CurDAG->getMachineNode(Opc, DL, ResTys, Ops);
2396 SDValue SuperReg = SDValue(Load, 0);
2397 for (unsigned i = 0; i < NumVecs; ++i)
2398 ReplaceUses(SDValue(N, i), CurDAG->getTargetExtractSubreg(
2399 AArch64::zsub0 + i, DL, VT, SuperReg));
2400
2401 // Copy chain
2402 unsigned ChainIdx = NumVecs;
2403 ReplaceUses(SDValue(N, ChainIdx), SDValue(Load, 1));
2404 CurDAG->RemoveDeadNode(N);
2405}
2406
2407void AArch64DAGToDAGISel::SelectContiguousMultiVectorLoad(SDNode *N,
2408 unsigned NumVecs,
2409 unsigned Scale,
2410 unsigned Opc_ri,
2411 unsigned Opc_rr) {
2412 assert(Scale < 4 && "Invalid scaling value.");
2413 SDLoc DL(N);
2414 EVT VT = N->getValueType(0);
2415 SDValue Chain = N->getOperand(0);
2416
2417 SDValue PNg = N->getOperand(2);
2418 SDValue Base = N->getOperand(3);
2419 SDValue Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
2420 unsigned Opc;
2421 std::tie(Opc, Base, Offset) =
2422 findAddrModeSVELoadStore(N, Opc_rr, Opc_ri, Base, Offset, Scale);
2423
2424 SDValue Ops[] = {PNg, // Predicate-as-counter
2425 Base, // Memory operand
2426 Offset, Chain};
2427
2428 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2429
2430 SDNode *Load = CurDAG->getMachineNode(Opc, DL, ResTys, Ops);
2431 SDValue SuperReg = SDValue(Load, 0);
2432 for (unsigned i = 0; i < NumVecs; ++i)
2433 ReplaceUses(SDValue(N, i), CurDAG->getTargetExtractSubreg(
2434 AArch64::zsub0 + i, DL, VT, SuperReg));
2435
2436 // Copy chain
2437 unsigned ChainIdx = NumVecs;
2438 ReplaceUses(SDValue(N, ChainIdx), SDValue(Load, 1));
2439 CurDAG->RemoveDeadNode(N);
2440}
2441
2442void AArch64DAGToDAGISel::SelectFrintFromVT(SDNode *N, unsigned NumVecs,
2443 unsigned Opcode) {
2444 if (N->getValueType(0) != MVT::nxv4f32)
2445 return;
2446 SelectUnaryMultiIntrinsic(N, NumVecs, true, Opcode);
2447}
2448
2449void AArch64DAGToDAGISel::SelectMultiVectorLutiLane(SDNode *Node,
2450 unsigned NumOutVecs,
2451 unsigned Opc,
2452 uint32_t MaxImm) {
2453 if (ConstantSDNode *Imm = dyn_cast<ConstantSDNode>(Node->getOperand(4)))
2454 if (Imm->getZExtValue() > MaxImm)
2455 return;
2456
2457 SDValue ZtValue;
2458 if (!ImmToReg<AArch64::ZT0, 0>(Node->getOperand(2), ZtValue))
2459 return;
2460
2461 SDValue Chain = Node->getOperand(0);
2462 SDValue Ops[] = {ZtValue, Node->getOperand(3), Node->getOperand(4), Chain};
2463 SDLoc DL(Node);
2464 EVT VT = Node->getValueType(0);
2465
2466 SDNode *Instruction =
2467 CurDAG->getMachineNode(Opc, DL, {MVT::Untyped, MVT::Other}, Ops);
2468 SDValue SuperReg = SDValue(Instruction, 0);
2469
2470 for (unsigned I = 0; I < NumOutVecs; ++I)
2471 ReplaceUses(SDValue(Node, I), CurDAG->getTargetExtractSubreg(
2472 AArch64::zsub0 + I, DL, VT, SuperReg));
2473
2474 // Copy chain
2475 unsigned ChainIdx = NumOutVecs;
2476 ReplaceUses(SDValue(Node, ChainIdx), SDValue(Instruction, 1));
2477 CurDAG->RemoveDeadNode(Node);
2478}
2479
2480void AArch64DAGToDAGISel::SelectMultiVectorLuti6LaneX4(SDNode *Node,
2481 unsigned NumIndexVecs) {
2482 assert((NumIndexVecs == 2 || NumIndexVecs == 3) &&
2483 "unexpected number of index vectors");
2484
2485 constexpr unsigned FirstIndexOp = 3;
2486 unsigned ImmOp = FirstIndexOp + NumIndexVecs;
2487 auto *Imm = dyn_cast<ConstantSDNode>(Node->getOperand(ImmOp));
2488 if (!Imm || Imm->getZExtValue() > 1)
2489 return;
2490
2491 // The luti6 instruction always takes a 2-register Zm index tuple. The x3
2492 // ACLE form provides three index vectors, so the lane selects which adjacent
2493 // pair to use before forming Zm (op 3/4 or op 4/5, with op6 as imm)
2494 unsigned Lane = Imm->getZExtValue();
2495 unsigned IndexOp = FirstIndexOp;
2496 if (NumIndexVecs == 3)
2497 IndexOp += Lane;
2498
2499 SDValue TableTuple = createZTuple({Node->getOperand(1), Node->getOperand(2)});
2500 SDValue IndexTuple =
2501 createZTuple({Node->getOperand(IndexOp), Node->getOperand(IndexOp + 1)});
2502 SDValue Ops[] = {TableTuple, IndexTuple, Node->getOperand(ImmOp)};
2503
2504 SDLoc DL(Node);
2505 EVT VT = Node->getValueType(0);
2506 SDNode *Instruction =
2507 CurDAG->getMachineNode(AArch64::LUTI6_4Z2Z2ZI, DL, MVT::Untyped, Ops);
2508 SDValue SuperReg = SDValue(Instruction, 0);
2509
2510 for (unsigned I = 0; I < 4; ++I)
2511 ReplaceUses(SDValue(Node, I), CurDAG->getTargetExtractSubreg(
2512 AArch64::zsub0 + I, DL, VT, SuperReg));
2513
2514 CurDAG->RemoveDeadNode(Node);
2515}
2516
2517void AArch64DAGToDAGISel::SelectMultiVectorLuti(SDNode *Node,
2518 unsigned NumOutVecs,
2519 unsigned Opc,
2520 unsigned NumInVecs) {
2521 assert((NumInVecs == 2 || NumInVecs == 3) &&
2522 "unexpected number of input vectors");
2523
2524 SDValue ZtValue;
2525 if (!ImmToReg<AArch64::ZT0, 0>(Node->getOperand(2), ZtValue))
2526 return;
2527
2528 SmallVector<SDValue, 4> Regs(Node->ops().slice(3, NumInVecs));
2529 SDValue ZTuple = NumInVecs == 3 ? createZTuple(Regs) : createZMulTuple(Regs);
2530 SDValue Ops[] = {ZtValue, ZTuple, Node->getOperand(0)};
2531
2532 SDLoc DL(Node);
2533 EVT VT = Node->getValueType(0);
2534
2535 SDNode *Instruction =
2536 CurDAG->getMachineNode(Opc, DL, {MVT::Untyped, MVT::Other}, Ops);
2537 SDValue SuperReg = SDValue(Instruction, 0);
2538
2539 for (unsigned I = 0; I < NumOutVecs; ++I)
2540 ReplaceUses(SDValue(Node, I), CurDAG->getTargetExtractSubreg(
2541 AArch64::zsub0 + I, DL, VT, SuperReg));
2542
2543 ReplaceUses(SDValue(Node, NumOutVecs), SDValue(Instruction, 1));
2544 CurDAG->RemoveDeadNode(Node);
2545}
2546
2547void AArch64DAGToDAGISel::SelectClamp(SDNode *N, unsigned NumVecs,
2548 unsigned Op) {
2549 SDLoc DL(N);
2550 EVT VT = N->getValueType(0);
2551
2552 SmallVector<SDValue, 4> Regs(N->ops().slice(1, NumVecs));
2553 SDValue Zd = createZMulTuple(Regs);
2554 SDValue Zn = N->getOperand(1 + NumVecs);
2555 SDValue Zm = N->getOperand(2 + NumVecs);
2556
2557 SDValue Ops[] = {Zd, Zn, Zm};
2558
2559 SDNode *Intrinsic = CurDAG->getMachineNode(Op, DL, MVT::Untyped, Ops);
2560 SDValue SuperReg = SDValue(Intrinsic, 0);
2561 for (unsigned i = 0; i < NumVecs; ++i)
2562 ReplaceUses(SDValue(N, i), CurDAG->getTargetExtractSubreg(
2563 AArch64::zsub0 + i, DL, VT, SuperReg));
2564
2565 CurDAG->RemoveDeadNode(N);
2566}
2567
2568bool SelectSMETile(unsigned &BaseReg, unsigned TileNum) {
2569 switch (BaseReg) {
2570 default:
2571 return false;
2572 case AArch64::ZA:
2573 case AArch64::ZAB0:
2574 if (TileNum == 0)
2575 break;
2576 return false;
2577 case AArch64::ZAH0:
2578 if (TileNum <= 1)
2579 break;
2580 return false;
2581 case AArch64::ZAS0:
2582 if (TileNum <= 3)
2583 break;
2584 return false;
2585 case AArch64::ZAD0:
2586 if (TileNum <= 7)
2587 break;
2588 return false;
2589 }
2590
2591 BaseReg += TileNum;
2592 return true;
2593}
2594
2595template <unsigned MaxIdx, unsigned Scale>
2596void AArch64DAGToDAGISel::SelectMultiVectorMove(SDNode *N, unsigned NumVecs,
2597 unsigned BaseReg, unsigned Op) {
2598 unsigned TileNum = 0;
2599 if (BaseReg != AArch64::ZA)
2600 TileNum = N->getConstantOperandVal(2);
2601
2602 if (!SelectSMETile(BaseReg, TileNum))
2603 return;
2604
2605 SDValue SliceBase, Base, Offset;
2606 if (BaseReg == AArch64::ZA)
2607 SliceBase = N->getOperand(2);
2608 else
2609 SliceBase = N->getOperand(3);
2610
2611 if (!SelectSMETileSlice(SliceBase, MaxIdx, Base, Offset, Scale))
2612 return;
2613
2614 SDLoc DL(N);
2615 SDValue SubReg = CurDAG->getRegister(BaseReg, MVT::Other);
2616 SDValue Ops[] = {SubReg, Base, Offset, /*Chain*/ N->getOperand(0)};
2617 SDNode *Mov = CurDAG->getMachineNode(Op, DL, {MVT::Untyped, MVT::Other}, Ops);
2618
2619 EVT VT = N->getValueType(0);
2620 for (unsigned I = 0; I < NumVecs; ++I)
2621 ReplaceUses(SDValue(N, I),
2622 CurDAG->getTargetExtractSubreg(AArch64::zsub0 + I, DL, VT,
2623 SDValue(Mov, 0)));
2624 // Copy chain
2625 unsigned ChainIdx = NumVecs;
2626 ReplaceUses(SDValue(N, ChainIdx), SDValue(Mov, 1));
2627 CurDAG->RemoveDeadNode(N);
2628}
2629
2630void AArch64DAGToDAGISel::SelectMultiVectorMoveZ(SDNode *N, unsigned NumVecs,
2631 unsigned Op, unsigned MaxIdx,
2632 unsigned Scale, unsigned BaseReg) {
2633 // Slice can be in different positions
2634 // The array to vector: llvm.aarch64.sme.readz.<h/v>.<sz>(slice)
2635 // The tile to vector: llvm.aarch64.sme.readz.<h/v>.<sz>(tile, slice)
2636 SDValue SliceBase = N->getOperand(2);
2637 if (BaseReg != AArch64::ZA)
2638 SliceBase = N->getOperand(3);
2639
2640 SDValue Base, Offset;
2641 if (!SelectSMETileSlice(SliceBase, MaxIdx, Base, Offset, Scale))
2642 return;
2643 // The correct Za tile number is computed in Machine Instruction
2644 // See EmitZAInstr
2645 // DAG cannot select Za tile as an output register with ZReg
2646 SDLoc DL(N);
2648 if (BaseReg != AArch64::ZA )
2649 Ops.push_back(N->getOperand(2));
2650 Ops.push_back(Base);
2651 Ops.push_back(Offset);
2652 Ops.push_back(N->getOperand(0)); //Chain
2653 SDNode *Mov = CurDAG->getMachineNode(Op, DL, {MVT::Untyped, MVT::Other}, Ops);
2654
2655 EVT VT = N->getValueType(0);
2656 for (unsigned I = 0; I < NumVecs; ++I)
2657 ReplaceUses(SDValue(N, I),
2658 CurDAG->getTargetExtractSubreg(AArch64::zsub0 + I, DL, VT,
2659 SDValue(Mov, 0)));
2660
2661 // Copy chain
2662 unsigned ChainIdx = NumVecs;
2663 ReplaceUses(SDValue(N, ChainIdx), SDValue(Mov, 1));
2664 CurDAG->RemoveDeadNode(N);
2665}
2666
2667void AArch64DAGToDAGISel::SelectUnaryMultiIntrinsic(SDNode *N,
2668 unsigned NumOutVecs,
2669 bool IsTupleInput,
2670 unsigned Opc) {
2671 SDLoc DL(N);
2672 EVT VT = N->getValueType(0);
2673 unsigned NumInVecs = N->getNumOperands() - 1;
2674
2676 if (IsTupleInput) {
2677 assert((NumInVecs == 2 || NumInVecs == 4) &&
2678 "Don't know how to handle multi-register input!");
2679 SmallVector<SDValue, 4> Regs(N->ops().slice(1, NumInVecs));
2680 Ops.push_back(createZMulTuple(Regs));
2681 } else {
2682 // All intrinsic nodes have the ID as the first operand, hence the "1 + I".
2683 for (unsigned I = 0; I < NumInVecs; I++)
2684 Ops.push_back(N->getOperand(1 + I));
2685 }
2686
2687 SDNode *Res = CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Ops);
2688 SDValue SuperReg = SDValue(Res, 0);
2689
2690 for (unsigned I = 0; I < NumOutVecs; I++)
2691 ReplaceUses(SDValue(N, I), CurDAG->getTargetExtractSubreg(
2692 AArch64::zsub0 + I, DL, VT, SuperReg));
2693 CurDAG->RemoveDeadNode(N);
2694}
2695
2696void AArch64DAGToDAGISel::SelectStore(SDNode *N, unsigned NumVecs,
2697 unsigned Opc) {
2698 SDLoc dl(N);
2699 EVT VT = N->getOperand(2)->getValueType(0);
2700
2701 // Form a REG_SEQUENCE to force register allocation.
2702 bool Is128Bit = VT.getSizeInBits() == 128;
2703 SmallVector<SDValue, 4> Regs(N->ops().slice(2, NumVecs));
2704 SDValue RegSeq = Is128Bit ? createQTuple(Regs) : createDTuple(Regs);
2705
2706 SDValue Ops[] = {RegSeq, N->getOperand(NumVecs + 2), N->getOperand(0)};
2707 SDNode *St = CurDAG->getMachineNode(Opc, dl, N->getValueType(0), Ops);
2708
2709 // Transfer memoperands.
2710 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2711 CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
2712
2713 ReplaceNode(N, St);
2714}
2715
2716void AArch64DAGToDAGISel::SelectPredicatedStore(SDNode *N, unsigned NumVecs,
2717 unsigned Scale, unsigned Opc_rr,
2718 unsigned Opc_ri) {
2719 SDLoc dl(N);
2720
2721 // Form a REG_SEQUENCE to force register allocation.
2722 SmallVector<SDValue, 4> Regs(N->ops().slice(2, NumVecs));
2723 SDValue RegSeq = createZTuple(Regs);
2724
2725 // Optimize addressing mode.
2726 unsigned Opc;
2727 SDValue Offset, Base;
2728 std::tie(Opc, Base, Offset) = findAddrModeSVELoadStore(
2729 N, Opc_rr, Opc_ri, N->getOperand(NumVecs + 3),
2730 CurDAG->getTargetConstant(0, dl, MVT::i64), Scale);
2731
2732 SDValue Ops[] = {RegSeq, N->getOperand(NumVecs + 2), // predicate
2733 Base, // address
2734 Offset, // offset
2735 N->getOperand(0)}; // chain
2736 SDNode *St = CurDAG->getMachineNode(Opc, dl, N->getValueType(0), Ops);
2737
2738 // Transfer memoperands.
2739 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2740 CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
2741
2742 ReplaceNode(N, St);
2743}
2744
2745void AArch64DAGToDAGISel::SelectPostStore(SDNode *N, unsigned NumVecs,
2746 unsigned Opc) {
2747 SDLoc dl(N);
2748 EVT VT = N->getOperand(2)->getValueType(0);
2749 const EVT ResTys[] = {MVT::i64, // Type of the write back register
2750 MVT::Other}; // Type for the Chain
2751
2752 // Form a REG_SEQUENCE to force register allocation.
2753 bool Is128Bit = VT.getSizeInBits() == 128;
2754 SmallVector<SDValue, 4> Regs(N->ops().slice(1, NumVecs));
2755 SDValue RegSeq = Is128Bit ? createQTuple(Regs) : createDTuple(Regs);
2756
2757 SDValue Ops[] = {RegSeq,
2758 N->getOperand(NumVecs + 1), // base register
2759 N->getOperand(NumVecs + 2), // Incremental
2760 N->getOperand(0)}; // Chain
2761 SDNode *St = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2762
2763 // Transfer memoperands.
2764 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2765 CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
2766
2767 ReplaceNode(N, St);
2768}
2769
2770namespace {
2771/// WidenVector - Given a value in the V64 register class, produce the
2772/// equivalent value in the V128 register class.
2773class WidenVector {
2774 SelectionDAG &DAG;
2775
2776public:
2777 WidenVector(SelectionDAG &DAG) : DAG(DAG) {}
2778
2779 SDValue operator()(SDValue V64Reg) {
2780 EVT VT = V64Reg.getValueType();
2781 unsigned NarrowSize = VT.getVectorNumElements();
2782 MVT EltTy = VT.getVectorElementType().getSimpleVT();
2783 MVT WideTy = MVT::getVectorVT(EltTy, 2 * NarrowSize);
2784 SDLoc DL(V64Reg);
2785
2786 SDValue Undef =
2787 SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, WideTy), 0);
2788 return DAG.getTargetInsertSubreg(AArch64::dsub, DL, WideTy, Undef, V64Reg);
2789 }
2790};
2791} // namespace
2792
2793/// NarrowVector - Given a value in the V128 register class, produce the
2794/// equivalent value in the V64 register class.
2796 EVT VT = V128Reg.getValueType();
2797 unsigned WideSize = VT.getVectorNumElements();
2798 MVT EltTy = VT.getVectorElementType().getSimpleVT();
2799 MVT NarrowTy = MVT::getVectorVT(EltTy, WideSize / 2);
2800
2801 return DAG.getTargetExtractSubreg(AArch64::dsub, SDLoc(V128Reg), NarrowTy,
2802 V128Reg);
2803}
2804
2805void AArch64DAGToDAGISel::SelectLoadLane(SDNode *N, unsigned NumVecs,
2806 unsigned Opc) {
2807 SDLoc dl(N);
2808 EVT VT = N->getValueType(0);
2809 bool Narrow = VT.getSizeInBits() == 64;
2810
2811 // Form a REG_SEQUENCE to force register allocation.
2812 SmallVector<SDValue, 4> Regs(N->ops().slice(2, NumVecs));
2813
2814 if (Narrow)
2815 transform(Regs, Regs.begin(),
2816 WidenVector(*CurDAG));
2817
2818 SDValue RegSeq = createQTuple(Regs);
2819
2820 const EVT ResTys[] = {MVT::Untyped, MVT::Other};
2821
2822 unsigned LaneNo = N->getConstantOperandVal(NumVecs + 2);
2823
2824 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2825 N->getOperand(NumVecs + 3), N->getOperand(0)};
2826 SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2827 SDValue SuperReg = SDValue(Ld, 0);
2828
2829 EVT WideVT = RegSeq.getOperand(1)->getValueType(0);
2830 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2831 AArch64::qsub2, AArch64::qsub3 };
2832 for (unsigned i = 0; i < NumVecs; ++i) {
2833 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT, SuperReg);
2834 if (Narrow)
2835 NV = NarrowVector(NV, *CurDAG);
2836 ReplaceUses(SDValue(N, i), NV);
2837 }
2838
2839 ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 1));
2840 CurDAG->RemoveDeadNode(N);
2841}
2842
2843void AArch64DAGToDAGISel::SelectPostLoadLane(SDNode *N, unsigned NumVecs,
2844 unsigned Opc) {
2845 SDLoc dl(N);
2846 EVT VT = N->getValueType(0);
2847 bool Narrow = VT.getSizeInBits() == 64;
2848
2849 // Form a REG_SEQUENCE to force register allocation.
2850 SmallVector<SDValue, 4> Regs(N->ops().slice(1, NumVecs));
2851
2852 if (Narrow)
2853 transform(Regs, Regs.begin(),
2854 WidenVector(*CurDAG));
2855
2856 SDValue RegSeq = createQTuple(Regs);
2857
2858 const EVT ResTys[] = {MVT::i64, // Type of the write back register
2859 RegSeq->getValueType(0), MVT::Other};
2860
2861 unsigned LaneNo = N->getConstantOperandVal(NumVecs + 1);
2862
2863 SDValue Ops[] = {RegSeq,
2864 CurDAG->getTargetConstant(LaneNo, dl,
2865 MVT::i64), // Lane Number
2866 N->getOperand(NumVecs + 2), // Base register
2867 N->getOperand(NumVecs + 3), // Incremental
2868 N->getOperand(0)};
2869 SDNode *Ld = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2870
2871 // Update uses of the write back register
2872 ReplaceUses(SDValue(N, NumVecs), SDValue(Ld, 0));
2873
2874 // Update uses of the vector list
2875 SDValue SuperReg = SDValue(Ld, 1);
2876 if (NumVecs == 1) {
2877 ReplaceUses(SDValue(N, 0),
2878 Narrow ? NarrowVector(SuperReg, *CurDAG) : SuperReg);
2879 } else {
2880 EVT WideVT = RegSeq.getOperand(1)->getValueType(0);
2881 static const unsigned QSubs[] = { AArch64::qsub0, AArch64::qsub1,
2882 AArch64::qsub2, AArch64::qsub3 };
2883 for (unsigned i = 0; i < NumVecs; ++i) {
2884 SDValue NV = CurDAG->getTargetExtractSubreg(QSubs[i], dl, WideVT,
2885 SuperReg);
2886 if (Narrow)
2887 NV = NarrowVector(NV, *CurDAG);
2888 ReplaceUses(SDValue(N, i), NV);
2889 }
2890 }
2891
2892 // Update the Chain
2893 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(Ld, 2));
2894 CurDAG->RemoveDeadNode(N);
2895}
2896
2897void AArch64DAGToDAGISel::SelectStoreLane(SDNode *N, unsigned NumVecs,
2898 unsigned Opc) {
2899 SDLoc dl(N);
2900 EVT VT = N->getOperand(2)->getValueType(0);
2901 bool Narrow = VT.getSizeInBits() == 64;
2902
2903 // Form a REG_SEQUENCE to force register allocation.
2904 SmallVector<SDValue, 4> Regs(N->ops().slice(2, NumVecs));
2905
2906 if (Narrow)
2907 transform(Regs, Regs.begin(),
2908 WidenVector(*CurDAG));
2909
2910 SDValue RegSeq = createQTuple(Regs);
2911
2912 unsigned LaneNo = N->getConstantOperandVal(NumVecs + 2);
2913
2914 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2915 N->getOperand(NumVecs + 3), N->getOperand(0)};
2916 SDNode *St = CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops);
2917
2918 // Transfer memoperands.
2919 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2920 CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
2921
2922 ReplaceNode(N, St);
2923}
2924
2925void AArch64DAGToDAGISel::SelectPostStoreLane(SDNode *N, unsigned NumVecs,
2926 unsigned Opc) {
2927 SDLoc dl(N);
2928 EVT VT = N->getOperand(2)->getValueType(0);
2929 bool Narrow = VT.getSizeInBits() == 64;
2930
2931 // Form a REG_SEQUENCE to force register allocation.
2932 SmallVector<SDValue, 4> Regs(N->ops().slice(1, NumVecs));
2933
2934 if (Narrow)
2935 transform(Regs, Regs.begin(),
2936 WidenVector(*CurDAG));
2937
2938 SDValue RegSeq = createQTuple(Regs);
2939
2940 const EVT ResTys[] = {MVT::i64, // Type of the write back register
2941 MVT::Other};
2942
2943 unsigned LaneNo = N->getConstantOperandVal(NumVecs + 1);
2944
2945 SDValue Ops[] = {RegSeq, CurDAG->getTargetConstant(LaneNo, dl, MVT::i64),
2946 N->getOperand(NumVecs + 2), // Base Register
2947 N->getOperand(NumVecs + 3), // Incremental
2948 N->getOperand(0)};
2949 SDNode *St = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
2950
2951 // Transfer memoperands.
2952 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
2953 CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
2954
2955 ReplaceNode(N, St);
2956}
2957
2959 unsigned &Opc, SDValue &Opd0,
2960 unsigned &LSB, unsigned &MSB,
2961 unsigned NumberOfIgnoredLowBits,
2962 bool BiggerPattern) {
2963 assert(N->getOpcode() == ISD::AND &&
2964 "N must be a AND operation to call this function");
2965
2966 EVT VT = N->getValueType(0);
2967
2968 // Here we can test the type of VT and return false when the type does not
2969 // match, but since it is done prior to that call in the current context
2970 // we turned that into an assert to avoid redundant code.
2971 assert((VT == MVT::i32 || VT == MVT::i64) &&
2972 "Type checking must have been done before calling this function");
2973
2974 // FIXME: simplify-demanded-bits in DAGCombine will probably have
2975 // changed the AND node to a 32-bit mask operation. We'll have to
2976 // undo that as part of the transform here if we want to catch all
2977 // the opportunities.
2978 // Currently the NumberOfIgnoredLowBits argument helps to recover
2979 // from these situations when matching bigger pattern (bitfield insert).
2980
2981 // For unsigned extracts, check for a shift right and mask
2982 uint64_t AndImm = 0;
2983 if (!isOpcWithIntImmediate(N, ISD::AND, AndImm))
2984 return false;
2985
2986 const SDNode *Op0 = N->getOperand(0).getNode();
2987
2988 // Because of simplify-demanded-bits in DAGCombine, the mask may have been
2989 // simplified. Try to undo that
2990 AndImm |= maskTrailingOnes<uint64_t>(NumberOfIgnoredLowBits);
2991
2992 // The immediate is a mask of the low bits iff imm & (imm+1) == 0
2993 if (AndImm & (AndImm + 1))
2994 return false;
2995
2996 bool ClampMSB = false;
2997 uint64_t SrlImm = 0;
2998 // Handle the SRL + ANY_EXTEND case.
2999 if (VT == MVT::i64 && Op0->getOpcode() == ISD::ANY_EXTEND &&
3000 isOpcWithIntImmediate(Op0->getOperand(0).getNode(), ISD::SRL, SrlImm)) {
3001 // Extend the incoming operand of the SRL to 64-bit.
3002 Opd0 = Widen(CurDAG, Op0->getOperand(0).getOperand(0));
3003 // Make sure to clamp the MSB so that we preserve the semantics of the
3004 // original operations.
3005 ClampMSB = true;
3006 } else if (VT == MVT::i32 && Op0->getOpcode() == ISD::TRUNCATE &&
3008 SrlImm)) {
3009 // If the shift result was truncated, we can still combine them.
3010 Opd0 = Op0->getOperand(0).getOperand(0);
3011
3012 // Use the type of SRL node.
3013 VT = Opd0->getValueType(0);
3014 } else if (isOpcWithIntImmediate(Op0, ISD::SRL, SrlImm)) {
3015 Opd0 = Op0->getOperand(0);
3016 ClampMSB = (VT == MVT::i32);
3017 } else if (BiggerPattern) {
3018 // Let's pretend a 0 shift right has been performed.
3019 // The resulting code will be at least as good as the original one
3020 // plus it may expose more opportunities for bitfield insert pattern.
3021 // FIXME: Currently we limit this to the bigger pattern, because
3022 // some optimizations expect AND and not UBFM.
3023 Opd0 = N->getOperand(0);
3024 } else
3025 return false;
3026
3027 // Bail out on large immediates. This happens when no proper
3028 // combining/constant folding was performed.
3029 if (!BiggerPattern && (SrlImm <= 0 || SrlImm >= VT.getSizeInBits())) {
3030 LLVM_DEBUG(
3031 (dbgs() << N
3032 << ": Found large shift immediate, this should not happen\n"));
3033 return false;
3034 }
3035
3036 LSB = SrlImm;
3037 MSB = SrlImm +
3038 (VT == MVT::i32 ? llvm::countr_one<uint32_t>(AndImm)
3039 : llvm::countr_one<uint64_t>(AndImm)) -
3040 1;
3041 if (ClampMSB)
3042 // Since we're moving the extend before the right shift operation, we need
3043 // to clamp the MSB to make sure we don't shift in undefined bits instead of
3044 // the zeros which would get shifted in with the original right shift
3045 // operation.
3046 MSB = MSB > 31 ? 31 : MSB;
3047
3048 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3049 return true;
3050}
3051
3053 SDValue &Opd0, unsigned &Immr,
3054 unsigned &Imms) {
3055 assert(N->getOpcode() == ISD::SIGN_EXTEND_INREG);
3056
3057 EVT VT = N->getValueType(0);
3058 unsigned BitWidth = VT.getSizeInBits();
3059 assert((VT == MVT::i32 || VT == MVT::i64) &&
3060 "Type checking must have been done before calling this function");
3061
3062 SDValue Op = N->getOperand(0);
3063 if (Op->getOpcode() == ISD::TRUNCATE) {
3064 Op = Op->getOperand(0);
3065 VT = Op->getValueType(0);
3066 BitWidth = VT.getSizeInBits();
3067 }
3068
3069 uint64_t ShiftImm;
3070 if (!isOpcWithIntImmediate(Op.getNode(), ISD::SRL, ShiftImm) &&
3071 !isOpcWithIntImmediate(Op.getNode(), ISD::SRA, ShiftImm))
3072 return false;
3073
3074 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
3075 if (ShiftImm + Width > BitWidth)
3076 return false;
3077
3078 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
3079 Opd0 = Op.getOperand(0);
3080 Immr = ShiftImm;
3081 Imms = ShiftImm + Width - 1;
3082 return true;
3083}
3084
3086 SDValue &Opd0, unsigned &LSB,
3087 unsigned &MSB) {
3088 // We are looking for the following pattern which basically extracts several
3089 // continuous bits from the source value and places it from the LSB of the
3090 // destination value, all other bits of the destination value or set to zero:
3091 //
3092 // Value2 = AND Value, MaskImm
3093 // SRL Value2, ShiftImm
3094 //
3095 // with MaskImm >> ShiftImm to search for the bit width.
3096 //
3097 // This gets selected into a single UBFM:
3098 //
3099 // UBFM Value, ShiftImm, Log2_64(MaskImm)
3100 //
3101
3102 if (N->getOpcode() != ISD::SRL)
3103 return false;
3104
3105 uint64_t AndMask = 0;
3106 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, AndMask))
3107 return false;
3108
3109 Opd0 = N->getOperand(0).getOperand(0);
3110
3111 uint64_t SrlImm = 0;
3112 if (!isIntImmediate(N->getOperand(1), SrlImm))
3113 return false;
3114
3115 // Check whether we really have several bits extract here.
3116 if (!isMask_64(AndMask >> SrlImm))
3117 return false;
3118
3119 Opc = N->getValueType(0) == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3120 LSB = SrlImm;
3121 MSB = llvm::Log2_64(AndMask);
3122 return true;
3123}
3124
3125static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0,
3126 unsigned &Immr, unsigned &Imms,
3127 bool BiggerPattern) {
3128 assert((N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL) &&
3129 "N must be a SHR/SRA operation to call this function");
3130
3131 EVT VT = N->getValueType(0);
3132
3133 // Here we can test the type of VT and return false when the type does not
3134 // match, but since it is done prior to that call in the current context
3135 // we turned that into an assert to avoid redundant code.
3136 assert((VT == MVT::i32 || VT == MVT::i64) &&
3137 "Type checking must have been done before calling this function");
3138
3139 // Check for AND + SRL doing several bits extract.
3140 if (isSeveralBitsExtractOpFromShr(N, Opc, Opd0, Immr, Imms))
3141 return true;
3142
3143 // We're looking for a shift of a shift.
3144 uint64_t ShlImm = 0;
3145 uint64_t TruncBits = 0;
3146 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, ShlImm)) {
3147 Opd0 = N->getOperand(0).getOperand(0);
3148 } else if (VT == MVT::i32 && N->getOpcode() == ISD::SRL &&
3149 N->getOperand(0).getNode()->getOpcode() == ISD::TRUNCATE) {
3150 // We are looking for a shift of truncate. Truncate from i64 to i32 could
3151 // be considered as setting high 32 bits as zero. Our strategy here is to
3152 // always generate 64bit UBFM. This consistency will help the CSE pass
3153 // later find more redundancy.
3154 Opd0 = N->getOperand(0).getOperand(0);
3155 TruncBits = Opd0->getValueType(0).getSizeInBits() - VT.getSizeInBits();
3156 VT = Opd0.getValueType();
3157 assert(VT == MVT::i64 && "the promoted type should be i64");
3158 } else if (BiggerPattern) {
3159 // Let's pretend a 0 shift left has been performed.
3160 // FIXME: Currently we limit this to the bigger pattern case,
3161 // because some optimizations expect AND and not UBFM
3162 Opd0 = N->getOperand(0);
3163 } else
3164 return false;
3165
3166 // Missing combines/constant folding may have left us with strange
3167 // constants.
3168 if (ShlImm >= VT.getSizeInBits()) {
3169 LLVM_DEBUG(
3170 (dbgs() << N
3171 << ": Found large shift immediate, this should not happen\n"));
3172 return false;
3173 }
3174
3175 uint64_t SrlImm = 0;
3176 if (!isIntImmediate(N->getOperand(1), SrlImm))
3177 return false;
3178
3179 assert(SrlImm > 0 && SrlImm < VT.getSizeInBits() &&
3180 "bad amount in shift node!");
3181 int immr = SrlImm - ShlImm;
3182 Immr = immr < 0 ? immr + VT.getSizeInBits() : immr;
3183 Imms = VT.getSizeInBits() - ShlImm - TruncBits - 1;
3184 // SRA requires a signed extraction
3185 if (VT == MVT::i32)
3186 Opc = N->getOpcode() == ISD::SRA ? AArch64::SBFMWri : AArch64::UBFMWri;
3187 else
3188 Opc = N->getOpcode() == ISD::SRA ? AArch64::SBFMXri : AArch64::UBFMXri;
3189 return true;
3190}
3191
3192static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc,
3193 SDValue &Opd0, unsigned &Immr, unsigned &Imms,
3194 unsigned NumberOfIgnoredLowBits = 0,
3195 bool BiggerPattern = false) {
3196 if (N->getValueType(0) != MVT::i32 && N->getValueType(0) != MVT::i64)
3197 return false;
3198
3199 switch (N->getOpcode()) {
3200 default:
3201 if (!N->isMachineOpcode())
3202 return false;
3203 break;
3204 case ISD::AND:
3205 return isBitfieldExtractOpFromAnd(CurDAG, N, Opc, Opd0, Immr, Imms,
3206 NumberOfIgnoredLowBits, BiggerPattern);
3207 case ISD::SRL:
3208 case ISD::SRA:
3209 return isBitfieldExtractOpFromShr(N, Opc, Opd0, Immr, Imms, BiggerPattern);
3210
3212 return isBitfieldExtractOpFromSExtInReg(N, Opc, Opd0, Immr, Imms);
3213 }
3214
3215 unsigned NOpc = N->getMachineOpcode();
3216 switch (NOpc) {
3217 default:
3218 return false;
3219 case AArch64::SBFMWri:
3220 case AArch64::UBFMWri:
3221 case AArch64::SBFMXri:
3222 case AArch64::UBFMXri:
3223 Opc = NOpc;
3224 Opd0 = N->getOperand(0);
3225 Immr = N->getConstantOperandVal(1);
3226 Imms = N->getConstantOperandVal(2);
3227 return true;
3228 }
3229 // Unreachable
3230 return false;
3231}
3232
3233bool AArch64DAGToDAGISel::tryBitfieldExtractOp(SDNode *N) {
3234 unsigned Opc, Immr, Imms;
3235 SDValue Opd0;
3236 if (!isBitfieldExtractOp(CurDAG, N, Opc, Opd0, Immr, Imms))
3237 return false;
3238
3239 EVT VT = N->getValueType(0);
3240 SDLoc dl(N);
3241
3242 // If the bit extract operation is 64bit but the original type is 32bit, we
3243 // need to add one EXTRACT_SUBREG.
3244 if ((Opc == AArch64::SBFMXri || Opc == AArch64::UBFMXri) && VT == MVT::i32) {
3245 SDValue Ops64[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, MVT::i64),
3246 CurDAG->getTargetConstant(Imms, dl, MVT::i64)};
3247
3248 SDNode *BFM = CurDAG->getMachineNode(Opc, dl, MVT::i64, Ops64);
3249 SDValue Inner = CurDAG->getTargetExtractSubreg(AArch64::sub_32, dl,
3250 MVT::i32, SDValue(BFM, 0));
3251 ReplaceNode(N, Inner.getNode());
3252 return true;
3253 }
3254
3255 SDValue Ops[] = {Opd0, CurDAG->getTargetConstant(Immr, dl, VT),
3256 CurDAG->getTargetConstant(Imms, dl, VT)};
3257 CurDAG->SelectNodeTo(N, Opc, VT, Ops);
3258 return true;
3259}
3260
3261/// Does DstMask form a complementary pair with the mask provided by
3262/// BitsToBeInserted, suitable for use in a BFI instruction. Roughly speaking,
3263/// this asks whether DstMask zeroes precisely those bits that will be set by
3264/// the other half.
3265static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted,
3266 unsigned NumberOfIgnoredHighBits, EVT VT) {
3267 assert((VT == MVT::i32 || VT == MVT::i64) &&
3268 "i32 or i64 mask type expected!");
3269 unsigned BitWidth = VT.getSizeInBits() - NumberOfIgnoredHighBits;
3270
3271 // Enable implicitTrunc as we're intentionally ignoring high bits.
3272 APInt SignificantDstMask =
3273 APInt(BitWidth, DstMask, /*isSigned=*/false, /*implicitTrunc=*/true);
3274 APInt SignificantBitsToBeInserted = BitsToBeInserted.zextOrTrunc(BitWidth);
3275
3276 return (SignificantDstMask & SignificantBitsToBeInserted) == 0 &&
3277 (SignificantDstMask | SignificantBitsToBeInserted).isAllOnes();
3278}
3279
3280// Look for bits that will be useful for later uses.
3281// A bit is consider useless as soon as it is dropped and never used
3282// before it as been dropped.
3283// E.g., looking for useful bit of x
3284// 1. y = x & 0x7
3285// 2. z = y >> 2
3286// After #1, x useful bits are 0x7, then the useful bits of x, live through
3287// y.
3288// After #2, the useful bits of x are 0x4.
3289// However, if x is used on an unpredictable instruction, then all its bits
3290// are useful.
3291// E.g.
3292// 1. y = x & 0x7
3293// 2. z = y >> 2
3294// 3. str x, [@x]
3295static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth = 0);
3296
3298 unsigned Depth) {
3299 uint64_t Imm =
3300 cast<const ConstantSDNode>(Op.getOperand(1).getNode())->getZExtValue();
3302 UsefulBits &= APInt(UsefulBits.getBitWidth(), Imm);
3303 getUsefulBits(Op, UsefulBits, Depth + 1);
3304}
3305
3307 uint64_t Imm, uint64_t MSB,
3308 unsigned Depth) {
3309 // inherit the bitwidth value
3310 APInt OpUsefulBits(UsefulBits);
3311 OpUsefulBits = 1;
3312
3313 if (MSB >= Imm) {
3314 OpUsefulBits <<= MSB - Imm + 1;
3315 --OpUsefulBits;
3316 // The interesting part will be in the lower part of the result
3317 getUsefulBits(Op, OpUsefulBits, Depth + 1);
3318 // The interesting part was starting at Imm in the argument
3319 OpUsefulBits <<= Imm;
3320 } else {
3321 OpUsefulBits <<= MSB + 1;
3322 --OpUsefulBits;
3323 // The interesting part will be shifted in the result
3324 OpUsefulBits <<= OpUsefulBits.getBitWidth() - Imm;
3325 getUsefulBits(Op, OpUsefulBits, Depth + 1);
3326 // The interesting part was at zero in the argument
3327 OpUsefulBits.lshrInPlace(OpUsefulBits.getBitWidth() - Imm);
3328 }
3329
3330 UsefulBits &= OpUsefulBits;
3331}
3332
3333static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits,
3334 unsigned Depth) {
3335 uint64_t Imm =
3336 cast<const ConstantSDNode>(Op.getOperand(1).getNode())->getZExtValue();
3337 uint64_t MSB =
3338 cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
3339
3340 getUsefulBitsFromBitfieldMoveOpd(Op, UsefulBits, Imm, MSB, Depth);
3341}
3342
3344 unsigned Depth) {
3345 uint64_t ShiftTypeAndValue =
3346 cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
3347 APInt Mask(UsefulBits);
3348 Mask.clearAllBits();
3349 Mask.flipAllBits();
3350
3351 if (AArch64_AM::getShiftType(ShiftTypeAndValue) == AArch64_AM::LSL) {
3352 // Shift Left
3353 uint64_t ShiftAmt = AArch64_AM::getShiftValue(ShiftTypeAndValue);
3354 Mask <<= ShiftAmt;
3355 getUsefulBits(Op, Mask, Depth + 1);
3356 Mask.lshrInPlace(ShiftAmt);
3357 } else if (AArch64_AM::getShiftType(ShiftTypeAndValue) == AArch64_AM::LSR) {
3358 // Shift Right
3359 // We do not handle AArch64_AM::ASR, because the sign will change the
3360 // number of useful bits
3361 uint64_t ShiftAmt = AArch64_AM::getShiftValue(ShiftTypeAndValue);
3362 Mask.lshrInPlace(ShiftAmt);
3363 getUsefulBits(Op, Mask, Depth + 1);
3364 Mask <<= ShiftAmt;
3365 } else
3366 return;
3367
3368 UsefulBits &= Mask;
3369}
3370
3371static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits,
3372 unsigned Depth) {
3373 uint64_t Imm =
3374 cast<const ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
3375 uint64_t MSB =
3376 cast<const ConstantSDNode>(Op.getOperand(3).getNode())->getZExtValue();
3377
3378 APInt OpUsefulBits(UsefulBits);
3379 OpUsefulBits = 1;
3380
3381 APInt ResultUsefulBits(UsefulBits.getBitWidth(), 0);
3382 ResultUsefulBits.flipAllBits();
3383 APInt Mask(UsefulBits.getBitWidth(), 0);
3384
3385 getUsefulBits(Op, ResultUsefulBits, Depth + 1);
3386
3387 if (MSB >= Imm) {
3388 // The instruction is a BFXIL.
3389 uint64_t Width = MSB - Imm + 1;
3390 uint64_t LSB = Imm;
3391
3392 OpUsefulBits <<= Width;
3393 --OpUsefulBits;
3394
3395 if (Op.getOperand(1) == Orig) {
3396 // Copy the low bits from the result to bits starting from LSB.
3397 Mask = ResultUsefulBits & OpUsefulBits;
3398 Mask <<= LSB;
3399 }
3400
3401 if (Op.getOperand(0) == Orig)
3402 // Bits starting from LSB in the input contribute to the result.
3403 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3404 } else {
3405 // The instruction is a BFI.
3406 uint64_t Width = MSB + 1;
3407 uint64_t LSB = UsefulBits.getBitWidth() - Imm;
3408
3409 OpUsefulBits <<= Width;
3410 --OpUsefulBits;
3411 OpUsefulBits <<= LSB;
3412
3413 if (Op.getOperand(1) == Orig) {
3414 // Copy the bits from the result to the zero bits.
3415 Mask = ResultUsefulBits & OpUsefulBits;
3416 Mask.lshrInPlace(LSB);
3417 }
3418
3419 if (Op.getOperand(0) == Orig)
3420 Mask |= (ResultUsefulBits & ~OpUsefulBits);
3421 }
3422
3423 UsefulBits &= Mask;
3424}
3425
3426static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits,
3427 SDValue Orig, unsigned Depth) {
3428
3429 // Users of this node should have already been instruction selected
3430 // FIXME: Can we turn that into an assert?
3431 if (!UserNode->isMachineOpcode())
3432 return;
3433
3434 switch (UserNode->getMachineOpcode()) {
3435 default:
3436 return;
3437 case AArch64::ANDSWri:
3438 case AArch64::ANDSXri:
3439 case AArch64::ANDWri:
3440 case AArch64::ANDXri:
3441 // We increment Depth only when we call the getUsefulBits
3442 return getUsefulBitsFromAndWithImmediate(SDValue(UserNode, 0), UsefulBits,
3443 Depth);
3444 case AArch64::UBFMWri:
3445 case AArch64::UBFMXri:
3446 return getUsefulBitsFromUBFM(SDValue(UserNode, 0), UsefulBits, Depth);
3447
3448 case AArch64::ORRWrs:
3449 case AArch64::ORRXrs:
3450 if (UserNode->getOperand(0) != Orig && UserNode->getOperand(1) == Orig)
3451 getUsefulBitsFromOrWithShiftedReg(SDValue(UserNode, 0), UsefulBits,
3452 Depth);
3453 return;
3454 case AArch64::BFMWri:
3455 case AArch64::BFMXri:
3456 return getUsefulBitsFromBFM(SDValue(UserNode, 0), Orig, UsefulBits, Depth);
3457
3458 case AArch64::STRBBui:
3459 case AArch64::STURBBi:
3460 if (UserNode->getOperand(0) != Orig)
3461 return;
3462 UsefulBits &= APInt(UsefulBits.getBitWidth(), 0xff);
3463 return;
3464
3465 case AArch64::STRHHui:
3466 case AArch64::STURHHi:
3467 if (UserNode->getOperand(0) != Orig)
3468 return;
3469 UsefulBits &= APInt(UsefulBits.getBitWidth(), 0xffff);
3470 return;
3471 }
3472}
3473
3474static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth) {
3476 return;
3477 // Initialize UsefulBits
3478 if (!Depth) {
3479 unsigned Bitwidth = Op.getScalarValueSizeInBits();
3480 // At the beginning, assume every produced bits is useful
3481 UsefulBits = APInt(Bitwidth, 0);
3482 UsefulBits.flipAllBits();
3483 }
3484 APInt UsersUsefulBits(UsefulBits.getBitWidth(), 0);
3485
3486 for (SDNode *Node : Op.getNode()->users()) {
3487 // A use cannot produce useful bits
3488 APInt UsefulBitsForUse = APInt(UsefulBits);
3489 getUsefulBitsForUse(Node, UsefulBitsForUse, Op, Depth);
3490 UsersUsefulBits |= UsefulBitsForUse;
3491 }
3492 // UsefulBits contains the produced bits that are meaningful for the
3493 // current definition, thus a user cannot make a bit meaningful at
3494 // this point
3495 UsefulBits &= UsersUsefulBits;
3496}
3497
3498/// Create a machine node performing a notional SHL of Op by ShlAmount. If
3499/// ShlAmount is negative, do a (logical) right-shift instead. If ShlAmount is
3500/// 0, return Op unchanged.
3501static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount) {
3502 if (ShlAmount == 0)
3503 return Op;
3504
3505 EVT VT = Op.getValueType();
3506 SDLoc dl(Op);
3507 unsigned BitWidth = VT.getSizeInBits();
3508 unsigned UBFMOpc = BitWidth == 32 ? AArch64::UBFMWri : AArch64::UBFMXri;
3509
3510 SDNode *ShiftNode;
3511 if (ShlAmount > 0) {
3512 // LSL wD, wN, #Amt == UBFM wD, wN, #32-Amt, #31-Amt
3513 ShiftNode = CurDAG->getMachineNode(
3514 UBFMOpc, dl, VT, Op,
3515 CurDAG->getTargetConstant(BitWidth - ShlAmount, dl, VT),
3516 CurDAG->getTargetConstant(BitWidth - 1 - ShlAmount, dl, VT));
3517 } else {
3518 // LSR wD, wN, #Amt == UBFM wD, wN, #Amt, #32-1
3519 assert(ShlAmount < 0 && "expected right shift");
3520 int ShrAmount = -ShlAmount;
3521 ShiftNode = CurDAG->getMachineNode(
3522 UBFMOpc, dl, VT, Op, CurDAG->getTargetConstant(ShrAmount, dl, VT),
3523 CurDAG->getTargetConstant(BitWidth - 1, dl, VT));
3524 }
3525
3526 return SDValue(ShiftNode, 0);
3527}
3528
3529// For bit-field-positioning pattern "(and (shl VAL, N), ShiftedMask)".
3530static bool isBitfieldPositioningOpFromAnd(SelectionDAG *CurDAG, SDValue Op,
3531 bool BiggerPattern,
3532 const uint64_t NonZeroBits,
3533 SDValue &Src, int &DstLSB,
3534 int &Width);
3535
3536// For bit-field-positioning pattern "shl VAL, N)".
3537static bool isBitfieldPositioningOpFromShl(SelectionDAG *CurDAG, SDValue Op,
3538 bool BiggerPattern,
3539 const uint64_t NonZeroBits,
3540 SDValue &Src, int &DstLSB,
3541 int &Width);
3542
3543/// Does this tree qualify as an attempt to move a bitfield into position,
3544/// essentially "(and (shl VAL, N), Mask)" or (shl VAL, N).
3546 bool BiggerPattern, SDValue &Src,
3547 int &DstLSB, int &Width) {
3548 EVT VT = Op.getValueType();
3549 unsigned BitWidth = VT.getSizeInBits();
3550 (void)BitWidth;
3551 assert(BitWidth == 32 || BitWidth == 64);
3552
3554
3555 // Non-zero in the sense that they're not provably zero, which is the key
3556 // point if we want to use this value
3557 const uint64_t NonZeroBits = (~Known.Zero).getZExtValue();
3558 if (!isShiftedMask_64(NonZeroBits))
3559 return false;
3560
3561 switch (Op.getOpcode()) {
3562 default:
3563 break;
3564 case ISD::AND:
3565 return isBitfieldPositioningOpFromAnd(CurDAG, Op, BiggerPattern,
3566 NonZeroBits, Src, DstLSB, Width);
3567 case ISD::SHL:
3568 return isBitfieldPositioningOpFromShl(CurDAG, Op, BiggerPattern,
3569 NonZeroBits, Src, DstLSB, Width);
3570 }
3571
3572 return false;
3573}
3574
3576 bool BiggerPattern,
3577 const uint64_t NonZeroBits,
3578 SDValue &Src, int &DstLSB,
3579 int &Width) {
3580 assert(isShiftedMask_64(NonZeroBits) && "Caller guaranteed");
3581
3582 EVT VT = Op.getValueType();
3583 assert((VT == MVT::i32 || VT == MVT::i64) &&
3584 "Caller guarantees VT is one of i32 or i64");
3585 (void)VT;
3586
3587 uint64_t AndImm;
3588 if (!isOpcWithIntImmediate(Op.getNode(), ISD::AND, AndImm))
3589 return false;
3590
3591 // If (~AndImm & NonZeroBits) is not zero at POS, we know that
3592 // 1) (AndImm & (1 << POS) == 0)
3593 // 2) the result of AND is not zero at POS bit (according to NonZeroBits)
3594 //
3595 // 1) and 2) don't agree so something must be wrong (e.g., in
3596 // 'SelectionDAG::computeKnownBits')
3597 assert((~AndImm & NonZeroBits) == 0 &&
3598 "Something must be wrong (e.g., in SelectionDAG::computeKnownBits)");
3599
3600 SDValue AndOp0 = Op.getOperand(0);
3601
3602 uint64_t ShlImm;
3603 SDValue ShlOp0;
3604 if (isOpcWithIntImmediate(AndOp0.getNode(), ISD::SHL, ShlImm)) {
3605 // For pattern "and(shl(val, N), shifted-mask)", 'ShlOp0' is set to 'val'.
3606 ShlOp0 = AndOp0.getOperand(0);
3607 } else if (VT == MVT::i64 && AndOp0.getOpcode() == ISD::ANY_EXTEND &&
3609 ShlImm)) {
3610 // For pattern "and(any_extend(shl(val, N)), shifted-mask)"
3611
3612 // ShlVal == shl(val, N), which is a left shift on a smaller type.
3613 SDValue ShlVal = AndOp0.getOperand(0);
3614
3615 // Since this is after type legalization and ShlVal is extended to MVT::i64,
3616 // expect VT to be MVT::i32.
3617 assert((ShlVal.getValueType() == MVT::i32) && "Expect VT to be MVT::i32.");
3618
3619 // Widens 'val' to MVT::i64 as the source of bit field positioning.
3620 ShlOp0 = Widen(CurDAG, ShlVal.getOperand(0));
3621 } else
3622 return false;
3623
3624 // For !BiggerPattern, bail out if the AndOp0 has more than one use, since
3625 // then we'll end up generating AndOp0+UBFIZ instead of just keeping
3626 // AndOp0+AND.
3627 if (!BiggerPattern && !AndOp0.hasOneUse())
3628 return false;
3629
3630 DstLSB = llvm::countr_zero(NonZeroBits);
3631 Width = llvm::countr_one(NonZeroBits >> DstLSB);
3632
3633 // Bail out on large Width. This happens when no proper combining / constant
3634 // folding was performed.
3635 if (Width >= (int)VT.getSizeInBits()) {
3636 // If VT is i64, Width > 64 is insensible since NonZeroBits is uint64_t, and
3637 // Width == 64 indicates a missed dag-combine from "(and val, AllOnes)" to
3638 // "val".
3639 // If VT is i32, what Width >= 32 means:
3640 // - For "(and (any_extend(shl val, N)), shifted-mask)", the`and` Op
3641 // demands at least 'Width' bits (after dag-combiner). This together with
3642 // `any_extend` Op (undefined higher bits) indicates missed combination
3643 // when lowering the 'and' IR instruction to an machine IR instruction.
3644 LLVM_DEBUG(
3645 dbgs()
3646 << "Found large Width in bit-field-positioning -- this indicates no "
3647 "proper combining / constant folding was performed\n");
3648 return false;
3649 }
3650
3651 // BFI encompasses sufficiently many nodes that it's worth inserting an extra
3652 // LSL/LSR if the mask in NonZeroBits doesn't quite match up with the ISD::SHL
3653 // amount. BiggerPattern is true when this pattern is being matched for BFI,
3654 // BiggerPattern is false when this pattern is being matched for UBFIZ, in
3655 // which case it is not profitable to insert an extra shift.
3656 if (ShlImm != uint64_t(DstLSB) && !BiggerPattern)
3657 return false;
3658
3659 Src = getLeftShift(CurDAG, ShlOp0, ShlImm - DstLSB);
3660 return true;
3661}
3662
3663// For node (shl (and val, mask), N)), returns true if the node is equivalent to
3664// UBFIZ.
3666 SDValue &Src, int &DstLSB,
3667 int &Width) {
3668 // Caller should have verified that N is a left shift with constant shift
3669 // amount; asserts that.
3670 assert(Op.getOpcode() == ISD::SHL &&
3671 "Op.getNode() should be a SHL node to call this function");
3672 assert(isIntImmediateEq(Op.getOperand(1), ShlImm) &&
3673 "Op.getNode() should shift ShlImm to call this function");
3674
3675 uint64_t AndImm = 0;
3676 SDValue Op0 = Op.getOperand(0);
3677 if (!isOpcWithIntImmediate(Op0.getNode(), ISD::AND, AndImm))
3678 return false;
3679
3680 const uint64_t ShiftedAndImm = ((AndImm << ShlImm) >> ShlImm);
3681 if (isMask_64(ShiftedAndImm)) {
3682 // AndImm is a superset of (AllOnes >> ShlImm); in other words, AndImm
3683 // should end with Mask, and could be prefixed with random bits if those
3684 // bits are shifted out.
3685 //
3686 // For example, xyz11111 (with {x,y,z} being 0 or 1) is fine if ShlImm >= 3;
3687 // the AND result corresponding to those bits are shifted out, so it's fine
3688 // to not extract them.
3689 Width = llvm::countr_one(ShiftedAndImm);
3690 DstLSB = ShlImm;
3691 Src = Op0.getOperand(0);
3692 return true;
3693 }
3694 return false;
3695}
3696
3698 bool BiggerPattern,
3699 const uint64_t NonZeroBits,
3700 SDValue &Src, int &DstLSB,
3701 int &Width) {
3702 assert(isShiftedMask_64(NonZeroBits) && "Caller guaranteed");
3703
3704 EVT VT = Op.getValueType();
3705 assert((VT == MVT::i32 || VT == MVT::i64) &&
3706 "Caller guarantees that type is i32 or i64");
3707 (void)VT;
3708
3709 uint64_t ShlImm;
3710 if (!isOpcWithIntImmediate(Op.getNode(), ISD::SHL, ShlImm))
3711 return false;
3712
3713 if (!BiggerPattern && !Op.hasOneUse())
3714 return false;
3715
3716 if (isSeveralBitsPositioningOpFromShl(ShlImm, Op, Src, DstLSB, Width))
3717 return true;
3718
3719 DstLSB = llvm::countr_zero(NonZeroBits);
3720 Width = llvm::countr_one(NonZeroBits >> DstLSB);
3721
3722 if (ShlImm != uint64_t(DstLSB) && !BiggerPattern)
3723 return false;
3724
3725 Src = getLeftShift(CurDAG, Op.getOperand(0), ShlImm - DstLSB);
3726 return true;
3727}
3728
3729static bool isShiftedMask(uint64_t Mask, EVT VT) {
3730 assert(VT == MVT::i32 || VT == MVT::i64);
3731 if (VT == MVT::i32)
3732 return isShiftedMask_32(Mask);
3733 return isShiftedMask_64(Mask);
3734}
3735
3736// Generate a BFI/BFXIL from 'or (and X, MaskImm), OrImm' iff the value being
3737// inserted only sets known zero bits.
3739 assert(N->getOpcode() == ISD::OR && "Expect a OR operation");
3740
3741 EVT VT = N->getValueType(0);
3742 if (VT != MVT::i32 && VT != MVT::i64)
3743 return false;
3744
3745 unsigned BitWidth = VT.getSizeInBits();
3746
3747 uint64_t OrImm;
3748 if (!isOpcWithIntImmediate(N, ISD::OR, OrImm))
3749 return false;
3750
3751 // Skip this transformation if the ORR immediate can be encoded in the ORR.
3752 // Otherwise, we'll trade an AND+ORR for ORR+BFI/BFXIL, which is most likely
3753 // performance neutral.
3755 return false;
3756
3757 uint64_t MaskImm;
3758 SDValue And = N->getOperand(0);
3759 // Must be a single use AND with an immediate operand.
3760 if (!And.hasOneUse() ||
3761 !isOpcWithIntImmediate(And.getNode(), ISD::AND, MaskImm))
3762 return false;
3763
3764 // Compute the Known Zero for the AND as this allows us to catch more general
3765 // cases than just looking for AND with imm.
3767
3768 // Non-zero in the sense that they're not provably zero, which is the key
3769 // point if we want to use this value.
3770 uint64_t NotKnownZero = (~Known.Zero).getZExtValue();
3771
3772 // The KnownZero mask must be a shifted mask (e.g., 1110..011, 11100..00).
3773 if (!isShiftedMask(Known.Zero.getZExtValue(), VT))
3774 return false;
3775
3776 // The bits being inserted must only set those bits that are known to be zero.
3777 if ((OrImm & NotKnownZero) != 0) {
3778 // FIXME: It's okay if the OrImm sets NotKnownZero bits to 1, but we don't
3779 // currently handle this case.
3780 return false;
3781 }
3782
3783 // BFI/BFXIL dst, src, #lsb, #width.
3784 int LSB = llvm::countr_one(NotKnownZero);
3785 int Width = BitWidth - APInt(BitWidth, NotKnownZero).popcount();
3786
3787 // BFI/BFXIL is an alias of BFM, so translate to BFM operands.
3788 unsigned ImmR = (BitWidth - LSB) % BitWidth;
3789 unsigned ImmS = Width - 1;
3790
3791 // If we're creating a BFI instruction avoid cases where we need more
3792 // instructions to materialize the BFI constant as compared to the original
3793 // ORR. A BFXIL will use the same constant as the original ORR, so the code
3794 // should be no worse in this case.
3795 bool IsBFI = LSB != 0;
3796 uint64_t BFIImm = OrImm >> LSB;
3797 if (IsBFI && !AArch64_AM::isLogicalImmediate(BFIImm, BitWidth)) {
3798 // We have a BFI instruction and we know the constant can't be materialized
3799 // with a ORR-immediate with the zero register.
3800 unsigned OrChunks = 0, BFIChunks = 0;
3801 for (unsigned Shift = 0; Shift < BitWidth; Shift += 16) {
3802 if (((OrImm >> Shift) & 0xFFFF) != 0)
3803 ++OrChunks;
3804 if (((BFIImm >> Shift) & 0xFFFF) != 0)
3805 ++BFIChunks;
3806 }
3807 if (BFIChunks > OrChunks)
3808 return false;
3809 }
3810
3811 // Materialize the constant to be inserted.
3812 SDLoc DL(N);
3813 unsigned MOVIOpc = VT == MVT::i32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
3814 SDNode *MOVI = CurDAG->getMachineNode(
3815 MOVIOpc, DL, VT, CurDAG->getTargetConstant(BFIImm, DL, VT));
3816
3817 // Create the BFI/BFXIL instruction.
3818 SDValue Ops[] = {And.getOperand(0), SDValue(MOVI, 0),
3819 CurDAG->getTargetConstant(ImmR, DL, VT),
3820 CurDAG->getTargetConstant(ImmS, DL, VT)};
3821 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
3822 CurDAG->SelectNodeTo(N, Opc, VT, Ops);
3823 return true;
3824}
3825
3827 SDValue &ShiftedOperand,
3828 uint64_t &EncodedShiftImm) {
3829 // Avoid folding Dst into ORR-with-shift if Dst has other uses than ORR.
3830 if (!Dst.hasOneUse())
3831 return false;
3832
3833 EVT VT = Dst.getValueType();
3834 assert((VT == MVT::i32 || VT == MVT::i64) &&
3835 "Caller should guarantee that VT is one of i32 or i64");
3836 const unsigned SizeInBits = VT.getSizeInBits();
3837
3838 SDLoc DL(Dst.getNode());
3839 uint64_t AndImm, ShlImm;
3840 if (isOpcWithIntImmediate(Dst.getNode(), ISD::AND, AndImm) &&
3841 isShiftedMask_64(AndImm)) {
3842 // Avoid transforming 'DstOp0' if it has other uses than the AND node.
3843 SDValue DstOp0 = Dst.getOperand(0);
3844 if (!DstOp0.hasOneUse())
3845 return false;
3846
3847 // An example to illustrate the transformation
3848 // From:
3849 // lsr x8, x1, #1
3850 // and x8, x8, #0x3f80
3851 // bfxil x8, x1, #0, #7
3852 // To:
3853 // and x8, x23, #0x7f
3854 // ubfx x9, x23, #8, #7
3855 // orr x23, x8, x9, lsl #7
3856 //
3857 // The number of instructions remains the same, but ORR is faster than BFXIL
3858 // on many AArch64 processors (or as good as BFXIL if not faster). Besides,
3859 // the dependency chain is improved after the transformation.
3860 uint64_t SrlImm;
3861 if (isOpcWithIntImmediate(DstOp0.getNode(), ISD::SRL, SrlImm)) {
3862 uint64_t NumTrailingZeroInShiftedMask = llvm::countr_zero(AndImm);
3863 if ((SrlImm + NumTrailingZeroInShiftedMask) < SizeInBits) {
3864 unsigned MaskWidth =
3865 llvm::countr_one(AndImm >> NumTrailingZeroInShiftedMask);
3866 unsigned UBFMOpc =
3867 (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
3868 SDNode *UBFMNode = CurDAG->getMachineNode(
3869 UBFMOpc, DL, VT, DstOp0.getOperand(0),
3870 CurDAG->getTargetConstant(SrlImm + NumTrailingZeroInShiftedMask, DL,
3871 VT),
3872 CurDAG->getTargetConstant(
3873 SrlImm + NumTrailingZeroInShiftedMask + MaskWidth - 1, DL, VT));
3874 ShiftedOperand = SDValue(UBFMNode, 0);
3875 EncodedShiftImm = AArch64_AM::getShifterImm(
3876 AArch64_AM::LSL, NumTrailingZeroInShiftedMask);
3877 return true;
3878 }
3879 }
3880 return false;
3881 }
3882
3883 if (isOpcWithIntImmediate(Dst.getNode(), ISD::SHL, ShlImm)) {
3884 ShiftedOperand = Dst.getOperand(0);
3885 EncodedShiftImm = AArch64_AM::getShifterImm(AArch64_AM::LSL, ShlImm);
3886 return true;
3887 }
3888
3889 uint64_t SrlImm;
3890 if (isOpcWithIntImmediate(Dst.getNode(), ISD::SRL, SrlImm)) {
3891 ShiftedOperand = Dst.getOperand(0);
3892 EncodedShiftImm = AArch64_AM::getShifterImm(AArch64_AM::LSR, SrlImm);
3893 return true;
3894 }
3895 return false;
3896}
3897
3898// Given an 'ISD::OR' node that is going to be selected as BFM, analyze
3899// the operands and select it to AArch64::ORR with shifted registers if
3900// that's more efficient. Returns true iff selection to AArch64::ORR happens.
3901static bool tryOrrWithShift(SDNode *N, SDValue OrOpd0, SDValue OrOpd1,
3902 SDValue Src, SDValue Dst, SelectionDAG *CurDAG,
3903 const bool BiggerPattern) {
3904 EVT VT = N->getValueType(0);
3905 assert(N->getOpcode() == ISD::OR && "Expect N to be an OR node");
3906 assert(((N->getOperand(0) == OrOpd0 && N->getOperand(1) == OrOpd1) ||
3907 (N->getOperand(1) == OrOpd0 && N->getOperand(0) == OrOpd1)) &&
3908 "Expect OrOpd0 and OrOpd1 to be operands of ISD::OR");
3909 assert((VT == MVT::i32 || VT == MVT::i64) &&
3910 "Expect result type to be i32 or i64 since N is combinable to BFM");
3911 SDLoc DL(N);
3912
3913 // Bail out if BFM simplifies away one node in BFM Dst.
3914 if (OrOpd1 != Dst)
3915 return false;
3916
3917 const unsigned OrrOpc = (VT == MVT::i32) ? AArch64::ORRWrs : AArch64::ORRXrs;
3918 // For "BFM Rd, Rn, #immr, #imms", it's known that BFM simplifies away fewer
3919 // nodes from Rn (or inserts additional shift node) if BiggerPattern is true.
3920 if (BiggerPattern) {
3921 uint64_t SrcAndImm;
3922 if (isOpcWithIntImmediate(OrOpd0.getNode(), ISD::AND, SrcAndImm) &&
3923 isMask_64(SrcAndImm) && OrOpd0.getOperand(0) == Src) {
3924 // OrOpd0 = AND Src, #Mask
3925 // So BFM simplifies away one AND node from Src and doesn't simplify away
3926 // nodes from Dst. If ORR with left-shifted operand also simplifies away
3927 // one node (from Rd), ORR is better since it has higher throughput and
3928 // smaller latency than BFM on many AArch64 processors (and for the rest
3929 // ORR is at least as good as BFM).
3930 SDValue ShiftedOperand;
3931 uint64_t EncodedShiftImm;
3932 if (isWorthFoldingIntoOrrWithShift(Dst, CurDAG, ShiftedOperand,
3933 EncodedShiftImm)) {
3934 SDValue Ops[] = {OrOpd0, ShiftedOperand,
3935 CurDAG->getTargetConstant(EncodedShiftImm, DL, VT)};
3936 CurDAG->SelectNodeTo(N, OrrOpc, VT, Ops);
3937 return true;
3938 }
3939 }
3940 return false;
3941 }
3942
3943 assert((!BiggerPattern) && "BiggerPattern should be handled above");
3944
3945 uint64_t ShlImm;
3946 if (isOpcWithIntImmediate(OrOpd0.getNode(), ISD::SHL, ShlImm)) {
3947 if (OrOpd0.getOperand(0) == Src && OrOpd0.hasOneUse()) {
3948 SDValue Ops[] = {
3949 Dst, Src,
3950 CurDAG->getTargetConstant(
3952 CurDAG->SelectNodeTo(N, OrrOpc, VT, Ops);
3953 return true;
3954 }
3955
3956 // Select the following pattern to left-shifted operand rather than BFI.
3957 // %val1 = op ..
3958 // %val2 = shl %val1, #imm
3959 // %res = or %val1, %val2
3960 //
3961 // If N is selected to be BFI, we know that
3962 // 1) OrOpd0 would be the operand from which extract bits (i.e., folded into
3963 // BFI) 2) OrOpd1 would be the destination operand (i.e., preserved)
3964 //
3965 // Instead of selecting N to BFI, fold OrOpd0 as a left shift directly.
3966 if (OrOpd0.getOperand(0) == OrOpd1) {
3967 SDValue Ops[] = {
3968 OrOpd1, OrOpd1,
3969 CurDAG->getTargetConstant(
3971 CurDAG->SelectNodeTo(N, OrrOpc, VT, Ops);
3972 return true;
3973 }
3974 }
3975
3976 uint64_t SrlImm;
3977 if (isOpcWithIntImmediate(OrOpd0.getNode(), ISD::SRL, SrlImm)) {
3978 // Select the following pattern to right-shifted operand rather than BFXIL.
3979 // %val1 = op ..
3980 // %val2 = lshr %val1, #imm
3981 // %res = or %val1, %val2
3982 //
3983 // If N is selected to be BFXIL, we know that
3984 // 1) OrOpd0 would be the operand from which extract bits (i.e., folded into
3985 // BFXIL) 2) OrOpd1 would be the destination operand (i.e., preserved)
3986 //
3987 // Instead of selecting N to BFXIL, fold OrOpd0 as a right shift directly.
3988 if (OrOpd0.getOperand(0) == OrOpd1) {
3989 SDValue Ops[] = {
3990 OrOpd1, OrOpd1,
3991 CurDAG->getTargetConstant(
3993 CurDAG->SelectNodeTo(N, OrrOpc, VT, Ops);
3994 return true;
3995 }
3996 }
3997
3998 return false;
3999}
4000
4001static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits,
4002 SelectionDAG *CurDAG) {
4003 assert(N->getOpcode() == ISD::OR && "Expect a OR operation");
4004
4005 EVT VT = N->getValueType(0);
4006 if (VT != MVT::i32 && VT != MVT::i64)
4007 return false;
4008
4009 unsigned BitWidth = VT.getSizeInBits();
4010
4011 // Because of simplify-demanded-bits in DAGCombine, involved masks may not
4012 // have the expected shape. Try to undo that.
4013
4014 unsigned NumberOfIgnoredLowBits = UsefulBits.countr_zero();
4015 unsigned NumberOfIgnoredHighBits = UsefulBits.countl_zero();
4016
4017 // Given a OR operation, check if we have the following pattern
4018 // ubfm c, b, imm, imm2 (or something that does the same jobs, see
4019 // isBitfieldExtractOp)
4020 // d = e & mask2 ; where mask is a binary sequence of 1..10..0 and
4021 // countTrailingZeros(mask2) == imm2 - imm + 1
4022 // f = d | c
4023 // if yes, replace the OR instruction with:
4024 // f = BFM Opd0, Opd1, LSB, MSB ; where LSB = imm, and MSB = imm2
4025
4026 // OR is commutative, check all combinations of operand order and values of
4027 // BiggerPattern, i.e.
4028 // Opd0, Opd1, BiggerPattern=false
4029 // Opd1, Opd0, BiggerPattern=false
4030 // Opd0, Opd1, BiggerPattern=true
4031 // Opd1, Opd0, BiggerPattern=true
4032 // Several of these combinations may match, so check with BiggerPattern=false
4033 // first since that will produce better results by matching more instructions
4034 // and/or inserting fewer extra instructions.
4035 for (int I = 0; I < 4; ++I) {
4036
4037 SDValue Dst, Src;
4038 unsigned ImmR, ImmS;
4039 bool BiggerPattern = I / 2;
4040 SDValue OrOpd0Val = N->getOperand(I % 2);
4041 SDNode *OrOpd0 = OrOpd0Val.getNode();
4042 SDValue OrOpd1Val = N->getOperand((I + 1) % 2);
4043 SDNode *OrOpd1 = OrOpd1Val.getNode();
4044
4045 unsigned BFXOpc;
4046 int DstLSB, Width;
4047 if (isBitfieldExtractOp(CurDAG, OrOpd0, BFXOpc, Src, ImmR, ImmS,
4048 NumberOfIgnoredLowBits, BiggerPattern)) {
4049 // Check that the returned opcode is compatible with the pattern,
4050 // i.e., same type and zero extended (U and not S)
4051 if ((BFXOpc != AArch64::UBFMXri && VT == MVT::i64) ||
4052 (BFXOpc != AArch64::UBFMWri && VT == MVT::i32))
4053 continue;
4054
4055 // Compute the width of the bitfield insertion
4056 DstLSB = 0;
4057 Width = ImmS - ImmR + 1;
4058 // FIXME: This constraint is to catch bitfield insertion we may
4059 // want to widen the pattern if we want to grab general bitfield
4060 // move case
4061 if (Width <= 0)
4062 continue;
4063
4064 // If the mask on the insertee is correct, we have a BFXIL operation. We
4065 // can share the ImmR and ImmS values from the already-computed UBFM.
4066 } else if (isBitfieldPositioningOp(CurDAG, OrOpd0Val,
4067 BiggerPattern,
4068 Src, DstLSB, Width)) {
4069 ImmR = (BitWidth - DstLSB) % BitWidth;
4070 ImmS = Width - 1;
4071 } else
4072 continue;
4073
4074 // Check the second part of the pattern
4075 EVT VT = OrOpd1Val.getValueType();
4076 assert((VT == MVT::i32 || VT == MVT::i64) && "unexpected OR operand");
4077
4078 // Compute the Known Zero for the candidate of the first operand.
4079 // This allows to catch more general case than just looking for
4080 // AND with imm. Indeed, simplify-demanded-bits may have removed
4081 // the AND instruction because it proves it was useless.
4082 KnownBits Known = CurDAG->computeKnownBits(OrOpd1Val);
4083
4084 // Check if there is enough room for the second operand to appear
4085 // in the first one
4086 APInt BitsToBeInserted =
4087 APInt::getBitsSet(Known.getBitWidth(), DstLSB, DstLSB + Width);
4088
4089 if ((BitsToBeInserted & ~Known.Zero) != 0)
4090 continue;
4091
4092 // Set the first operand
4093 uint64_t Imm;
4094 if (isOpcWithIntImmediate(OrOpd1, ISD::AND, Imm) &&
4095 isBitfieldDstMask(Imm, BitsToBeInserted, NumberOfIgnoredHighBits, VT))
4096 // In that case, we can eliminate the AND
4097 Dst = OrOpd1->getOperand(0);
4098 else
4099 // Maybe the AND has been removed by simplify-demanded-bits
4100 // or is useful because it discards more bits
4101 Dst = OrOpd1Val;
4102
4103 // Before selecting ISD::OR node to AArch64::BFM, see if an AArch64::ORR
4104 // with shifted operand is more efficient.
4105 if (tryOrrWithShift(N, OrOpd0Val, OrOpd1Val, Src, Dst, CurDAG,
4106 BiggerPattern))
4107 return true;
4108
4109 // both parts match
4110 SDLoc DL(N);
4111 SDValue Ops[] = {Dst, Src, CurDAG->getTargetConstant(ImmR, DL, VT),
4112 CurDAG->getTargetConstant(ImmS, DL, VT)};
4113 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4114 CurDAG->SelectNodeTo(N, Opc, VT, Ops);
4115 return true;
4116 }
4117
4118 // Generate a BFXIL from 'or (and X, Mask0Imm), (and Y, Mask1Imm)' iff
4119 // Mask0Imm and ~Mask1Imm are equivalent and one of the MaskImms is a shifted
4120 // mask (e.g., 0x000ffff0).
4121 uint64_t Mask0Imm, Mask1Imm;
4122 SDValue And0 = N->getOperand(0);
4123 SDValue And1 = N->getOperand(1);
4124 if (And0.hasOneUse() && And1.hasOneUse() &&
4125 isOpcWithIntImmediate(And0.getNode(), ISD::AND, Mask0Imm) &&
4126 isOpcWithIntImmediate(And1.getNode(), ISD::AND, Mask1Imm) &&
4127 APInt(BitWidth, Mask0Imm) == ~APInt(BitWidth, Mask1Imm) &&
4128 (isShiftedMask(Mask0Imm, VT) || isShiftedMask(Mask1Imm, VT))) {
4129
4130 // ORR is commutative, so canonicalize to the form 'or (and X, Mask0Imm),
4131 // (and Y, Mask1Imm)' where Mask1Imm is the shifted mask masking off the
4132 // bits to be inserted.
4133 if (isShiftedMask(Mask0Imm, VT)) {
4134 std::swap(And0, And1);
4135 std::swap(Mask0Imm, Mask1Imm);
4136 }
4137
4138 SDValue Src = And1->getOperand(0);
4139 SDValue Dst = And0->getOperand(0);
4140 unsigned LSB = llvm::countr_zero(Mask1Imm);
4141 int Width = BitWidth - APInt(BitWidth, Mask0Imm).popcount();
4142
4143 // The BFXIL inserts the low-order bits from a source register, so right
4144 // shift the needed bits into place.
4145 SDLoc DL(N);
4146 unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4147 uint64_t LsrImm = LSB;
4148 if (Src->hasOneUse() &&
4149 isOpcWithIntImmediate(Src.getNode(), ISD::SRL, LsrImm) &&
4150 (LsrImm + LSB) < BitWidth) {
4151 Src = Src->getOperand(0);
4152 LsrImm += LSB;
4153 }
4154
4155 SDNode *LSR = CurDAG->getMachineNode(
4156 ShiftOpc, DL, VT, Src, CurDAG->getTargetConstant(LsrImm, DL, VT),
4157 CurDAG->getTargetConstant(BitWidth - 1, DL, VT));
4158
4159 // BFXIL is an alias of BFM, so translate to BFM operands.
4160 unsigned ImmR = (BitWidth - LSB) % BitWidth;
4161 unsigned ImmS = Width - 1;
4162
4163 // Create the BFXIL instruction.
4164 SDValue Ops[] = {Dst, SDValue(LSR, 0),
4165 CurDAG->getTargetConstant(ImmR, DL, VT),
4166 CurDAG->getTargetConstant(ImmS, DL, VT)};
4167 unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
4168 CurDAG->SelectNodeTo(N, Opc, VT, Ops);
4169 return true;
4170 }
4171
4172 return false;
4173}
4174
4175bool AArch64DAGToDAGISel::tryBitfieldInsertOp(SDNode *N) {
4176 if (N->getOpcode() != ISD::OR)
4177 return false;
4178
4179 APInt NUsefulBits;
4180 getUsefulBits(SDValue(N, 0), NUsefulBits);
4181
4182 // If all bits are not useful, just return UNDEF.
4183 if (!NUsefulBits) {
4184 CurDAG->SelectNodeTo(N, TargetOpcode::IMPLICIT_DEF, N->getValueType(0));
4185 return true;
4186 }
4187
4188 if (tryBitfieldInsertOpFromOr(N, NUsefulBits, CurDAG))
4189 return true;
4190
4191 return tryBitfieldInsertOpFromOrAndImm(N, CurDAG);
4192}
4193
4194/// SelectBitfieldInsertInZeroOp - Match a UBFIZ instruction that is the
4195/// equivalent of a left shift by a constant amount followed by an and masking
4196/// out a contiguous set of bits.
4197bool AArch64DAGToDAGISel::tryBitfieldInsertInZeroOp(SDNode *N) {
4198 if (N->getOpcode() != ISD::AND)
4199 return false;
4200
4201 EVT VT = N->getValueType(0);
4202 if (VT != MVT::i32 && VT != MVT::i64)
4203 return false;
4204
4205 SDValue Op0;
4206 int DstLSB, Width;
4207 if (!isBitfieldPositioningOp(CurDAG, SDValue(N, 0), /*BiggerPattern=*/false,
4208 Op0, DstLSB, Width))
4209 return false;
4210
4211 // ImmR is the rotate right amount.
4212 unsigned ImmR = (VT.getSizeInBits() - DstLSB) % VT.getSizeInBits();
4213 // ImmS is the most significant bit of the source to be moved.
4214 unsigned ImmS = Width - 1;
4215
4216 SDLoc DL(N);
4217 SDValue Ops[] = {Op0, CurDAG->getTargetConstant(ImmR, DL, VT),
4218 CurDAG->getTargetConstant(ImmS, DL, VT)};
4219 unsigned Opc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
4220 CurDAG->SelectNodeTo(N, Opc, VT, Ops);
4221 return true;
4222}
4223
4225 SDValue &FixedPos,
4226 unsigned RegWidth,
4227 bool isReciprocal) {
4228 APFloat FVal(0.0);
4230 FVal = CN->getValueAPF();
4231 else if (LoadSDNode *LN = dyn_cast<LoadSDNode>(N)) {
4232 // Some otherwise illegal constants are allowed in this case.
4233 if (LN->getOperand(1).getOpcode() != AArch64ISD::ADDlow ||
4234 !isa<ConstantPoolSDNode>(LN->getOperand(1)->getOperand(1)))
4235 return false;
4236
4237 ConstantPoolSDNode *CN =
4238 dyn_cast<ConstantPoolSDNode>(LN->getOperand(1)->getOperand(1));
4239 FVal = cast<ConstantFP>(CN->getConstVal())->getValueAPF();
4240 } else
4241 return false;
4242
4243 if (unsigned FBits =
4244 CheckFixedPointOperandConstant(FVal, RegWidth, isReciprocal)) {
4245 FixedPos = CurDAG->getTargetConstant(FBits, SDLoc(N), MVT::i32);
4246 return true;
4247 }
4248
4249 return false;
4250}
4251
4253 SDValue N,
4254 SDValue &FixedPos,
4255 unsigned RegWidth,
4256 bool isReciprocal) {
4257 if ((N.getOpcode() == AArch64ISD::NVCAST || N.getOpcode() == ISD::BITCAST) &&
4258 N.getValueType().getScalarSizeInBits() ==
4259 N.getOperand(0).getValueType().getScalarSizeInBits())
4260 N = N.getOperand(0);
4261
4262 auto ImmToFloat = [RegWidth](APInt Imm) {
4263 switch (RegWidth) {
4264 case 16:
4265 return APFloat(APFloat::IEEEhalf(), Imm);
4266 case 32:
4267 return APFloat(APFloat::IEEEsingle(), Imm);
4268 case 64:
4269 return APFloat(APFloat::IEEEdouble(), Imm);
4270 default:
4271 llvm_unreachable("Unexpected RegWidth!");
4272 };
4273 };
4274
4275 APFloat FVal(0.0);
4276 switch (N->getOpcode()) {
4277 case AArch64ISD::MOVIshift:
4278 FVal = ImmToFloat(APInt(RegWidth, N.getConstantOperandVal(0)
4279 << N.getConstantOperandVal(1)));
4280 break;
4281 case AArch64ISD::FMOV:
4282 FVal = ImmToFloat(DecodeFMOVImm(N.getConstantOperandVal(0), RegWidth));
4283 break;
4284 case AArch64ISD::DUP:
4285 if (isa<ConstantSDNode>(N.getOperand(0)))
4286 FVal = ImmToFloat(N.getConstantOperandAPInt(0).trunc(RegWidth));
4287 else
4288 return false;
4289 break;
4290 default:
4291 return false;
4292 }
4293
4294 if (unsigned FBits =
4295 CheckFixedPointOperandConstant(FVal, RegWidth, isReciprocal)) {
4296 FixedPos = CurDAG->getTargetConstant(FBits, SDLoc(N), MVT::i32);
4297 return true;
4298 }
4299
4300 return false;
4301}
4302
4303bool AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos,
4304 unsigned RegWidth) {
4305 return checkCVTFixedPointOperandWithFBits(CurDAG, N, FixedPos, RegWidth,
4306 /*isReciprocal*/ false);
4307}
4308
4309bool AArch64DAGToDAGISel::SelectCVTFixedPointVec(SDValue N, SDValue &FixedPos,
4310 unsigned RegWidth) {
4312 CurDAG, N, FixedPos, RegWidth, /*isReciprocal*/ false);
4313}
4314
4315bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperandVec(SDValue N,
4316 SDValue &FixedPos,
4317 unsigned RegWidth) {
4319 CurDAG, N, FixedPos, RegWidth, /*isReciprocal*/ true);
4320}
4321
4322bool AArch64DAGToDAGISel::SelectCVTFixedPosRecipOperand(SDValue N,
4323 SDValue &FixedPos,
4324 unsigned RegWidth) {
4325 return checkCVTFixedPointOperandWithFBits(CurDAG, N, FixedPos, RegWidth,
4326 /*isReciprocal*/ true);
4327}
4328
4329// Inspects a register string of the form o0:op1:CRn:CRm:op2 gets the fields
4330// of the string and obtains the integer values from them and combines these
4331// into a single value to be used in the MRS/MSR instruction.
4334 RegString.split(Fields, ':');
4335
4336 if (Fields.size() == 1)
4337 return -1;
4338
4339 assert(Fields.size() == 5
4340 && "Invalid number of fields in read register string");
4341
4343 bool AllIntFields = true;
4344
4345 for (StringRef Field : Fields) {
4346 unsigned IntField;
4347 AllIntFields &= !Field.getAsInteger(10, IntField);
4348 Ops.push_back(IntField);
4349 }
4350
4351 assert(AllIntFields &&
4352 "Unexpected non-integer value in special register string.");
4353 (void)AllIntFields;
4354
4355 // Need to combine the integer fields of the string into a single value
4356 // based on the bit encoding of MRS/MSR instruction.
4357 return (Ops[0] << 14) | (Ops[1] << 11) | (Ops[2] << 7) | (Ops[3] << 3) |
4358 (Ops[4]);
4359}
4360
4361// Lower the read_register intrinsic to an MRS instruction node if the special
4362// register string argument is either of the form detailed in the ALCE (the
4363// form described in getIntOperandsFromRegisterString) or is a named register
4364// known by the MRS SysReg mapper.
4365bool AArch64DAGToDAGISel::tryReadRegister(SDNode *N) {
4366 const auto *MD = cast<MDNodeSDNode>(N->getOperand(1));
4367 const auto *RegString = cast<MDString>(MD->getMD()->getOperand(0));
4368 SDLoc DL(N);
4369
4370 bool ReadIs128Bit = N->getOpcode() == AArch64ISD::MRRS;
4371
4372 unsigned Opcode64Bit = AArch64::MRS;
4373 int Imm = getIntOperandFromRegisterString(RegString->getString());
4374 if (Imm == -1) {
4375 // No match, Use the sysreg mapper to map the remaining possible strings to
4376 // the value for the register to be used for the instruction operand.
4377 const auto *TheReg =
4378 AArch64SysReg::lookupSysRegByName(RegString->getString());
4379 if (TheReg && TheReg->Readable &&
4380 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4381 Imm = TheReg->Encoding;
4382 else
4383 Imm = AArch64SysReg::parseGenericRegister(RegString->getString());
4384
4385 if (Imm == -1) {
4386 // Still no match, see if this is "pc" or give up.
4387 if (!ReadIs128Bit && RegString->getString() == "pc") {
4388 Opcode64Bit = AArch64::ADR;
4389 Imm = 0;
4390 } else {
4391 // Not a system register. It may name an allocatable 64-bit GPR/FPR read
4392 // by the MSVC __getReg/__getRegFp intrinsics. Emit a pseudo that
4393 // carries the source register as an immediate so the read does not
4394 // reference an undefined physical register (which the machine verifier
4395 // rejects); the AsmPrinter materializes the real mov/fmov.
4396 Register PReg = Subtarget->getTargetLowering()->matchRegisterName(
4397 RegString->getString());
4398 unsigned PseudoOp = 0;
4399 if (AArch64::GPR64RegClass.contains(PReg))
4400 PseudoOp = AArch64::READ_REGISTER_GPR64;
4401 else if (AArch64::FPR64RegClass.contains(PReg))
4402 PseudoOp = AArch64::READ_REGISTER_FPR64;
4403 if (!ReadIs128Bit && PseudoOp && N->getValueType(0) == MVT::i64) {
4404 CurDAG->SelectNodeTo(N, PseudoOp, MVT::i64, MVT::Other,
4405 {CurDAG->getTargetConstant(PReg, DL, MVT::i32),
4406 N->getOperand(0)});
4407 return true;
4408 }
4409 return false;
4410 }
4411 }
4412 }
4413
4414 SDValue InChain = N->getOperand(0);
4415 SDValue SysRegImm = CurDAG->getTargetConstant(Imm, DL, MVT::i32);
4416 if (!ReadIs128Bit) {
4417 CurDAG->SelectNodeTo(N, Opcode64Bit, MVT::i64, MVT::Other /* Chain */,
4418 {SysRegImm, InChain});
4419 } else {
4420 SDNode *MRRS = CurDAG->getMachineNode(
4421 AArch64::MRRS, DL,
4422 {MVT::Untyped /* XSeqPair */, MVT::Other /* Chain */},
4423 {SysRegImm, InChain});
4424
4425 // Sysregs are not endian. The even register always contains the low half
4426 // of the register.
4427 SDValue Lo = CurDAG->getTargetExtractSubreg(AArch64::sube64, DL, MVT::i64,
4428 SDValue(MRRS, 0));
4429 SDValue Hi = CurDAG->getTargetExtractSubreg(AArch64::subo64, DL, MVT::i64,
4430 SDValue(MRRS, 0));
4431 SDValue OutChain = SDValue(MRRS, 1);
4432
4433 ReplaceUses(SDValue(N, 0), Lo);
4434 ReplaceUses(SDValue(N, 1), Hi);
4435 ReplaceUses(SDValue(N, 2), OutChain);
4436 };
4437 return true;
4438}
4439
4440// Lower the write_register intrinsic to an MSR instruction node if the special
4441// register string argument is either of the form detailed in the ALCE (the
4442// form described in getIntOperandsFromRegisterString) or is a named register
4443// known by the MSR SysReg mapper.
4444bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *N) {
4445 const auto *MD = cast<MDNodeSDNode>(N->getOperand(1));
4446 const auto *RegString = cast<MDString>(MD->getMD()->getOperand(0));
4447 SDLoc DL(N);
4448
4449 bool WriteIs128Bit = N->getOpcode() == AArch64ISD::MSRR;
4450
4451 if (!WriteIs128Bit) {
4452 // Check if the register was one of those allowed as the pstatefield value
4453 // in the MSR (immediate) instruction. To accept the values allowed in the
4454 // pstatefield for the MSR (immediate) instruction, we also require that an
4455 // immediate value has been provided as an argument, we know that this is
4456 // the case as it has been ensured by semantic checking.
4457 auto trySelectPState = [&](auto PMapper, unsigned State) {
4458 if (PMapper) {
4459 assert(isa<ConstantSDNode>(N->getOperand(2)) &&
4460 "Expected a constant integer expression.");
4461 unsigned Reg = PMapper->Encoding;
4462 uint64_t Immed = N->getConstantOperandVal(2);
4463 CurDAG->SelectNodeTo(
4464 N, State, MVT::Other, CurDAG->getTargetConstant(Reg, DL, MVT::i32),
4465 CurDAG->getTargetConstant(Immed, DL, MVT::i16), N->getOperand(0));
4466 return true;
4467 }
4468 return false;
4469 };
4470
4471 if (trySelectPState(
4472 AArch64PState::lookupPStateImm0_15ByName(RegString->getString()),
4473 AArch64::MSRpstateImm4))
4474 return true;
4475 if (trySelectPState(
4476 AArch64PState::lookupPStateImm0_1ByName(RegString->getString()),
4477 AArch64::MSRpstateImm1))
4478 return true;
4479 }
4480
4481 int Imm = getIntOperandFromRegisterString(RegString->getString());
4482 if (Imm == -1) {
4483 // Use the sysreg mapper to attempt to map the remaining possible strings
4484 // to the value for the register to be used for the MSR (register)
4485 // instruction operand.
4486 auto TheReg = AArch64SysReg::lookupSysRegByName(RegString->getString());
4487 if (TheReg && TheReg->Writeable &&
4488 TheReg->haveFeatures(Subtarget->getFeatureBits()))
4489 Imm = TheReg->Encoding;
4490 else
4491 Imm = AArch64SysReg::parseGenericRegister(RegString->getString());
4492
4493 if (Imm == -1) {
4494 // Used by the MSVC __setReg/__setRegFp intrinsics. Copy the value into
4495 // the physical register and keep it live with a FAKE_USE so the write is
4496 // not dead-eliminated. (getRegisterByName rejects allocatable registers,
4497 // so the generic write path cannot handle these.)
4498 Register PReg = Subtarget->getTargetLowering()->matchRegisterName(
4499 RegString->getString());
4500 bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
4501 bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
4502 if (!WriteIs128Bit && (IsGPR || IsFPR) &&
4503 N->getOperand(2).getValueType() == MVT::i64) {
4504 SDValue Copy =
4505 CurDAG->getCopyToReg(N->getOperand(0), DL, PReg, N->getOperand(2));
4506 SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
4507 SDNode *FakeUse = CurDAG->getMachineNode(TargetOpcode::FAKE_USE, DL,
4508 MVT::Other, {RegOp, Copy});
4509 ReplaceUses(SDValue(N, 0), SDValue(FakeUse, 0));
4510 CurDAG->RemoveDeadNode(N);
4511 return true;
4512 }
4513 return false;
4514 }
4515 }
4516
4517 SDValue InChain = N->getOperand(0);
4518 if (!WriteIs128Bit) {
4519 CurDAG->SelectNodeTo(N, AArch64::MSR, MVT::Other,
4520 CurDAG->getTargetConstant(Imm, DL, MVT::i32),
4521 N->getOperand(2), InChain);
4522 } else {
4523 // No endian swap. The lower half always goes into the even subreg, and the
4524 // higher half always into the odd supreg.
4525 SDNode *Pair = CurDAG->getMachineNode(
4526 TargetOpcode::REG_SEQUENCE, DL, MVT::Untyped /* XSeqPair */,
4527 {CurDAG->getTargetConstant(AArch64::XSeqPairsClassRegClass.getID(), DL,
4528 MVT::i32),
4529 N->getOperand(2),
4530 CurDAG->getTargetConstant(AArch64::sube64, DL, MVT::i32),
4531 N->getOperand(3),
4532 CurDAG->getTargetConstant(AArch64::subo64, DL, MVT::i32)});
4533
4534 CurDAG->SelectNodeTo(N, AArch64::MSRR, MVT::Other,
4535 CurDAG->getTargetConstant(Imm, DL, MVT::i32),
4536 SDValue(Pair, 0), InChain);
4537 }
4538
4539 return true;
4540}
4541
4542/// We've got special pseudo-instructions for these
4543bool AArch64DAGToDAGISel::SelectCMP_SWAP(SDNode *N) {
4544 unsigned Opcode;
4545 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT();
4546
4547 // Leave IR for LSE if subtarget supports it.
4548 if (Subtarget->hasLSE()) return false;
4549
4550 if (MemTy == MVT::i8)
4551 Opcode = AArch64::CMP_SWAP_8;
4552 else if (MemTy == MVT::i16)
4553 Opcode = AArch64::CMP_SWAP_16;
4554 else if (MemTy == MVT::i32)
4555 Opcode = AArch64::CMP_SWAP_32;
4556 else if (MemTy == MVT::i64)
4557 Opcode = AArch64::CMP_SWAP_64;
4558 else
4559 llvm_unreachable("Unknown AtomicCmpSwap type");
4560
4561 MVT RegTy = MemTy == MVT::i64 ? MVT::i64 : MVT::i32;
4562 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3),
4563 N->getOperand(0)};
4564 SDNode *CmpSwap = CurDAG->getMachineNode(
4565 Opcode, SDLoc(N),
4566 CurDAG->getVTList(RegTy, MVT::i32, MVT::Other), Ops);
4567
4568 MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand();
4569 CurDAG->setNodeMemRefs(cast<MachineSDNode>(CmpSwap), {MemOp});
4570
4571 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0));
4572 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2));
4573 CurDAG->RemoveDeadNode(N);
4574
4575 return true;
4576}
4577
4579AArch64DAGToDAGISel::decodeMemoryHintFlags(MachineMemOperand *MMO) const {
4580 int MemoryHint = -1;
4581 const MDNode *MemCacheHint = MMO->getMemCacheHint();
4582 if (!MemCacheHint)
4583 return AArch64MemoryHint::NONE;
4584
4585 for (unsigned I = 0; I + 1 < MemCacheHint->getNumOperands(); I += 2) {
4586 if (MemCacheHint->getOperand(I).equalsStr("aarch64.mem_hint")) {
4587 const Metadata *Val = MemCacheHint->getOperand(I + 1).get();
4589 ->getZExtValue();
4590 }
4591 }
4592
4593 return toAArch64MemoryHint(MemoryHint);
4594}
4595
4596bool AArch64DAGToDAGISel::isAtomicMemoryHint(SDNode *N,
4597 AArch64MemoryHint Hint) const {
4598 return decodeMemoryHintFlags(cast<MemSDNode>(N)->getMemOperand()) == Hint;
4599}
4600
4601bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDValue N, MVT VT, SDValue &Imm,
4602 SDValue &Shift, bool Negate) {
4603 if (!isa<ConstantSDNode>(N))
4604 return false;
4605
4606 APInt Val =
4607 cast<ConstantSDNode>(N)->getAPIntValue().trunc(VT.getFixedSizeInBits());
4608
4609 return SelectSVEAddSubImm(SDLoc(N), Val, VT, Imm, Shift, Negate);
4610}
4611
4612bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDLoc DL, APInt Val, MVT VT,
4613 SDValue &Imm, SDValue &Shift,
4614 bool Negate) {
4615 if (Negate)
4616 Val = -Val;
4617
4618 switch (VT.SimpleTy) {
4619 case MVT::i8:
4620 // All immediates are supported.
4621 Shift = CurDAG->getTargetConstant(0, DL, MVT::i32);
4622 Imm = CurDAG->getTargetConstant(Val.getZExtValue(), DL, MVT::i32);
4623 return true;
4624 case MVT::i16:
4625 case MVT::i32:
4626 case MVT::i64:
4627 // Support 8bit unsigned immediates.
4628 if ((Val & ~0xff) == 0) {
4629 Shift = CurDAG->getTargetConstant(0, DL, MVT::i32);
4630 Imm = CurDAG->getTargetConstant(Val.getZExtValue(), DL, MVT::i32);
4631 return true;
4632 }
4633 // Support 16bit unsigned immediates that are a multiple of 256.
4634 if ((Val & ~0xff00) == 0) {
4635 Shift = CurDAG->getTargetConstant(8, DL, MVT::i32);
4636 Imm = CurDAG->getTargetConstant(Val.lshr(8).getZExtValue(), DL, MVT::i32);
4637 return true;
4638 }
4639 break;
4640 default:
4641 break;
4642 }
4643
4644 return false;
4645}
4646
4647bool AArch64DAGToDAGISel::SelectSVEAddSubSSatImm(SDValue N, MVT VT,
4648 SDValue &Imm, SDValue &Shift,
4649 bool Negate) {
4650 if (!isa<ConstantSDNode>(N))
4651 return false;
4652
4653 SDLoc DL(N);
4654 int64_t Val = cast<ConstantSDNode>(N)
4655 ->getAPIntValue()
4657 .getSExtValue();
4658
4659 if (Negate)
4660 Val = -Val;
4661
4662 // Signed saturating instructions treat their immediate operand as unsigned,
4663 // whereas the related intrinsics define their operands to be signed. This
4664 // means we can only use the immediate form when the operand is non-negative.
4665 if (Val < 0)
4666 return false;
4667
4668 switch (VT.SimpleTy) {
4669 case MVT::i8:
4670 // All positive immediates are supported.
4671 Shift = CurDAG->getTargetConstant(0, DL, MVT::i32);
4672 Imm = CurDAG->getTargetConstant(Val, DL, MVT::i32);
4673 return true;
4674 case MVT::i16:
4675 case MVT::i32:
4676 case MVT::i64:
4677 // Support 8bit positive immediates.
4678 if (Val <= 255) {
4679 Shift = CurDAG->getTargetConstant(0, DL, MVT::i32);
4680 Imm = CurDAG->getTargetConstant(Val, DL, MVT::i32);
4681 return true;
4682 }
4683 // Support 16bit positive immediates that are a multiple of 256.
4684 if (Val <= 65280 && Val % 256 == 0) {
4685 Shift = CurDAG->getTargetConstant(8, DL, MVT::i32);
4686 Imm = CurDAG->getTargetConstant(Val >> 8, DL, MVT::i32);
4687 return true;
4688 }
4689 break;
4690 default:
4691 break;
4692 }
4693
4694 return false;
4695}
4696
4697bool AArch64DAGToDAGISel::SelectSVECpyDupImm(SDValue N, MVT VT, SDValue &Imm,
4698 SDValue &Shift) {
4699 if (!isa<ConstantSDNode>(N))
4700 return false;
4701
4702 SDLoc DL(N);
4703 int64_t Val = cast<ConstantSDNode>(N)
4704 ->getAPIntValue()
4705 .trunc(VT.getFixedSizeInBits())
4706 .getSExtValue();
4707 int32_t ImmVal, ShiftVal;
4708 if (!AArch64_AM::isSVECpyDupImm(VT.getScalarSizeInBits(), Val, ImmVal,
4709 ShiftVal))
4710 return false;
4711
4712 Shift = CurDAG->getTargetConstant(ShiftVal, DL, MVT::i32);
4713 Imm = CurDAG->getTargetConstant(ImmVal, DL, MVT::i32);
4714 return true;
4715}
4716
4717bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDValue N, SDValue &Imm) {
4718 if (auto CNode = dyn_cast<ConstantSDNode>(N))
4719 return SelectSVESignedArithImm(SDLoc(N), CNode->getAPIntValue(), Imm);
4720 return false;
4721}
4722
4723bool AArch64DAGToDAGISel::SelectSVESignedArithImm(SDLoc DL, APInt Val,
4724 SDValue &Imm) {
4725 int64_t ImmVal = Val.getSExtValue();
4726 if (ImmVal >= -128 && ImmVal < 128) {
4727 Imm = CurDAG->getSignedTargetConstant(ImmVal, DL, MVT::i32);
4728 return true;
4729 }
4730 return false;
4731}
4732
4733bool AArch64DAGToDAGISel::SelectSVEArithImm(SDValue N, MVT VT, SDValue &Imm) {
4734 if (auto CNode = dyn_cast<ConstantSDNode>(N)) {
4735 uint64_t ImmVal = CNode->getZExtValue();
4736
4737 switch (VT.SimpleTy) {
4738 case MVT::i8:
4739 ImmVal &= 0xFF;
4740 break;
4741 case MVT::i16:
4742 ImmVal &= 0xFFFF;
4743 break;
4744 case MVT::i32:
4745 ImmVal &= 0xFFFFFFFF;
4746 break;
4747 case MVT::i64:
4748 break;
4749 default:
4750 llvm_unreachable("Unexpected type");
4751 }
4752
4753 if (ImmVal < 256) {
4754 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(N), MVT::i32);
4755 return true;
4756 }
4757 }
4758 return false;
4759}
4760
4761bool AArch64DAGToDAGISel::SelectSVELogicalImm(SDValue N, MVT VT, SDValue &Imm,
4762 bool Invert) {
4763 uint64_t ImmVal;
4764 if (auto CI = dyn_cast<ConstantSDNode>(N))
4765 ImmVal = CI->getZExtValue();
4766 else if (auto CFP = dyn_cast<ConstantFPSDNode>(N))
4767 ImmVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
4768 else
4769 return false;
4770
4771 if (Invert)
4772 ImmVal = ~ImmVal;
4773
4774 uint64_t encoding;
4775 if (!AArch64_AM::isSVELogicalImm(VT.getScalarSizeInBits(), ImmVal, encoding))
4776 return false;
4777
4778 Imm = CurDAG->getTargetConstant(encoding, SDLoc(N), MVT::i64);
4779 return true;
4780}
4781
4782// SVE shift intrinsics allow shift amounts larger than the element's bitwidth.
4783// Rather than attempt to normalise everything we can sometimes saturate the
4784// shift amount during selection. This function also allows for consistent
4785// isel patterns by ensuring the resulting "Imm" node is of the i32 type
4786// required by the instructions.
4787bool AArch64DAGToDAGISel::SelectSVEShiftImm(SDValue N, uint64_t Low,
4788 uint64_t High, bool AllowSaturation,
4789 SDValue &Imm) {
4790 if (auto *CN = dyn_cast<ConstantSDNode>(N)) {
4791 uint64_t ImmVal = CN->getZExtValue();
4792
4793 // Reject shift amounts that are too small.
4794 if (ImmVal < Low)
4795 return false;
4796
4797 // Reject or saturate shift amounts that are too big.
4798 if (ImmVal > High) {
4799 if (!AllowSaturation)
4800 return false;
4801 ImmVal = High;
4802 }
4803
4804 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(N), MVT::i32);
4805 return true;
4806 }
4807
4808 return false;
4809}
4810
4811bool AArch64DAGToDAGISel::trySelectStackSlotTagP(SDNode *N) {
4812 // tagp(FrameIndex, IRGstack, tag_offset):
4813 // since the offset between FrameIndex and IRGstack is a compile-time
4814 // constant, this can be lowered to a single ADDG instruction.
4815 if (!(isa<FrameIndexSDNode>(N->getOperand(1)))) {
4816 return false;
4817 }
4818
4819 SDValue IRG_SP = N->getOperand(2);
4820 if (IRG_SP->getOpcode() != ISD::INTRINSIC_W_CHAIN ||
4821 IRG_SP->getConstantOperandVal(1) != Intrinsic::aarch64_irg_sp) {
4822 return false;
4823 }
4824
4825 const TargetLowering *TLI = getTargetLowering();
4826 SDLoc DL(N);
4827 int FI = cast<FrameIndexSDNode>(N->getOperand(1))->getIndex();
4828 SDValue FiOp = CurDAG->getTargetFrameIndex(
4829 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
4830 int TagOffset = N->getConstantOperandVal(3);
4831
4832 SDNode *Out = CurDAG->getMachineNode(
4833 AArch64::TAGPstack, DL, MVT::i64,
4834 {FiOp, CurDAG->getTargetConstant(0, DL, MVT::i64), N->getOperand(2),
4835 CurDAG->getTargetConstant(TagOffset, DL, MVT::i64)});
4836 ReplaceNode(N, Out);
4837 return true;
4838}
4839
4840void AArch64DAGToDAGISel::SelectTagP(SDNode *N) {
4841 assert(isa<ConstantSDNode>(N->getOperand(3)) &&
4842 "llvm.aarch64.tagp third argument must be an immediate");
4843 if (trySelectStackSlotTagP(N))
4844 return;
4845 // FIXME: above applies in any case when offset between Op1 and Op2 is a
4846 // compile-time constant, not just for stack allocations.
4847
4848 // General case for unrelated pointers in Op1 and Op2.
4849 SDLoc DL(N);
4850 int TagOffset = N->getConstantOperandVal(3);
4851 SDNode *N1 = CurDAG->getMachineNode(AArch64::SUBP, DL, MVT::i64,
4852 {N->getOperand(1), N->getOperand(2)});
4853 SDNode *N2 = CurDAG->getMachineNode(AArch64::ADDXrr, DL, MVT::i64,
4854 {SDValue(N1, 0), N->getOperand(2)});
4855 SDNode *N3 = CurDAG->getMachineNode(
4856 AArch64::ADDG, DL, MVT::i64,
4857 {SDValue(N2, 0), CurDAG->getTargetConstant(0, DL, MVT::i64),
4858 CurDAG->getTargetConstant(TagOffset, DL, MVT::i64)});
4859 ReplaceNode(N, N3);
4860}
4861
4862bool AArch64DAGToDAGISel::trySelectCastFixedLengthToScalableVector(SDNode *N) {
4863 assert(N->getOpcode() == ISD::INSERT_SUBVECTOR && "Invalid Node!");
4864
4865 // Bail when not a "cast" like insert_subvector.
4866 if (N->getConstantOperandVal(2) != 0)
4867 return false;
4868 if (!N->getOperand(0).isUndef())
4869 return false;
4870
4871 // Bail when normal isel should do the job.
4872 EVT VT = N->getValueType(0);
4873 EVT InVT = N->getOperand(1).getValueType();
4874 if (VT.isFixedLengthVector() || InVT.isScalableVector())
4875 return false;
4876 if (InVT.getSizeInBits() <= 128)
4877 return false;
4878
4879 // NOTE: We can only get here when doing fixed length SVE code generation.
4880 // We do manual selection because the types involved are not linked to real
4881 // registers (despite being legal) and must be coerced into SVE registers.
4882
4884 "Expected to insert into a packed scalable vector!");
4885
4886 SDLoc DL(N);
4887 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID, DL, MVT::i64);
4888 ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, DL, VT,
4889 N->getOperand(1), RC));
4890 return true;
4891}
4892
4893bool AArch64DAGToDAGISel::trySelectCastScalableToFixedLengthVector(SDNode *N) {
4894 assert(N->getOpcode() == ISD::EXTRACT_SUBVECTOR && "Invalid Node!");
4895
4896 // Bail when not a "cast" like extract_subvector.
4897 if (N->getConstantOperandVal(1) != 0)
4898 return false;
4899
4900 // Bail when normal isel can do the job.
4901 EVT VT = N->getValueType(0);
4902 EVT InVT = N->getOperand(0).getValueType();
4903 if (VT.isScalableVector() || InVT.isFixedLengthVector())
4904 return false;
4905 if (VT.getSizeInBits() <= 128)
4906 return false;
4907
4908 // NOTE: We can only get here when doing fixed length SVE code generation.
4909 // We do manual selection because the types involved are not linked to real
4910 // registers (despite being legal) and must be coerced into SVE registers.
4911
4913 "Expected to extract from a packed scalable vector!");
4914
4915 SDLoc DL(N);
4916 auto RC = CurDAG->getTargetConstant(AArch64::ZPRRegClassID, DL, MVT::i64);
4917 ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, DL, VT,
4918 N->getOperand(0), RC));
4919 return true;
4920}
4921
4922bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
4923 assert(N->getOpcode() == ISD::OR && "Expected OR instruction");
4924
4925 SDValue N0 = N->getOperand(0);
4926 SDValue N1 = N->getOperand(1);
4927
4928 EVT VT = N->getValueType(0);
4929 SDLoc DL(N);
4930
4931 // Essentially: rotr (xor(x, y), imm) -> xar (x, y, imm)
4932 // Rotate by a constant is a funnel shift in IR which is expanded to
4933 // an OR with shifted operands.
4934 // We do the following transform:
4935 // OR N0, N1 -> xar (x, y, imm)
4936 // Where:
4937 // N1 = SRL_PRED true, V, splat(imm) --> rotr amount
4938 // N0 = SHL_PRED true, V, splat(bits-imm)
4939 // V = (xor x, y)
4940 if (VT.isScalableVector() &&
4941 (Subtarget->hasSVE2() ||
4942 (Subtarget->hasSME() && Subtarget->isStreaming()))) {
4943 if (N0.getOpcode() != AArch64ISD::SHL_PRED ||
4944 N1.getOpcode() != AArch64ISD::SRL_PRED)
4945 std::swap(N0, N1);
4946 if (N0.getOpcode() != AArch64ISD::SHL_PRED ||
4947 N1.getOpcode() != AArch64ISD::SRL_PRED)
4948 return false;
4949
4950 auto *TLI = static_cast<const AArch64TargetLowering *>(getTargetLowering());
4951 if (!TLI->isAllActivePredicate(*CurDAG, N0.getOperand(0)) ||
4952 !TLI->isAllActivePredicate(*CurDAG, N1.getOperand(0)))
4953 return false;
4954
4955 if (N0.getOperand(1) != N1.getOperand(1))
4956 return false;
4957
4958 SDValue R1, R2;
4959 bool IsXOROperand = true;
4960 if (N0.getOperand(1).getOpcode() != ISD::XOR) {
4961 IsXOROperand = false;
4962 } else {
4963 R1 = N0.getOperand(1).getOperand(0);
4964 R2 = N1.getOperand(1).getOperand(1);
4965 }
4966
4967 APInt ShlAmt, ShrAmt;
4968 if (!ISD::isConstantSplatVector(N0.getOperand(2).getNode(), ShlAmt) ||
4970 return false;
4971
4972 if (ShlAmt + ShrAmt != VT.getScalarSizeInBits())
4973 return false;
4974
4975 if (!IsXOROperand) {
4976 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64);
4977 SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns, DL, VT, Zero);
4978 SDValue MOVIV = SDValue(MOV, 0);
4979
4980 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub, DL, MVT::i32);
4981 SDNode *SubRegToReg =
4982 CurDAG->getMachineNode(AArch64::SUBREG_TO_REG, DL, VT, MOVIV, ZSub);
4983
4984 R1 = N1->getOperand(1);
4985 R2 = SDValue(SubRegToReg, 0);
4986 }
4987
4988 SDValue Imm =
4989 CurDAG->getTargetConstant(ShrAmt.getZExtValue(), DL, MVT::i32);
4990
4991 SDValue Ops[] = {R1, R2, Imm};
4993 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4994 AArch64::XAR_ZZZI_D})) {
4995 CurDAG->SelectNodeTo(N, Opc, VT, Ops);
4996 return true;
4997 }
4998 return false;
4999 }
5000
5001 // We have Neon SHA3 XAR operation for v2i64 but for types
5002 // v4i32, v8i16, v16i8 we can use SVE operations when SVE2-SHA3
5003 // is available.
5004 EVT SVT;
5005 switch (VT.getSimpleVT().SimpleTy) {
5006 case MVT::v4i32:
5007 case MVT::v2i32:
5008 SVT = MVT::nxv4i32;
5009 break;
5010 case MVT::v8i16:
5011 case MVT::v4i16:
5012 SVT = MVT::nxv8i16;
5013 break;
5014 case MVT::v16i8:
5015 case MVT::v8i8:
5016 SVT = MVT::nxv16i8;
5017 break;
5018 case MVT::v2i64:
5019 case MVT::v1i64:
5020 SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
5021 break;
5022 default:
5023 return false;
5024 }
5025
5026 if ((!SVT.isScalableVector() && !Subtarget->hasSHA3()) ||
5027 (SVT.isScalableVector() && !Subtarget->hasSVE2()))
5028 return false;
5029
5030 if (N0->getOpcode() != AArch64ISD::VSHL ||
5031 N1->getOpcode() != AArch64ISD::VLSHR)
5032 return false;
5033
5034 if (N0->getOperand(0) != N1->getOperand(0))
5035 return false;
5036
5037 SDValue R1, R2;
5038 bool IsXOROperand = true;
5039 if (N1->getOperand(0)->getOpcode() != ISD::XOR) {
5040 IsXOROperand = false;
5041 } else {
5042 SDValue XOR = N0.getOperand(0);
5043 R1 = XOR.getOperand(0);
5044 R2 = XOR.getOperand(1);
5045 }
5046
5047 unsigned HsAmt = N0.getConstantOperandVal(1);
5048 unsigned ShAmt = N1.getConstantOperandVal(1);
5049
5050 SDValue Imm = CurDAG->getTargetConstant(
5051 ShAmt, DL, N0.getOperand(1).getValueType(), false);
5052
5053 unsigned VTSizeInBits = VT.getScalarSizeInBits();
5054 if (ShAmt + HsAmt != VTSizeInBits)
5055 return false;
5056
5057 if (!IsXOROperand) {
5058 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64);
5059 SDNode *MOV =
5060 CurDAG->getMachineNode(AArch64::MOVIv2d_ns, DL, MVT::v2i64, Zero);
5061 SDValue MOVIV = SDValue(MOV, 0);
5062
5063 R1 = N1->getOperand(0);
5064 R2 = MOVIV;
5065 }
5066
5067 if (SVT != VT) {
5068 SDValue Undef =
5069 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, SVT), 0);
5070
5071 if (SVT.isScalableVector() && VT.is64BitVector()) {
5072 EVT QVT = VT.getDoubleNumVectorElementsVT(*CurDAG->getContext());
5073
5074 SDValue UndefQ = SDValue(
5075 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, QVT), 0);
5076 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
5077
5078 R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, QVT,
5079 UndefQ, R1, DSub),
5080 0);
5081 if (R2.getValueType() == VT)
5082 R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, QVT,
5083 UndefQ, R2, DSub),
5084 0);
5085 }
5086
5087 SDValue SubReg = CurDAG->getTargetConstant(
5088 (SVT.isScalableVector() ? AArch64::zsub : AArch64::dsub), DL, MVT::i32);
5089
5090 R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, SVT, Undef,
5091 R1, SubReg),
5092 0);
5093
5094 if (SVT.isScalableVector() || R2.getValueType() != SVT)
5095 R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, SVT,
5096 Undef, R2, SubReg),
5097 0);
5098 }
5099
5100 SDValue Ops[] = {R1, R2, Imm};
5101 SDNode *XAR = nullptr;
5102
5103 if (SVT.isScalableVector()) {
5105 SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
5106 AArch64::XAR_ZZZI_D}))
5107 XAR = CurDAG->getMachineNode(Opc, DL, SVT, Ops);
5108 } else {
5109 XAR = CurDAG->getMachineNode(AArch64::XAR, DL, SVT, Ops);
5110 }
5111
5112 assert(XAR && "Unexpected NULL value for XAR instruction in DAG");
5113
5114 if (SVT != VT) {
5115 if (VT.is64BitVector() && SVT.isScalableVector()) {
5116 EVT QVT = VT.getDoubleNumVectorElementsVT(*CurDAG->getContext());
5117
5118 SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub, DL, MVT::i32);
5119 SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG, DL, QVT,
5120 SDValue(XAR, 0), ZSub);
5121
5122 SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
5123 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG, DL, VT,
5124 SDValue(Q, 0), DSub);
5125 } else {
5126 SDValue SubReg = CurDAG->getTargetConstant(
5127 (SVT.isScalableVector() ? AArch64::zsub : AArch64::dsub), DL,
5128 MVT::i32);
5129 XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG, DL, VT,
5130 SDValue(XAR, 0), SubReg);
5131 }
5132 }
5133 ReplaceNode(N, XAR);
5134 return true;
5135}
5136
5137/// Returns a copy from WZR or XZR. This can be used during instruction
5138/// selection (it does not require any further selection/legalization).
5140 assert(VT == MVT::i32 || VT == MVT::i64);
5141 return DAG.getCopyFromReg(DAG.getEntryNode(), DL,
5142 VT == MVT::i32 ? AArch64::WZR : AArch64::XZR, VT);
5143}
5144
5145void AArch64DAGToDAGISel::Select(SDNode *Node) {
5146 // If we have a custom node, we already have selected!
5147 if (Node->isMachineOpcode()) {
5148 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
5149 Node->setNodeId(-1);
5150 return;
5151 }
5152
5153 // Few custom selection stuff.
5154 EVT VT = Node->getValueType(0);
5155
5156 switch (Node->getOpcode()) {
5157 default:
5158 break;
5159
5161 if (SelectCMP_SWAP(Node))
5162 return;
5163 break;
5164
5165 case ISD::READ_REGISTER:
5166 case AArch64ISD::MRRS:
5167 if (tryReadRegister(Node))
5168 return;
5169 break;
5170
5172 case AArch64ISD::MSRR:
5173 if (tryWriteRegister(Node))
5174 return;
5175 break;
5176
5177 case ISD::LOAD: {
5178 // Try to select as an indexed load. Fall through to normal processing
5179 // if we can't.
5180 if (tryIndexedLoad(Node))
5181 return;
5182 break;
5183 }
5184
5185 case ISD::SRL:
5186 case ISD::AND:
5187 case ISD::SRA:
5189 if (tryBitfieldExtractOp(Node))
5190 return;
5191 if (tryBitfieldInsertInZeroOp(Node))
5192 return;
5193 [[fallthrough]];
5194 case ISD::ROTR:
5195 case ISD::SHL:
5196 break;
5197
5198 case ISD::OR:
5199 if (tryBitfieldInsertOp(Node))
5200 return;
5201 if (trySelectXAR(Node))
5202 return;
5203 break;
5204
5206 if (trySelectCastScalableToFixedLengthVector(Node))
5207 return;
5208 break;
5209 }
5210
5211 case ISD::INSERT_SUBVECTOR: {
5212 if (trySelectCastFixedLengthToScalableVector(Node))
5213 return;
5214 break;
5215 }
5216
5217 case AArch64ISD::CSEL:
5218 if (tryFoldCselToFMaxMin(Node))
5219 return;
5220 break;
5221
5222 case ISD::Constant: {
5223 // Materialize zero constants as copies from WZR/XZR. This allows
5224 // the coalescer to propagate these into other instructions.
5225 ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node);
5226 if (ConstNode->isZero() && (VT == MVT::i32 || VT == MVT::i64)) {
5227 ReplaceNode(Node, getZeroRegister(*CurDAG, SDLoc(Node), VT).getNode());
5228 return;
5229 }
5230 break;
5231 }
5232
5233 case ISD::FrameIndex: {
5234 // Selects to ADDXri FI, 0 which in turn will become ADDXri SP, imm.
5235 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
5236 unsigned Shifter = AArch64_AM::getShifterImm(AArch64_AM::LSL, 0);
5237 const TargetLowering *TLI = getTargetLowering();
5238 SDValue TFI = CurDAG->getTargetFrameIndex(
5239 FI, TLI->getPointerTy(CurDAG->getDataLayout()));
5240 SDLoc DL(Node);
5241 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, DL, MVT::i32),
5242 CurDAG->getTargetConstant(Shifter, DL, MVT::i32) };
5243 CurDAG->SelectNodeTo(Node, AArch64::ADDXri, MVT::i64, Ops);
5244 return;
5245 }
5247 unsigned IntNo = Node->getConstantOperandVal(1);
5248 switch (IntNo) {
5249 default:
5250 break;
5251 case Intrinsic::aarch64_gcsss: {
5252 SDLoc DL(Node);
5253 SDValue Chain = Node->getOperand(0);
5254 SDValue Val = Node->getOperand(2);
5255 SDValue Zero = CurDAG->getCopyFromReg(Chain, DL, AArch64::XZR, MVT::i64);
5256 SDNode *SS1 =
5257 CurDAG->getMachineNode(AArch64::GCSSS1, DL, MVT::Other, Val, Chain);
5258 SDNode *SS2 = CurDAG->getMachineNode(AArch64::GCSSS2, DL, MVT::i64,
5259 MVT::Other, Zero, SDValue(SS1, 0));
5260 ReplaceNode(Node, SS2);
5261 return;
5262 }
5263 case Intrinsic::aarch64_ldaxp:
5264 case Intrinsic::aarch64_ldxp: {
5265 unsigned Op =
5266 IntNo == Intrinsic::aarch64_ldaxp ? AArch64::LDAXPX : AArch64::LDXPX;
5267 SDValue MemAddr = Node->getOperand(2);
5268 SDLoc DL(Node);
5269 SDValue Chain = Node->getOperand(0);
5270
5271 SDNode *Ld = CurDAG->getMachineNode(Op, DL, MVT::i64, MVT::i64,
5272 MVT::Other, MemAddr, Chain);
5273
5274 // Transfer memoperands.
5275 MachineMemOperand *MemOp =
5276 cast<MemIntrinsicSDNode>(Node)->getMemOperand();
5277 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {MemOp});
5278 ReplaceNode(Node, Ld);
5279 return;
5280 }
5281 case Intrinsic::aarch64_stlxp:
5282 case Intrinsic::aarch64_stxp: {
5283 unsigned Op =
5284 IntNo == Intrinsic::aarch64_stlxp ? AArch64::STLXPX : AArch64::STXPX;
5285 SDLoc DL(Node);
5286 SDValue Chain = Node->getOperand(0);
5287 SDValue ValLo = Node->getOperand(2);
5288 SDValue ValHi = Node->getOperand(3);
5289 SDValue MemAddr = Node->getOperand(4);
5290
5291 // Place arguments in the right order.
5292 SDValue Ops[] = {ValLo, ValHi, MemAddr, Chain};
5293
5294 SDNode *St = CurDAG->getMachineNode(Op, DL, MVT::i32, MVT::Other, Ops);
5295 // Transfer memoperands.
5296 MachineMemOperand *MemOp =
5297 cast<MemIntrinsicSDNode>(Node)->getMemOperand();
5298 CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp});
5299
5300 ReplaceNode(Node, St);
5301 return;
5302 }
5303 case Intrinsic::aarch64_neon_ld1x2:
5304 if (VT == MVT::v8i8) {
5305 SelectLoad(Node, 2, AArch64::LD1Twov8b, AArch64::dsub0);
5306 return;
5307 } else if (VT == MVT::v16i8) {
5308 SelectLoad(Node, 2, AArch64::LD1Twov16b, AArch64::qsub0);
5309 return;
5310 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5311 SelectLoad(Node, 2, AArch64::LD1Twov4h, AArch64::dsub0);
5312 return;
5313 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5314 SelectLoad(Node, 2, AArch64::LD1Twov8h, AArch64::qsub0);
5315 return;
5316 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5317 SelectLoad(Node, 2, AArch64::LD1Twov2s, AArch64::dsub0);
5318 return;
5319 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5320 SelectLoad(Node, 2, AArch64::LD1Twov4s, AArch64::qsub0);
5321 return;
5322 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5323 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5324 return;
5325 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5326 SelectLoad(Node, 2, AArch64::LD1Twov2d, AArch64::qsub0);
5327 return;
5328 }
5329 break;
5330 case Intrinsic::aarch64_neon_ld1x3:
5331 if (VT == MVT::v8i8) {
5332 SelectLoad(Node, 3, AArch64::LD1Threev8b, AArch64::dsub0);
5333 return;
5334 } else if (VT == MVT::v16i8) {
5335 SelectLoad(Node, 3, AArch64::LD1Threev16b, AArch64::qsub0);
5336 return;
5337 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5338 SelectLoad(Node, 3, AArch64::LD1Threev4h, AArch64::dsub0);
5339 return;
5340 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5341 SelectLoad(Node, 3, AArch64::LD1Threev8h, AArch64::qsub0);
5342 return;
5343 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5344 SelectLoad(Node, 3, AArch64::LD1Threev2s, AArch64::dsub0);
5345 return;
5346 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5347 SelectLoad(Node, 3, AArch64::LD1Threev4s, AArch64::qsub0);
5348 return;
5349 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5350 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5351 return;
5352 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5353 SelectLoad(Node, 3, AArch64::LD1Threev2d, AArch64::qsub0);
5354 return;
5355 }
5356 break;
5357 case Intrinsic::aarch64_neon_ld1x4:
5358 if (VT == MVT::v8i8) {
5359 SelectLoad(Node, 4, AArch64::LD1Fourv8b, AArch64::dsub0);
5360 return;
5361 } else if (VT == MVT::v16i8) {
5362 SelectLoad(Node, 4, AArch64::LD1Fourv16b, AArch64::qsub0);
5363 return;
5364 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5365 SelectLoad(Node, 4, AArch64::LD1Fourv4h, AArch64::dsub0);
5366 return;
5367 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5368 SelectLoad(Node, 4, AArch64::LD1Fourv8h, AArch64::qsub0);
5369 return;
5370 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5371 SelectLoad(Node, 4, AArch64::LD1Fourv2s, AArch64::dsub0);
5372 return;
5373 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5374 SelectLoad(Node, 4, AArch64::LD1Fourv4s, AArch64::qsub0);
5375 return;
5376 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5377 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5378 return;
5379 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5380 SelectLoad(Node, 4, AArch64::LD1Fourv2d, AArch64::qsub0);
5381 return;
5382 }
5383 break;
5384 case Intrinsic::aarch64_neon_ld2:
5385 if (VT == MVT::v8i8) {
5386 SelectLoad(Node, 2, AArch64::LD2Twov8b, AArch64::dsub0);
5387 return;
5388 } else if (VT == MVT::v16i8) {
5389 SelectLoad(Node, 2, AArch64::LD2Twov16b, AArch64::qsub0);
5390 return;
5391 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5392 SelectLoad(Node, 2, AArch64::LD2Twov4h, AArch64::dsub0);
5393 return;
5394 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5395 SelectLoad(Node, 2, AArch64::LD2Twov8h, AArch64::qsub0);
5396 return;
5397 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5398 SelectLoad(Node, 2, AArch64::LD2Twov2s, AArch64::dsub0);
5399 return;
5400 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5401 SelectLoad(Node, 2, AArch64::LD2Twov4s, AArch64::qsub0);
5402 return;
5403 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5404 SelectLoad(Node, 2, AArch64::LD1Twov1d, AArch64::dsub0);
5405 return;
5406 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5407 SelectLoad(Node, 2, AArch64::LD2Twov2d, AArch64::qsub0);
5408 return;
5409 }
5410 break;
5411 case Intrinsic::aarch64_neon_ld3:
5412 if (VT == MVT::v8i8) {
5413 SelectLoad(Node, 3, AArch64::LD3Threev8b, AArch64::dsub0);
5414 return;
5415 } else if (VT == MVT::v16i8) {
5416 SelectLoad(Node, 3, AArch64::LD3Threev16b, AArch64::qsub0);
5417 return;
5418 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5419 SelectLoad(Node, 3, AArch64::LD3Threev4h, AArch64::dsub0);
5420 return;
5421 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5422 SelectLoad(Node, 3, AArch64::LD3Threev8h, AArch64::qsub0);
5423 return;
5424 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5425 SelectLoad(Node, 3, AArch64::LD3Threev2s, AArch64::dsub0);
5426 return;
5427 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5428 SelectLoad(Node, 3, AArch64::LD3Threev4s, AArch64::qsub0);
5429 return;
5430 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5431 SelectLoad(Node, 3, AArch64::LD1Threev1d, AArch64::dsub0);
5432 return;
5433 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5434 SelectLoad(Node, 3, AArch64::LD3Threev2d, AArch64::qsub0);
5435 return;
5436 }
5437 break;
5438 case Intrinsic::aarch64_neon_ld4:
5439 if (VT == MVT::v8i8) {
5440 SelectLoad(Node, 4, AArch64::LD4Fourv8b, AArch64::dsub0);
5441 return;
5442 } else if (VT == MVT::v16i8) {
5443 SelectLoad(Node, 4, AArch64::LD4Fourv16b, AArch64::qsub0);
5444 return;
5445 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5446 SelectLoad(Node, 4, AArch64::LD4Fourv4h, AArch64::dsub0);
5447 return;
5448 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5449 SelectLoad(Node, 4, AArch64::LD4Fourv8h, AArch64::qsub0);
5450 return;
5451 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5452 SelectLoad(Node, 4, AArch64::LD4Fourv2s, AArch64::dsub0);
5453 return;
5454 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5455 SelectLoad(Node, 4, AArch64::LD4Fourv4s, AArch64::qsub0);
5456 return;
5457 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5458 SelectLoad(Node, 4, AArch64::LD1Fourv1d, AArch64::dsub0);
5459 return;
5460 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5461 SelectLoad(Node, 4, AArch64::LD4Fourv2d, AArch64::qsub0);
5462 return;
5463 }
5464 break;
5465 case Intrinsic::aarch64_neon_ld2r:
5466 if (VT == MVT::v8i8) {
5467 SelectLoad(Node, 2, AArch64::LD2Rv8b, AArch64::dsub0);
5468 return;
5469 } else if (VT == MVT::v16i8) {
5470 SelectLoad(Node, 2, AArch64::LD2Rv16b, AArch64::qsub0);
5471 return;
5472 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5473 SelectLoad(Node, 2, AArch64::LD2Rv4h, AArch64::dsub0);
5474 return;
5475 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5476 SelectLoad(Node, 2, AArch64::LD2Rv8h, AArch64::qsub0);
5477 return;
5478 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5479 SelectLoad(Node, 2, AArch64::LD2Rv2s, AArch64::dsub0);
5480 return;
5481 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5482 SelectLoad(Node, 2, AArch64::LD2Rv4s, AArch64::qsub0);
5483 return;
5484 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5485 SelectLoad(Node, 2, AArch64::LD2Rv1d, AArch64::dsub0);
5486 return;
5487 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5488 SelectLoad(Node, 2, AArch64::LD2Rv2d, AArch64::qsub0);
5489 return;
5490 }
5491 break;
5492 case Intrinsic::aarch64_neon_ld3r:
5493 if (VT == MVT::v8i8) {
5494 SelectLoad(Node, 3, AArch64::LD3Rv8b, AArch64::dsub0);
5495 return;
5496 } else if (VT == MVT::v16i8) {
5497 SelectLoad(Node, 3, AArch64::LD3Rv16b, AArch64::qsub0);
5498 return;
5499 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5500 SelectLoad(Node, 3, AArch64::LD3Rv4h, AArch64::dsub0);
5501 return;
5502 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5503 SelectLoad(Node, 3, AArch64::LD3Rv8h, AArch64::qsub0);
5504 return;
5505 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5506 SelectLoad(Node, 3, AArch64::LD3Rv2s, AArch64::dsub0);
5507 return;
5508 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5509 SelectLoad(Node, 3, AArch64::LD3Rv4s, AArch64::qsub0);
5510 return;
5511 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5512 SelectLoad(Node, 3, AArch64::LD3Rv1d, AArch64::dsub0);
5513 return;
5514 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5515 SelectLoad(Node, 3, AArch64::LD3Rv2d, AArch64::qsub0);
5516 return;
5517 }
5518 break;
5519 case Intrinsic::aarch64_neon_ld4r:
5520 if (VT == MVT::v8i8) {
5521 SelectLoad(Node, 4, AArch64::LD4Rv8b, AArch64::dsub0);
5522 return;
5523 } else if (VT == MVT::v16i8) {
5524 SelectLoad(Node, 4, AArch64::LD4Rv16b, AArch64::qsub0);
5525 return;
5526 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
5527 SelectLoad(Node, 4, AArch64::LD4Rv4h, AArch64::dsub0);
5528 return;
5529 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
5530 SelectLoad(Node, 4, AArch64::LD4Rv8h, AArch64::qsub0);
5531 return;
5532 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
5533 SelectLoad(Node, 4, AArch64::LD4Rv2s, AArch64::dsub0);
5534 return;
5535 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
5536 SelectLoad(Node, 4, AArch64::LD4Rv4s, AArch64::qsub0);
5537 return;
5538 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
5539 SelectLoad(Node, 4, AArch64::LD4Rv1d, AArch64::dsub0);
5540 return;
5541 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
5542 SelectLoad(Node, 4, AArch64::LD4Rv2d, AArch64::qsub0);
5543 return;
5544 }
5545 break;
5546 case Intrinsic::aarch64_neon_ld2lane:
5547 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5548 SelectLoadLane(Node, 2, AArch64::LD2i8);
5549 return;
5550 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5551 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5552 SelectLoadLane(Node, 2, AArch64::LD2i16);
5553 return;
5554 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5555 VT == MVT::v2f32) {
5556 SelectLoadLane(Node, 2, AArch64::LD2i32);
5557 return;
5558 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5559 VT == MVT::v1f64) {
5560 SelectLoadLane(Node, 2, AArch64::LD2i64);
5561 return;
5562 }
5563 break;
5564 case Intrinsic::aarch64_neon_ld3lane:
5565 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5566 SelectLoadLane(Node, 3, AArch64::LD3i8);
5567 return;
5568 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5569 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5570 SelectLoadLane(Node, 3, AArch64::LD3i16);
5571 return;
5572 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5573 VT == MVT::v2f32) {
5574 SelectLoadLane(Node, 3, AArch64::LD3i32);
5575 return;
5576 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5577 VT == MVT::v1f64) {
5578 SelectLoadLane(Node, 3, AArch64::LD3i64);
5579 return;
5580 }
5581 break;
5582 case Intrinsic::aarch64_neon_ld4lane:
5583 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
5584 SelectLoadLane(Node, 4, AArch64::LD4i8);
5585 return;
5586 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
5587 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
5588 SelectLoadLane(Node, 4, AArch64::LD4i16);
5589 return;
5590 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
5591 VT == MVT::v2f32) {
5592 SelectLoadLane(Node, 4, AArch64::LD4i32);
5593 return;
5594 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
5595 VT == MVT::v1f64) {
5596 SelectLoadLane(Node, 4, AArch64::LD4i64);
5597 return;
5598 }
5599 break;
5600 case Intrinsic::aarch64_ld64b:
5601 SelectLoad(Node, 8, AArch64::LD64B, AArch64::x8sub_0);
5602 return;
5603 case Intrinsic::aarch64_sve_ld2q_sret: {
5604 SelectPredicatedLoad(Node, 2, 4, AArch64::LD2Q_IMM, AArch64::LD2Q, true);
5605 return;
5606 }
5607 case Intrinsic::aarch64_sve_ld3q_sret: {
5608 SelectPredicatedLoad(Node, 3, 4, AArch64::LD3Q_IMM, AArch64::LD3Q, true);
5609 return;
5610 }
5611 case Intrinsic::aarch64_sve_ld4q_sret: {
5612 SelectPredicatedLoad(Node, 4, 4, AArch64::LD4Q_IMM, AArch64::LD4Q, true);
5613 return;
5614 }
5615 case Intrinsic::aarch64_sve_ld2_sret: {
5616 if (VT == MVT::nxv16i8) {
5617 SelectPredicatedLoad(Node, 2, 0, AArch64::LD2B_IMM, AArch64::LD2B,
5618 true);
5619 return;
5620 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5621 VT == MVT::nxv8bf16) {
5622 SelectPredicatedLoad(Node, 2, 1, AArch64::LD2H_IMM, AArch64::LD2H,
5623 true);
5624 return;
5625 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5626 SelectPredicatedLoad(Node, 2, 2, AArch64::LD2W_IMM, AArch64::LD2W,
5627 true);
5628 return;
5629 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5630 SelectPredicatedLoad(Node, 2, 3, AArch64::LD2D_IMM, AArch64::LD2D,
5631 true);
5632 return;
5633 }
5634 break;
5635 }
5636 case Intrinsic::aarch64_sve_ld1_pn_x2: {
5637 if (VT == MVT::nxv16i8) {
5638 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5639 SelectContiguousMultiVectorLoad(
5640 Node, 2, 0, AArch64::LD1B_2Z_IMM_PSEUDO, AArch64::LD1B_2Z_PSEUDO);
5641 else if (Subtarget->hasSVE2p1())
5642 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LD1B_2Z_IMM,
5643 AArch64::LD1B_2Z);
5644 else
5645 break;
5646 return;
5647 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5648 VT == MVT::nxv8bf16) {
5649 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5650 SelectContiguousMultiVectorLoad(
5651 Node, 2, 1, AArch64::LD1H_2Z_IMM_PSEUDO, AArch64::LD1H_2Z_PSEUDO);
5652 else if (Subtarget->hasSVE2p1())
5653 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LD1H_2Z_IMM,
5654 AArch64::LD1H_2Z);
5655 else
5656 break;
5657 return;
5658 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5659 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5660 SelectContiguousMultiVectorLoad(
5661 Node, 2, 2, AArch64::LD1W_2Z_IMM_PSEUDO, AArch64::LD1W_2Z_PSEUDO);
5662 else if (Subtarget->hasSVE2p1())
5663 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LD1W_2Z_IMM,
5664 AArch64::LD1W_2Z);
5665 else
5666 break;
5667 return;
5668 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5669 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5670 SelectContiguousMultiVectorLoad(
5671 Node, 2, 3, AArch64::LD1D_2Z_IMM_PSEUDO, AArch64::LD1D_2Z_PSEUDO);
5672 else if (Subtarget->hasSVE2p1())
5673 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LD1D_2Z_IMM,
5674 AArch64::LD1D_2Z);
5675 else
5676 break;
5677 return;
5678 }
5679 break;
5680 }
5681 case Intrinsic::aarch64_sve_ld1_pn_x4: {
5682 if (VT == MVT::nxv16i8) {
5683 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5684 SelectContiguousMultiVectorLoad(
5685 Node, 4, 0, AArch64::LD1B_4Z_IMM_PSEUDO, AArch64::LD1B_4Z_PSEUDO);
5686 else if (Subtarget->hasSVE2p1())
5687 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LD1B_4Z_IMM,
5688 AArch64::LD1B_4Z);
5689 else
5690 break;
5691 return;
5692 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5693 VT == MVT::nxv8bf16) {
5694 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5695 SelectContiguousMultiVectorLoad(
5696 Node, 4, 1, AArch64::LD1H_4Z_IMM_PSEUDO, AArch64::LD1H_4Z_PSEUDO);
5697 else if (Subtarget->hasSVE2p1())
5698 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LD1H_4Z_IMM,
5699 AArch64::LD1H_4Z);
5700 else
5701 break;
5702 return;
5703 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5704 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5705 SelectContiguousMultiVectorLoad(
5706 Node, 4, 2, AArch64::LD1W_4Z_IMM_PSEUDO, AArch64::LD1W_4Z_PSEUDO);
5707 else if (Subtarget->hasSVE2p1())
5708 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LD1W_4Z_IMM,
5709 AArch64::LD1W_4Z);
5710 else
5711 break;
5712 return;
5713 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5714 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5715 SelectContiguousMultiVectorLoad(
5716 Node, 4, 3, AArch64::LD1D_4Z_IMM_PSEUDO, AArch64::LD1D_4Z_PSEUDO);
5717 else if (Subtarget->hasSVE2p1())
5718 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LD1D_4Z_IMM,
5719 AArch64::LD1D_4Z);
5720 else
5721 break;
5722 return;
5723 }
5724 break;
5725 }
5726 case Intrinsic::aarch64_sve_ldnt1_pn_x2: {
5727 if (VT == MVT::nxv16i8) {
5728 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5729 SelectContiguousMultiVectorLoad(Node, 2, 0,
5730 AArch64::LDNT1B_2Z_IMM_PSEUDO,
5731 AArch64::LDNT1B_2Z_PSEUDO);
5732 else if (Subtarget->hasSVE2p1())
5733 SelectContiguousMultiVectorLoad(Node, 2, 0, AArch64::LDNT1B_2Z_IMM,
5734 AArch64::LDNT1B_2Z);
5735 else
5736 break;
5737 return;
5738 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5739 VT == MVT::nxv8bf16) {
5740 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5741 SelectContiguousMultiVectorLoad(Node, 2, 1,
5742 AArch64::LDNT1H_2Z_IMM_PSEUDO,
5743 AArch64::LDNT1H_2Z_PSEUDO);
5744 else if (Subtarget->hasSVE2p1())
5745 SelectContiguousMultiVectorLoad(Node, 2, 1, AArch64::LDNT1H_2Z_IMM,
5746 AArch64::LDNT1H_2Z);
5747 else
5748 break;
5749 return;
5750 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5751 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5752 SelectContiguousMultiVectorLoad(Node, 2, 2,
5753 AArch64::LDNT1W_2Z_IMM_PSEUDO,
5754 AArch64::LDNT1W_2Z_PSEUDO);
5755 else if (Subtarget->hasSVE2p1())
5756 SelectContiguousMultiVectorLoad(Node, 2, 2, AArch64::LDNT1W_2Z_IMM,
5757 AArch64::LDNT1W_2Z);
5758 else
5759 break;
5760 return;
5761 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5762 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5763 SelectContiguousMultiVectorLoad(Node, 2, 3,
5764 AArch64::LDNT1D_2Z_IMM_PSEUDO,
5765 AArch64::LDNT1D_2Z_PSEUDO);
5766 else if (Subtarget->hasSVE2p1())
5767 SelectContiguousMultiVectorLoad(Node, 2, 3, AArch64::LDNT1D_2Z_IMM,
5768 AArch64::LDNT1D_2Z);
5769 else
5770 break;
5771 return;
5772 }
5773 break;
5774 }
5775 case Intrinsic::aarch64_sve_ldnt1_pn_x4: {
5776 if (VT == MVT::nxv16i8) {
5777 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5778 SelectContiguousMultiVectorLoad(Node, 4, 0,
5779 AArch64::LDNT1B_4Z_IMM_PSEUDO,
5780 AArch64::LDNT1B_4Z_PSEUDO);
5781 else if (Subtarget->hasSVE2p1())
5782 SelectContiguousMultiVectorLoad(Node, 4, 0, AArch64::LDNT1B_4Z_IMM,
5783 AArch64::LDNT1B_4Z);
5784 else
5785 break;
5786 return;
5787 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5788 VT == MVT::nxv8bf16) {
5789 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5790 SelectContiguousMultiVectorLoad(Node, 4, 1,
5791 AArch64::LDNT1H_4Z_IMM_PSEUDO,
5792 AArch64::LDNT1H_4Z_PSEUDO);
5793 else if (Subtarget->hasSVE2p1())
5794 SelectContiguousMultiVectorLoad(Node, 4, 1, AArch64::LDNT1H_4Z_IMM,
5795 AArch64::LDNT1H_4Z);
5796 else
5797 break;
5798 return;
5799 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5800 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5801 SelectContiguousMultiVectorLoad(Node, 4, 2,
5802 AArch64::LDNT1W_4Z_IMM_PSEUDO,
5803 AArch64::LDNT1W_4Z_PSEUDO);
5804 else if (Subtarget->hasSVE2p1())
5805 SelectContiguousMultiVectorLoad(Node, 4, 2, AArch64::LDNT1W_4Z_IMM,
5806 AArch64::LDNT1W_4Z);
5807 else
5808 break;
5809 return;
5810 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5811 if (Subtarget->hasSME2() && Subtarget->isStreaming())
5812 SelectContiguousMultiVectorLoad(Node, 4, 3,
5813 AArch64::LDNT1D_4Z_IMM_PSEUDO,
5814 AArch64::LDNT1D_4Z_PSEUDO);
5815 else if (Subtarget->hasSVE2p1())
5816 SelectContiguousMultiVectorLoad(Node, 4, 3, AArch64::LDNT1D_4Z_IMM,
5817 AArch64::LDNT1D_4Z);
5818 else
5819 break;
5820 return;
5821 }
5822 break;
5823 }
5824 case Intrinsic::aarch64_sve_ld3_sret: {
5825 if (VT == MVT::nxv16i8) {
5826 SelectPredicatedLoad(Node, 3, 0, AArch64::LD3B_IMM, AArch64::LD3B,
5827 true);
5828 return;
5829 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5830 VT == MVT::nxv8bf16) {
5831 SelectPredicatedLoad(Node, 3, 1, AArch64::LD3H_IMM, AArch64::LD3H,
5832 true);
5833 return;
5834 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5835 SelectPredicatedLoad(Node, 3, 2, AArch64::LD3W_IMM, AArch64::LD3W,
5836 true);
5837 return;
5838 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5839 SelectPredicatedLoad(Node, 3, 3, AArch64::LD3D_IMM, AArch64::LD3D,
5840 true);
5841 return;
5842 }
5843 break;
5844 }
5845 case Intrinsic::aarch64_sve_ld4_sret: {
5846 if (VT == MVT::nxv16i8) {
5847 SelectPredicatedLoad(Node, 4, 0, AArch64::LD4B_IMM, AArch64::LD4B,
5848 true);
5849 return;
5850 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5851 VT == MVT::nxv8bf16) {
5852 SelectPredicatedLoad(Node, 4, 1, AArch64::LD4H_IMM, AArch64::LD4H,
5853 true);
5854 return;
5855 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5856 SelectPredicatedLoad(Node, 4, 2, AArch64::LD4W_IMM, AArch64::LD4W,
5857 true);
5858 return;
5859 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5860 SelectPredicatedLoad(Node, 4, 3, AArch64::LD4D_IMM, AArch64::LD4D,
5861 true);
5862 return;
5863 }
5864 break;
5865 }
5866 case Intrinsic::aarch64_sme_read_hor_vg2: {
5867 if (VT == MVT::nxv16i8) {
5868 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5869 AArch64::MOVA_2ZMXI_H_B);
5870 return;
5871 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5872 VT == MVT::nxv8bf16) {
5873 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5874 AArch64::MOVA_2ZMXI_H_H);
5875 return;
5876 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5877 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5878 AArch64::MOVA_2ZMXI_H_S);
5879 return;
5880 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5881 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5882 AArch64::MOVA_2ZMXI_H_D);
5883 return;
5884 }
5885 break;
5886 }
5887 case Intrinsic::aarch64_sme_read_ver_vg2: {
5888 if (VT == MVT::nxv16i8) {
5889 SelectMultiVectorMove<14, 2>(Node, 2, AArch64::ZAB0,
5890 AArch64::MOVA_2ZMXI_V_B);
5891 return;
5892 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5893 VT == MVT::nxv8bf16) {
5894 SelectMultiVectorMove<6, 2>(Node, 2, AArch64::ZAH0,
5895 AArch64::MOVA_2ZMXI_V_H);
5896 return;
5897 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5898 SelectMultiVectorMove<2, 2>(Node, 2, AArch64::ZAS0,
5899 AArch64::MOVA_2ZMXI_V_S);
5900 return;
5901 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5902 SelectMultiVectorMove<0, 2>(Node, 2, AArch64::ZAD0,
5903 AArch64::MOVA_2ZMXI_V_D);
5904 return;
5905 }
5906 break;
5907 }
5908 case Intrinsic::aarch64_sme_read_hor_vg4: {
5909 if (VT == MVT::nxv16i8) {
5910 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5911 AArch64::MOVA_4ZMXI_H_B);
5912 return;
5913 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5914 VT == MVT::nxv8bf16) {
5915 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5916 AArch64::MOVA_4ZMXI_H_H);
5917 return;
5918 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5919 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAS0,
5920 AArch64::MOVA_4ZMXI_H_S);
5921 return;
5922 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5923 SelectMultiVectorMove<0, 2>(Node, 4, AArch64::ZAD0,
5924 AArch64::MOVA_4ZMXI_H_D);
5925 return;
5926 }
5927 break;
5928 }
5929 case Intrinsic::aarch64_sme_read_ver_vg4: {
5930 if (VT == MVT::nxv16i8) {
5931 SelectMultiVectorMove<12, 4>(Node, 4, AArch64::ZAB0,
5932 AArch64::MOVA_4ZMXI_V_B);
5933 return;
5934 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5935 VT == MVT::nxv8bf16) {
5936 SelectMultiVectorMove<4, 4>(Node, 4, AArch64::ZAH0,
5937 AArch64::MOVA_4ZMXI_V_H);
5938 return;
5939 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5940 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAS0,
5941 AArch64::MOVA_4ZMXI_V_S);
5942 return;
5943 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5944 SelectMultiVectorMove<0, 4>(Node, 4, AArch64::ZAD0,
5945 AArch64::MOVA_4ZMXI_V_D);
5946 return;
5947 }
5948 break;
5949 }
5950 case Intrinsic::aarch64_sme_read_vg1x2: {
5951 SelectMultiVectorMove<7, 1>(Node, 2, AArch64::ZA,
5952 AArch64::MOVA_VG2_2ZMXI);
5953 return;
5954 }
5955 case Intrinsic::aarch64_sme_read_vg1x4: {
5956 SelectMultiVectorMove<7, 1>(Node, 4, AArch64::ZA,
5957 AArch64::MOVA_VG4_4ZMXI);
5958 return;
5959 }
5960 case Intrinsic::aarch64_sme_readz_horiz_x2: {
5961 if (VT == MVT::nxv16i8) {
5962 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_B_PSEUDO, 14, 2);
5963 return;
5964 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5965 VT == MVT::nxv8bf16) {
5966 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_H_PSEUDO, 6, 2);
5967 return;
5968 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5969 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_S_PSEUDO, 2, 2);
5970 return;
5971 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5972 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_H_D_PSEUDO, 0, 2);
5973 return;
5974 }
5975 break;
5976 }
5977 case Intrinsic::aarch64_sme_readz_vert_x2: {
5978 if (VT == MVT::nxv16i8) {
5979 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_B_PSEUDO, 14, 2);
5980 return;
5981 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5982 VT == MVT::nxv8bf16) {
5983 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_H_PSEUDO, 6, 2);
5984 return;
5985 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
5986 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_S_PSEUDO, 2, 2);
5987 return;
5988 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
5989 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_2ZMI_V_D_PSEUDO, 0, 2);
5990 return;
5991 }
5992 break;
5993 }
5994 case Intrinsic::aarch64_sme_readz_horiz_x4: {
5995 if (VT == MVT::nxv16i8) {
5996 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_B_PSEUDO, 12, 4);
5997 return;
5998 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
5999 VT == MVT::nxv8bf16) {
6000 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_H_PSEUDO, 4, 4);
6001 return;
6002 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6003 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_S_PSEUDO, 0, 4);
6004 return;
6005 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6006 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_H_D_PSEUDO, 0, 4);
6007 return;
6008 }
6009 break;
6010 }
6011 case Intrinsic::aarch64_sme_readz_vert_x4: {
6012 if (VT == MVT::nxv16i8) {
6013 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_B_PSEUDO, 12, 4);
6014 return;
6015 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
6016 VT == MVT::nxv8bf16) {
6017 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_H_PSEUDO, 4, 4);
6018 return;
6019 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
6020 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_S_PSEUDO, 0, 4);
6021 return;
6022 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
6023 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_4ZMI_V_D_PSEUDO, 0, 4);
6024 return;
6025 }
6026 break;
6027 }
6028 case Intrinsic::aarch64_sme_readz_x2: {
6029 SelectMultiVectorMoveZ(Node, 2, AArch64::MOVAZ_VG2_2ZMXI_PSEUDO, 7, 1,
6030 AArch64::ZA);
6031 return;
6032 }
6033 case Intrinsic::aarch64_sme_readz_x4: {
6034 SelectMultiVectorMoveZ(Node, 4, AArch64::MOVAZ_VG4_4ZMXI_PSEUDO, 7, 1,
6035 AArch64::ZA);
6036 return;
6037 }
6038 case Intrinsic::swift_async_context_addr: {
6039 SDLoc DL(Node);
6040 SDValue Chain = Node->getOperand(0);
6041 SDValue CopyFP = CurDAG->getCopyFromReg(Chain, DL, AArch64::FP, MVT::i64);
6042 SDValue Res = SDValue(
6043 CurDAG->getMachineNode(AArch64::SUBXri, DL, MVT::i64, CopyFP,
6044 CurDAG->getTargetConstant(8, DL, MVT::i32),
6045 CurDAG->getTargetConstant(0, DL, MVT::i32)),
6046 0);
6047 ReplaceUses(SDValue(Node, 0), Res);
6048 ReplaceUses(SDValue(Node, 1), CopyFP.getValue(1));
6049 CurDAG->RemoveDeadNode(Node);
6050
6051 auto &MF = CurDAG->getMachineFunction();
6052 MF.getFrameInfo().setFrameAddressIsTaken(true);
6053 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(true);
6054 return;
6055 }
6056 case Intrinsic::aarch64_sme_luti2_lane_zt_x4: {
6058 Node->getValueType(0),
6059 {AArch64::LUTI2_4ZTZI_B, AArch64::LUTI2_4ZTZI_H,
6060 AArch64::LUTI2_4ZTZI_S}))
6061 // Second Immediate must be <= 3:
6062 SelectMultiVectorLutiLane(Node, 4, Opc, 3);
6063 return;
6064 }
6065 case Intrinsic::aarch64_sme_luti4_lane_zt_x4: {
6067 Node->getValueType(0),
6068 {0, AArch64::LUTI4_4ZTZI_H, AArch64::LUTI4_4ZTZI_S}))
6069 // Second Immediate must be <= 1:
6070 SelectMultiVectorLutiLane(Node, 4, Opc, 1);
6071 return;
6072 }
6073 case Intrinsic::aarch64_sme_luti2_lane_zt_x2: {
6075 Node->getValueType(0),
6076 {AArch64::LUTI2_2ZTZI_B, AArch64::LUTI2_2ZTZI_H,
6077 AArch64::LUTI2_2ZTZI_S}))
6078 // Second Immediate must be <= 7:
6079 SelectMultiVectorLutiLane(Node, 2, Opc, 7);
6080 return;
6081 }
6082 case Intrinsic::aarch64_sme_luti4_lane_zt_x2: {
6084 Node->getValueType(0),
6085 {AArch64::LUTI4_2ZTZI_B, AArch64::LUTI4_2ZTZI_H,
6086 AArch64::LUTI4_2ZTZI_S}))
6087 // Second Immediate must be <= 3:
6088 SelectMultiVectorLutiLane(Node, 2, Opc, 3);
6089 return;
6090 }
6091 case Intrinsic::aarch64_sme_luti4_zt_x4: {
6092 SelectMultiVectorLuti(Node, 4, AArch64::LUTI4_4ZZT2Z, 2);
6093 return;
6094 }
6095 case Intrinsic::aarch64_sme_luti6_zt_x4: {
6096 SelectMultiVectorLuti(Node, 4, AArch64::LUTI6_4ZT3Z, 3);
6097 return;
6098 }
6099 case Intrinsic::aarch64_sve_fp8_cvtl1_x2:
6101 Node->getValueType(0),
6102 {AArch64::BF1CVTL_2ZZ_BtoH, AArch64::F1CVTL_2ZZ_BtoH}))
6103 SelectCVTIntrinsicFP8(Node, 2, Opc);
6104 return;
6105 case Intrinsic::aarch64_sve_fp8_cvtl2_x2:
6107 Node->getValueType(0),
6108 {AArch64::BF2CVTL_2ZZ_BtoH, AArch64::F2CVTL_2ZZ_BtoH}))
6109 SelectCVTIntrinsicFP8(Node, 2, Opc);
6110 return;
6111 case Intrinsic::aarch64_sve_fp8_cvt1_x2:
6113 Node->getValueType(0),
6114 {AArch64::BF1CVT_2ZZ_BtoH, AArch64::F1CVT_2ZZ_BtoH}))
6115 SelectCVTIntrinsicFP8(Node, 2, Opc);
6116 return;
6117 case Intrinsic::aarch64_sve_fp8_cvt2_x2:
6119 Node->getValueType(0),
6120 {AArch64::BF2CVT_2ZZ_BtoH, AArch64::F2CVT_2ZZ_BtoH}))
6121 SelectCVTIntrinsicFP8(Node, 2, Opc);
6122 return;
6123 case Intrinsic::ptrauth_resign_load_relative:
6124 SelectPtrauthResign(Node);
6125 return;
6126 }
6127 } break;
6129 unsigned IntNo = Node->getConstantOperandVal(0);
6130 switch (IntNo) {
6131 default:
6132 break;
6133 case Intrinsic::aarch64_tagp:
6134 SelectTagP(Node);
6135 return;
6136
6137 case Intrinsic::ptrauth_auth:
6138 SelectPtrauthAuth(Node);
6139 return;
6140
6141 case Intrinsic::ptrauth_resign:
6142 SelectPtrauthResign(Node);
6143 return;
6144
6145 case Intrinsic::ptrauth_auth_with_pc_and_resign:
6146 SelectPtrauthResignWithPC(Node);
6147 return;
6148
6149 case Intrinsic::aarch64_neon_tbl2:
6150 SelectTable(Node, 2,
6151 VT == MVT::v8i8 ? AArch64::TBLv8i8Two : AArch64::TBLv16i8Two,
6152 false);
6153 return;
6154 case Intrinsic::aarch64_neon_tbl3:
6155 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBLv8i8Three
6156 : AArch64::TBLv16i8Three,
6157 false);
6158 return;
6159 case Intrinsic::aarch64_neon_tbl4:
6160 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBLv8i8Four
6161 : AArch64::TBLv16i8Four,
6162 false);
6163 return;
6164 case Intrinsic::aarch64_neon_tbx2:
6165 SelectTable(Node, 2,
6166 VT == MVT::v8i8 ? AArch64::TBXv8i8Two : AArch64::TBXv16i8Two,
6167 true);
6168 return;
6169 case Intrinsic::aarch64_neon_tbx3:
6170 SelectTable(Node, 3, VT == MVT::v8i8 ? AArch64::TBXv8i8Three
6171 : AArch64::TBXv16i8Three,
6172 true);
6173 return;
6174 case Intrinsic::aarch64_neon_tbx4:
6175 SelectTable(Node, 4, VT == MVT::v8i8 ? AArch64::TBXv8i8Four
6176 : AArch64::TBXv16i8Four,
6177 true);
6178 return;
6179 case Intrinsic::aarch64_sve_srshl_single_x2:
6181 Node->getValueType(0),
6182 {AArch64::SRSHL_VG2_2ZZ_B, AArch64::SRSHL_VG2_2ZZ_H,
6183 AArch64::SRSHL_VG2_2ZZ_S, AArch64::SRSHL_VG2_2ZZ_D}))
6184 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6185 return;
6186 case Intrinsic::aarch64_sve_srshl_single_x4:
6188 Node->getValueType(0),
6189 {AArch64::SRSHL_VG4_4ZZ_B, AArch64::SRSHL_VG4_4ZZ_H,
6190 AArch64::SRSHL_VG4_4ZZ_S, AArch64::SRSHL_VG4_4ZZ_D}))
6191 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6192 return;
6193 case Intrinsic::aarch64_sme_luti6_lane_x4_x2:
6194 SelectMultiVectorLuti6LaneX4(Node, 2);
6195 return;
6196 case Intrinsic::aarch64_sme_luti6_lane_x4_x3:
6197 SelectMultiVectorLuti6LaneX4(Node, 3);
6198 return;
6199 case Intrinsic::aarch64_sve_urshl_single_x2:
6201 Node->getValueType(0),
6202 {AArch64::URSHL_VG2_2ZZ_B, AArch64::URSHL_VG2_2ZZ_H,
6203 AArch64::URSHL_VG2_2ZZ_S, AArch64::URSHL_VG2_2ZZ_D}))
6204 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6205 return;
6206 case Intrinsic::aarch64_sve_urshl_single_x4:
6208 Node->getValueType(0),
6209 {AArch64::URSHL_VG4_4ZZ_B, AArch64::URSHL_VG4_4ZZ_H,
6210 AArch64::URSHL_VG4_4ZZ_S, AArch64::URSHL_VG4_4ZZ_D}))
6211 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6212 return;
6213 case Intrinsic::aarch64_sve_srshl_x2:
6215 Node->getValueType(0),
6216 {AArch64::SRSHL_VG2_2Z2Z_B, AArch64::SRSHL_VG2_2Z2Z_H,
6217 AArch64::SRSHL_VG2_2Z2Z_S, AArch64::SRSHL_VG2_2Z2Z_D}))
6218 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6219 return;
6220 case Intrinsic::aarch64_sve_srshl_x4:
6222 Node->getValueType(0),
6223 {AArch64::SRSHL_VG4_4Z4Z_B, AArch64::SRSHL_VG4_4Z4Z_H,
6224 AArch64::SRSHL_VG4_4Z4Z_S, AArch64::SRSHL_VG4_4Z4Z_D}))
6225 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6226 return;
6227 case Intrinsic::aarch64_sve_urshl_x2:
6229 Node->getValueType(0),
6230 {AArch64::URSHL_VG2_2Z2Z_B, AArch64::URSHL_VG2_2Z2Z_H,
6231 AArch64::URSHL_VG2_2Z2Z_S, AArch64::URSHL_VG2_2Z2Z_D}))
6232 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6233 return;
6234 case Intrinsic::aarch64_sve_urshl_x4:
6236 Node->getValueType(0),
6237 {AArch64::URSHL_VG4_4Z4Z_B, AArch64::URSHL_VG4_4Z4Z_H,
6238 AArch64::URSHL_VG4_4Z4Z_S, AArch64::URSHL_VG4_4Z4Z_D}))
6239 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6240 return;
6241 case Intrinsic::aarch64_sve_sqdmulh_single_vgx2:
6243 Node->getValueType(0),
6244 {AArch64::SQDMULH_VG2_2ZZ_B, AArch64::SQDMULH_VG2_2ZZ_H,
6245 AArch64::SQDMULH_VG2_2ZZ_S, AArch64::SQDMULH_VG2_2ZZ_D}))
6246 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6247 return;
6248 case Intrinsic::aarch64_sve_sqdmulh_single_vgx4:
6250 Node->getValueType(0),
6251 {AArch64::SQDMULH_VG4_4ZZ_B, AArch64::SQDMULH_VG4_4ZZ_H,
6252 AArch64::SQDMULH_VG4_4ZZ_S, AArch64::SQDMULH_VG4_4ZZ_D}))
6253 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6254 return;
6255 case Intrinsic::aarch64_sve_sqdmulh_vgx2:
6257 Node->getValueType(0),
6258 {AArch64::SQDMULH_VG2_2Z2Z_B, AArch64::SQDMULH_VG2_2Z2Z_H,
6259 AArch64::SQDMULH_VG2_2Z2Z_S, AArch64::SQDMULH_VG2_2Z2Z_D}))
6260 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6261 return;
6262 case Intrinsic::aarch64_sve_sqdmulh_vgx4:
6264 Node->getValueType(0),
6265 {AArch64::SQDMULH_VG4_4Z4Z_B, AArch64::SQDMULH_VG4_4Z4Z_H,
6266 AArch64::SQDMULH_VG4_4Z4Z_S, AArch64::SQDMULH_VG4_4Z4Z_D}))
6267 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6268 return;
6269 case Intrinsic::aarch64_sme_fp8_scale_single_x2:
6271 Node->getValueType(0),
6272 {0, AArch64::FSCALE_2ZZ_H, AArch64::FSCALE_2ZZ_S,
6273 AArch64::FSCALE_2ZZ_D}))
6274 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6275 return;
6276 case Intrinsic::aarch64_sme_fp8_scale_single_x4:
6278 Node->getValueType(0),
6279 {0, AArch64::FSCALE_4ZZ_H, AArch64::FSCALE_4ZZ_S,
6280 AArch64::FSCALE_4ZZ_D}))
6281 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6282 return;
6283 case Intrinsic::aarch64_sme_fp8_scale_x2:
6285 Node->getValueType(0),
6286 {0, AArch64::FSCALE_2Z2Z_H, AArch64::FSCALE_2Z2Z_S,
6287 AArch64::FSCALE_2Z2Z_D}))
6288 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6289 return;
6290 case Intrinsic::aarch64_sme_fp8_scale_x4:
6292 Node->getValueType(0),
6293 {0, AArch64::FSCALE_4Z4Z_H, AArch64::FSCALE_4Z4Z_S,
6294 AArch64::FSCALE_4Z4Z_D}))
6295 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6296 return;
6297 case Intrinsic::aarch64_sve_whilege_x2:
6299 Node->getValueType(0),
6300 {AArch64::WHILEGE_2PXX_B, AArch64::WHILEGE_2PXX_H,
6301 AArch64::WHILEGE_2PXX_S, AArch64::WHILEGE_2PXX_D}))
6302 SelectWhilePair(Node, Op);
6303 return;
6304 case Intrinsic::aarch64_sve_whilegt_x2:
6306 Node->getValueType(0),
6307 {AArch64::WHILEGT_2PXX_B, AArch64::WHILEGT_2PXX_H,
6308 AArch64::WHILEGT_2PXX_S, AArch64::WHILEGT_2PXX_D}))
6309 SelectWhilePair(Node, Op);
6310 return;
6311 case Intrinsic::aarch64_sve_whilehi_x2:
6313 Node->getValueType(0),
6314 {AArch64::WHILEHI_2PXX_B, AArch64::WHILEHI_2PXX_H,
6315 AArch64::WHILEHI_2PXX_S, AArch64::WHILEHI_2PXX_D}))
6316 SelectWhilePair(Node, Op);
6317 return;
6318 case Intrinsic::aarch64_sve_whilehs_x2:
6320 Node->getValueType(0),
6321 {AArch64::WHILEHS_2PXX_B, AArch64::WHILEHS_2PXX_H,
6322 AArch64::WHILEHS_2PXX_S, AArch64::WHILEHS_2PXX_D}))
6323 SelectWhilePair(Node, Op);
6324 return;
6325 case Intrinsic::aarch64_sve_whilele_x2:
6327 Node->getValueType(0),
6328 {AArch64::WHILELE_2PXX_B, AArch64::WHILELE_2PXX_H,
6329 AArch64::WHILELE_2PXX_S, AArch64::WHILELE_2PXX_D}))
6330 SelectWhilePair(Node, Op);
6331 return;
6332 case Intrinsic::aarch64_sve_whilelo_x2:
6334 Node->getValueType(0),
6335 {AArch64::WHILELO_2PXX_B, AArch64::WHILELO_2PXX_H,
6336 AArch64::WHILELO_2PXX_S, AArch64::WHILELO_2PXX_D}))
6337 SelectWhilePair(Node, Op);
6338 return;
6339 case Intrinsic::aarch64_sve_whilels_x2:
6341 Node->getValueType(0),
6342 {AArch64::WHILELS_2PXX_B, AArch64::WHILELS_2PXX_H,
6343 AArch64::WHILELS_2PXX_S, AArch64::WHILELS_2PXX_D}))
6344 SelectWhilePair(Node, Op);
6345 return;
6346 case Intrinsic::aarch64_sve_whilelt_x2:
6348 Node->getValueType(0),
6349 {AArch64::WHILELT_2PXX_B, AArch64::WHILELT_2PXX_H,
6350 AArch64::WHILELT_2PXX_S, AArch64::WHILELT_2PXX_D}))
6351 SelectWhilePair(Node, Op);
6352 return;
6353 case Intrinsic::aarch64_sve_smax_single_x2:
6355 Node->getValueType(0),
6356 {AArch64::SMAX_VG2_2ZZ_B, AArch64::SMAX_VG2_2ZZ_H,
6357 AArch64::SMAX_VG2_2ZZ_S, AArch64::SMAX_VG2_2ZZ_D}))
6358 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6359 return;
6360 case Intrinsic::aarch64_sve_umax_single_x2:
6362 Node->getValueType(0),
6363 {AArch64::UMAX_VG2_2ZZ_B, AArch64::UMAX_VG2_2ZZ_H,
6364 AArch64::UMAX_VG2_2ZZ_S, AArch64::UMAX_VG2_2ZZ_D}))
6365 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6366 return;
6367 case Intrinsic::aarch64_sve_fmax_single_x2:
6369 Node->getValueType(0),
6370 {AArch64::BFMAX_VG2_2ZZ_H, AArch64::FMAX_VG2_2ZZ_H,
6371 AArch64::FMAX_VG2_2ZZ_S, AArch64::FMAX_VG2_2ZZ_D}))
6372 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6373 return;
6374 case Intrinsic::aarch64_sve_smax_single_x4:
6376 Node->getValueType(0),
6377 {AArch64::SMAX_VG4_4ZZ_B, AArch64::SMAX_VG4_4ZZ_H,
6378 AArch64::SMAX_VG4_4ZZ_S, AArch64::SMAX_VG4_4ZZ_D}))
6379 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6380 return;
6381 case Intrinsic::aarch64_sve_umax_single_x4:
6383 Node->getValueType(0),
6384 {AArch64::UMAX_VG4_4ZZ_B, AArch64::UMAX_VG4_4ZZ_H,
6385 AArch64::UMAX_VG4_4ZZ_S, AArch64::UMAX_VG4_4ZZ_D}))
6386 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6387 return;
6388 case Intrinsic::aarch64_sve_fmax_single_x4:
6390 Node->getValueType(0),
6391 {AArch64::BFMAX_VG4_4ZZ_H, AArch64::FMAX_VG4_4ZZ_H,
6392 AArch64::FMAX_VG4_4ZZ_S, AArch64::FMAX_VG4_4ZZ_D}))
6393 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6394 return;
6395 case Intrinsic::aarch64_sve_smin_single_x2:
6397 Node->getValueType(0),
6398 {AArch64::SMIN_VG2_2ZZ_B, AArch64::SMIN_VG2_2ZZ_H,
6399 AArch64::SMIN_VG2_2ZZ_S, AArch64::SMIN_VG2_2ZZ_D}))
6400 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6401 return;
6402 case Intrinsic::aarch64_sve_umin_single_x2:
6404 Node->getValueType(0),
6405 {AArch64::UMIN_VG2_2ZZ_B, AArch64::UMIN_VG2_2ZZ_H,
6406 AArch64::UMIN_VG2_2ZZ_S, AArch64::UMIN_VG2_2ZZ_D}))
6407 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6408 return;
6409 case Intrinsic::aarch64_sve_fmin_single_x2:
6411 Node->getValueType(0),
6412 {AArch64::BFMIN_VG2_2ZZ_H, AArch64::FMIN_VG2_2ZZ_H,
6413 AArch64::FMIN_VG2_2ZZ_S, AArch64::FMIN_VG2_2ZZ_D}))
6414 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6415 return;
6416 case Intrinsic::aarch64_sve_smin_single_x4:
6418 Node->getValueType(0),
6419 {AArch64::SMIN_VG4_4ZZ_B, AArch64::SMIN_VG4_4ZZ_H,
6420 AArch64::SMIN_VG4_4ZZ_S, AArch64::SMIN_VG4_4ZZ_D}))
6421 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6422 return;
6423 case Intrinsic::aarch64_sve_umin_single_x4:
6425 Node->getValueType(0),
6426 {AArch64::UMIN_VG4_4ZZ_B, AArch64::UMIN_VG4_4ZZ_H,
6427 AArch64::UMIN_VG4_4ZZ_S, AArch64::UMIN_VG4_4ZZ_D}))
6428 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6429 return;
6430 case Intrinsic::aarch64_sve_fmin_single_x4:
6432 Node->getValueType(0),
6433 {AArch64::BFMIN_VG4_4ZZ_H, AArch64::FMIN_VG4_4ZZ_H,
6434 AArch64::FMIN_VG4_4ZZ_S, AArch64::FMIN_VG4_4ZZ_D}))
6435 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6436 return;
6437 case Intrinsic::aarch64_sve_smax_x2:
6439 Node->getValueType(0),
6440 {AArch64::SMAX_VG2_2Z2Z_B, AArch64::SMAX_VG2_2Z2Z_H,
6441 AArch64::SMAX_VG2_2Z2Z_S, AArch64::SMAX_VG2_2Z2Z_D}))
6442 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6443 return;
6444 case Intrinsic::aarch64_sve_umax_x2:
6446 Node->getValueType(0),
6447 {AArch64::UMAX_VG2_2Z2Z_B, AArch64::UMAX_VG2_2Z2Z_H,
6448 AArch64::UMAX_VG2_2Z2Z_S, AArch64::UMAX_VG2_2Z2Z_D}))
6449 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6450 return;
6451 case Intrinsic::aarch64_sve_fmax_x2:
6453 Node->getValueType(0),
6454 {AArch64::BFMAX_VG2_2Z2Z_H, AArch64::FMAX_VG2_2Z2Z_H,
6455 AArch64::FMAX_VG2_2Z2Z_S, AArch64::FMAX_VG2_2Z2Z_D}))
6456 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6457 return;
6458 case Intrinsic::aarch64_sve_smax_x4:
6460 Node->getValueType(0),
6461 {AArch64::SMAX_VG4_4Z4Z_B, AArch64::SMAX_VG4_4Z4Z_H,
6462 AArch64::SMAX_VG4_4Z4Z_S, AArch64::SMAX_VG4_4Z4Z_D}))
6463 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6464 return;
6465 case Intrinsic::aarch64_sve_umax_x4:
6467 Node->getValueType(0),
6468 {AArch64::UMAX_VG4_4Z4Z_B, AArch64::UMAX_VG4_4Z4Z_H,
6469 AArch64::UMAX_VG4_4Z4Z_S, AArch64::UMAX_VG4_4Z4Z_D}))
6470 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6471 return;
6472 case Intrinsic::aarch64_sve_fmax_x4:
6474 Node->getValueType(0),
6475 {AArch64::BFMAX_VG4_4Z2Z_H, AArch64::FMAX_VG4_4Z4Z_H,
6476 AArch64::FMAX_VG4_4Z4Z_S, AArch64::FMAX_VG4_4Z4Z_D}))
6477 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6478 return;
6479 case Intrinsic::aarch64_sme_famax_x2:
6481 Node->getValueType(0),
6482 {0, AArch64::FAMAX_2Z2Z_H, AArch64::FAMAX_2Z2Z_S,
6483 AArch64::FAMAX_2Z2Z_D}))
6484 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6485 return;
6486 case Intrinsic::aarch64_sme_famax_x4:
6488 Node->getValueType(0),
6489 {0, AArch64::FAMAX_4Z4Z_H, AArch64::FAMAX_4Z4Z_S,
6490 AArch64::FAMAX_4Z4Z_D}))
6491 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6492 return;
6493 case Intrinsic::aarch64_sme_famin_x2:
6495 Node->getValueType(0),
6496 {0, AArch64::FAMIN_2Z2Z_H, AArch64::FAMIN_2Z2Z_S,
6497 AArch64::FAMIN_2Z2Z_D}))
6498 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6499 return;
6500 case Intrinsic::aarch64_sme_famin_x4:
6502 Node->getValueType(0),
6503 {0, AArch64::FAMIN_4Z4Z_H, AArch64::FAMIN_4Z4Z_S,
6504 AArch64::FAMIN_4Z4Z_D}))
6505 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6506 return;
6507 case Intrinsic::aarch64_sve_smin_x2:
6509 Node->getValueType(0),
6510 {AArch64::SMIN_VG2_2Z2Z_B, AArch64::SMIN_VG2_2Z2Z_H,
6511 AArch64::SMIN_VG2_2Z2Z_S, AArch64::SMIN_VG2_2Z2Z_D}))
6512 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6513 return;
6514 case Intrinsic::aarch64_sve_umin_x2:
6516 Node->getValueType(0),
6517 {AArch64::UMIN_VG2_2Z2Z_B, AArch64::UMIN_VG2_2Z2Z_H,
6518 AArch64::UMIN_VG2_2Z2Z_S, AArch64::UMIN_VG2_2Z2Z_D}))
6519 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6520 return;
6521 case Intrinsic::aarch64_sve_fmin_x2:
6523 Node->getValueType(0),
6524 {AArch64::BFMIN_VG2_2Z2Z_H, AArch64::FMIN_VG2_2Z2Z_H,
6525 AArch64::FMIN_VG2_2Z2Z_S, AArch64::FMIN_VG2_2Z2Z_D}))
6526 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6527 return;
6528 case Intrinsic::aarch64_sve_smin_x4:
6530 Node->getValueType(0),
6531 {AArch64::SMIN_VG4_4Z4Z_B, AArch64::SMIN_VG4_4Z4Z_H,
6532 AArch64::SMIN_VG4_4Z4Z_S, AArch64::SMIN_VG4_4Z4Z_D}))
6533 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6534 return;
6535 case Intrinsic::aarch64_sve_umin_x4:
6537 Node->getValueType(0),
6538 {AArch64::UMIN_VG4_4Z4Z_B, AArch64::UMIN_VG4_4Z4Z_H,
6539 AArch64::UMIN_VG4_4Z4Z_S, AArch64::UMIN_VG4_4Z4Z_D}))
6540 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6541 return;
6542 case Intrinsic::aarch64_sve_fmin_x4:
6544 Node->getValueType(0),
6545 {AArch64::BFMIN_VG4_4Z2Z_H, AArch64::FMIN_VG4_4Z4Z_H,
6546 AArch64::FMIN_VG4_4Z4Z_S, AArch64::FMIN_VG4_4Z4Z_D}))
6547 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6548 return;
6549 case Intrinsic::aarch64_sve_fmaxnm_single_x2 :
6551 Node->getValueType(0),
6552 {AArch64::BFMAXNM_VG2_2ZZ_H, AArch64::FMAXNM_VG2_2ZZ_H,
6553 AArch64::FMAXNM_VG2_2ZZ_S, AArch64::FMAXNM_VG2_2ZZ_D}))
6554 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6555 return;
6556 case Intrinsic::aarch64_sve_fmaxnm_single_x4 :
6558 Node->getValueType(0),
6559 {AArch64::BFMAXNM_VG4_4ZZ_H, AArch64::FMAXNM_VG4_4ZZ_H,
6560 AArch64::FMAXNM_VG4_4ZZ_S, AArch64::FMAXNM_VG4_4ZZ_D}))
6561 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6562 return;
6563 case Intrinsic::aarch64_sve_fminnm_single_x2:
6565 Node->getValueType(0),
6566 {AArch64::BFMINNM_VG2_2ZZ_H, AArch64::FMINNM_VG2_2ZZ_H,
6567 AArch64::FMINNM_VG2_2ZZ_S, AArch64::FMINNM_VG2_2ZZ_D}))
6568 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6569 return;
6570 case Intrinsic::aarch64_sve_fminnm_single_x4:
6572 Node->getValueType(0),
6573 {AArch64::BFMINNM_VG4_4ZZ_H, AArch64::FMINNM_VG4_4ZZ_H,
6574 AArch64::FMINNM_VG4_4ZZ_S, AArch64::FMINNM_VG4_4ZZ_D}))
6575 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6576 return;
6577 case Intrinsic::aarch64_sve_fscale_single_x4:
6578 SelectDestructiveMultiIntrinsic(Node, 4, false, AArch64::BFSCALE_4ZZ);
6579 return;
6580 case Intrinsic::aarch64_sve_fscale_single_x2:
6581 SelectDestructiveMultiIntrinsic(Node, 2, false, AArch64::BFSCALE_2ZZ);
6582 return;
6583 case Intrinsic::aarch64_sve_fmul_single_x4:
6585 Node->getValueType(0),
6586 {AArch64::BFMUL_4ZZ, AArch64::FMUL_4ZZ_H, AArch64::FMUL_4ZZ_S,
6587 AArch64::FMUL_4ZZ_D}))
6588 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6589 return;
6590 case Intrinsic::aarch64_sve_fmul_single_x2:
6592 Node->getValueType(0),
6593 {AArch64::BFMUL_2ZZ, AArch64::FMUL_2ZZ_H, AArch64::FMUL_2ZZ_S,
6594 AArch64::FMUL_2ZZ_D}))
6595 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6596 return;
6597 case Intrinsic::aarch64_sve_fmaxnm_x2:
6599 Node->getValueType(0),
6600 {AArch64::BFMAXNM_VG2_2Z2Z_H, AArch64::FMAXNM_VG2_2Z2Z_H,
6601 AArch64::FMAXNM_VG2_2Z2Z_S, AArch64::FMAXNM_VG2_2Z2Z_D}))
6602 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6603 return;
6604 case Intrinsic::aarch64_sve_fmaxnm_x4:
6606 Node->getValueType(0),
6607 {AArch64::BFMAXNM_VG4_4Z2Z_H, AArch64::FMAXNM_VG4_4Z4Z_H,
6608 AArch64::FMAXNM_VG4_4Z4Z_S, AArch64::FMAXNM_VG4_4Z4Z_D}))
6609 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6610 return;
6611 case Intrinsic::aarch64_sve_fminnm_x2:
6613 Node->getValueType(0),
6614 {AArch64::BFMINNM_VG2_2Z2Z_H, AArch64::FMINNM_VG2_2Z2Z_H,
6615 AArch64::FMINNM_VG2_2Z2Z_S, AArch64::FMINNM_VG2_2Z2Z_D}))
6616 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6617 return;
6618 case Intrinsic::aarch64_sve_fminnm_x4:
6620 Node->getValueType(0),
6621 {AArch64::BFMINNM_VG4_4Z2Z_H, AArch64::FMINNM_VG4_4Z4Z_H,
6622 AArch64::FMINNM_VG4_4Z4Z_S, AArch64::FMINNM_VG4_4Z4Z_D}))
6623 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6624 return;
6625 case Intrinsic::aarch64_sve_aese_lane_x2:
6626 SelectDestructiveMultiIntrinsic(Node, 2, false, AArch64::AESE_2ZZI_B);
6627 return;
6628 case Intrinsic::aarch64_sve_aesd_lane_x2:
6629 SelectDestructiveMultiIntrinsic(Node, 2, false, AArch64::AESD_2ZZI_B);
6630 return;
6631 case Intrinsic::aarch64_sve_aesemc_lane_x2:
6632 SelectDestructiveMultiIntrinsic(Node, 2, false, AArch64::AESEMC_2ZZI_B);
6633 return;
6634 case Intrinsic::aarch64_sve_aesdimc_lane_x2:
6635 SelectDestructiveMultiIntrinsic(Node, 2, false, AArch64::AESDIMC_2ZZI_B);
6636 return;
6637 case Intrinsic::aarch64_sve_aese_lane_x4:
6638 SelectDestructiveMultiIntrinsic(Node, 4, false, AArch64::AESE_4ZZI_B);
6639 return;
6640 case Intrinsic::aarch64_sve_aesd_lane_x4:
6641 SelectDestructiveMultiIntrinsic(Node, 4, false, AArch64::AESD_4ZZI_B);
6642 return;
6643 case Intrinsic::aarch64_sve_aesemc_lane_x4:
6644 SelectDestructiveMultiIntrinsic(Node, 4, false, AArch64::AESEMC_4ZZI_B);
6645 return;
6646 case Intrinsic::aarch64_sve_aesdimc_lane_x4:
6647 SelectDestructiveMultiIntrinsic(Node, 4, false, AArch64::AESDIMC_4ZZI_B);
6648 return;
6649 case Intrinsic::aarch64_sve_pmlal_pair_x2:
6650 SelectDestructiveMultiIntrinsic(Node, 2, false, AArch64::PMLAL_2ZZZ_Q);
6651 return;
6652 case Intrinsic::aarch64_sve_pmull_pair_x2: {
6653 SDLoc DL(Node);
6654 SmallVector<SDValue, 4> Regs(Node->ops().slice(1, 2));
6655 SDNode *Res =
6656 CurDAG->getMachineNode(AArch64::PMULL_2ZZZ_Q, DL, MVT::Untyped, Regs);
6657 SDValue SuperReg = SDValue(Res, 0);
6658 for (unsigned I = 0; I < 2; I++)
6659 ReplaceUses(SDValue(Node, I),
6660 CurDAG->getTargetExtractSubreg(AArch64::zsub0 + I, DL, VT,
6661 SuperReg));
6662 CurDAG->RemoveDeadNode(Node);
6663 return;
6664 }
6665 case Intrinsic::aarch64_sve_fscale_x4:
6666 SelectDestructiveMultiIntrinsic(Node, 4, true, AArch64::BFSCALE_4Z4Z);
6667 return;
6668 case Intrinsic::aarch64_sve_fscale_x2:
6669 SelectDestructiveMultiIntrinsic(Node, 2, true, AArch64::BFSCALE_2Z2Z);
6670 return;
6671 case Intrinsic::aarch64_sve_fmul_x4:
6673 Node->getValueType(0),
6674 {AArch64::BFMUL_4Z4Z, AArch64::FMUL_4Z4Z_H, AArch64::FMUL_4Z4Z_S,
6675 AArch64::FMUL_4Z4Z_D}))
6676 SelectDestructiveMultiIntrinsic(Node, 4, true, Op);
6677 return;
6678 case Intrinsic::aarch64_sve_fmul_x2:
6680 Node->getValueType(0),
6681 {AArch64::BFMUL_2Z2Z, AArch64::FMUL_2Z2Z_H, AArch64::FMUL_2Z2Z_S,
6682 AArch64::FMUL_2Z2Z_D}))
6683 SelectDestructiveMultiIntrinsic(Node, 2, true, Op);
6684 return;
6685 case Intrinsic::aarch64_sve_fcvtzs_x2:
6686 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZS_2Z2Z_StoS);
6687 return;
6688 case Intrinsic::aarch64_sve_scvtf_x2:
6689 SelectCVTIntrinsic(Node, 2, AArch64::SCVTF_2Z2Z_StoS);
6690 return;
6691 case Intrinsic::aarch64_sve_fcvtzu_x2:
6692 SelectCVTIntrinsic(Node, 2, AArch64::FCVTZU_2Z2Z_StoS);
6693 return;
6694 case Intrinsic::aarch64_sve_ucvtf_x2:
6695 SelectCVTIntrinsic(Node, 2, AArch64::UCVTF_2Z2Z_StoS);
6696 return;
6697 case Intrinsic::aarch64_sve_fcvtzs_x4:
6698 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZS_4Z4Z_StoS);
6699 return;
6700 case Intrinsic::aarch64_sve_scvtf_x4:
6701 SelectCVTIntrinsic(Node, 4, AArch64::SCVTF_4Z4Z_StoS);
6702 return;
6703 case Intrinsic::aarch64_sve_fcvtzu_x4:
6704 SelectCVTIntrinsic(Node, 4, AArch64::FCVTZU_4Z4Z_StoS);
6705 return;
6706 case Intrinsic::aarch64_sve_ucvtf_x4:
6707 SelectCVTIntrinsic(Node, 4, AArch64::UCVTF_4Z4Z_StoS);
6708 return;
6709 case Intrinsic::aarch64_sve_fcvt_widen_x2:
6710 SelectUnaryMultiIntrinsic(Node, 2, false, AArch64::FCVT_2ZZ_H_S);
6711 return;
6712 case Intrinsic::aarch64_sve_fcvtl_widen_x2:
6713 SelectUnaryMultiIntrinsic(Node, 2, false, AArch64::FCVTL_2ZZ_H_S);
6714 return;
6715 case Intrinsic::aarch64_sve_sclamp_single_x2:
6717 Node->getValueType(0),
6718 {AArch64::SCLAMP_VG2_2Z2Z_B, AArch64::SCLAMP_VG2_2Z2Z_H,
6719 AArch64::SCLAMP_VG2_2Z2Z_S, AArch64::SCLAMP_VG2_2Z2Z_D}))
6720 SelectClamp(Node, 2, Op);
6721 return;
6722 case Intrinsic::aarch64_sve_uclamp_single_x2:
6724 Node->getValueType(0),
6725 {AArch64::UCLAMP_VG2_2Z2Z_B, AArch64::UCLAMP_VG2_2Z2Z_H,
6726 AArch64::UCLAMP_VG2_2Z2Z_S, AArch64::UCLAMP_VG2_2Z2Z_D}))
6727 SelectClamp(Node, 2, Op);
6728 return;
6729 case Intrinsic::aarch64_sve_fclamp_single_x2:
6731 Node->getValueType(0),
6732 {0, AArch64::FCLAMP_VG2_2Z2Z_H, AArch64::FCLAMP_VG2_2Z2Z_S,
6733 AArch64::FCLAMP_VG2_2Z2Z_D}))
6734 SelectClamp(Node, 2, Op);
6735 return;
6736 case Intrinsic::aarch64_sve_bfclamp_single_x2:
6737 SelectClamp(Node, 2, AArch64::BFCLAMP_VG2_2ZZZ_H);
6738 return;
6739 case Intrinsic::aarch64_sve_sclamp_single_x4:
6741 Node->getValueType(0),
6742 {AArch64::SCLAMP_VG4_4Z4Z_B, AArch64::SCLAMP_VG4_4Z4Z_H,
6743 AArch64::SCLAMP_VG4_4Z4Z_S, AArch64::SCLAMP_VG4_4Z4Z_D}))
6744 SelectClamp(Node, 4, Op);
6745 return;
6746 case Intrinsic::aarch64_sve_uclamp_single_x4:
6748 Node->getValueType(0),
6749 {AArch64::UCLAMP_VG4_4Z4Z_B, AArch64::UCLAMP_VG4_4Z4Z_H,
6750 AArch64::UCLAMP_VG4_4Z4Z_S, AArch64::UCLAMP_VG4_4Z4Z_D}))
6751 SelectClamp(Node, 4, Op);
6752 return;
6753 case Intrinsic::aarch64_sve_fclamp_single_x4:
6755 Node->getValueType(0),
6756 {0, AArch64::FCLAMP_VG4_4Z4Z_H, AArch64::FCLAMP_VG4_4Z4Z_S,
6757 AArch64::FCLAMP_VG4_4Z4Z_D}))
6758 SelectClamp(Node, 4, Op);
6759 return;
6760 case Intrinsic::aarch64_sve_bfclamp_single_x4:
6761 SelectClamp(Node, 4, AArch64::BFCLAMP_VG4_4ZZZ_H);
6762 return;
6763 case Intrinsic::aarch64_sve_add_single_x2:
6765 Node->getValueType(0),
6766 {AArch64::ADD_VG2_2ZZ_B, AArch64::ADD_VG2_2ZZ_H,
6767 AArch64::ADD_VG2_2ZZ_S, AArch64::ADD_VG2_2ZZ_D}))
6768 SelectDestructiveMultiIntrinsic(Node, 2, false, Op);
6769 return;
6770 case Intrinsic::aarch64_sve_add_single_x4:
6772 Node->getValueType(0),
6773 {AArch64::ADD_VG4_4ZZ_B, AArch64::ADD_VG4_4ZZ_H,
6774 AArch64::ADD_VG4_4ZZ_S, AArch64::ADD_VG4_4ZZ_D}))
6775 SelectDestructiveMultiIntrinsic(Node, 4, false, Op);
6776 return;
6777 case Intrinsic::aarch64_sve_zip_x2:
6779 Node->getValueType(0),
6780 {AArch64::ZIP_VG2_2ZZZ_B, AArch64::ZIP_VG2_2ZZZ_H,
6781 AArch64::ZIP_VG2_2ZZZ_S, AArch64::ZIP_VG2_2ZZZ_D}))
6782 SelectUnaryMultiIntrinsic(Node, 2, /*IsTupleInput=*/false, Op);
6783 return;
6784 case Intrinsic::aarch64_sve_zipq_x2:
6785 SelectUnaryMultiIntrinsic(Node, 2, /*IsTupleInput=*/false,
6786 AArch64::ZIP_VG2_2ZZZ_Q);
6787 return;
6788 case Intrinsic::aarch64_sve_zip_x4:
6790 Node->getValueType(0),
6791 {AArch64::ZIP_VG4_4Z4Z_B, AArch64::ZIP_VG4_4Z4Z_H,
6792 AArch64::ZIP_VG4_4Z4Z_S, AArch64::ZIP_VG4_4Z4Z_D}))
6793 SelectUnaryMultiIntrinsic(Node, 4, /*IsTupleInput=*/true, Op);
6794 return;
6795 case Intrinsic::aarch64_sve_zipq_x4:
6796 SelectUnaryMultiIntrinsic(Node, 4, /*IsTupleInput=*/true,
6797 AArch64::ZIP_VG4_4Z4Z_Q);
6798 return;
6799 case Intrinsic::aarch64_sve_uzp_x2:
6801 Node->getValueType(0),
6802 {AArch64::UZP_VG2_2ZZZ_B, AArch64::UZP_VG2_2ZZZ_H,
6803 AArch64::UZP_VG2_2ZZZ_S, AArch64::UZP_VG2_2ZZZ_D}))
6804 SelectUnaryMultiIntrinsic(Node, 2, /*IsTupleInput=*/false, Op);
6805 return;
6806 case Intrinsic::aarch64_sve_uzpq_x2:
6807 SelectUnaryMultiIntrinsic(Node, 2, /*IsTupleInput=*/false,
6808 AArch64::UZP_VG2_2ZZZ_Q);
6809 return;
6810 case Intrinsic::aarch64_sve_uzp_x4:
6812 Node->getValueType(0),
6813 {AArch64::UZP_VG4_4Z4Z_B, AArch64::UZP_VG4_4Z4Z_H,
6814 AArch64::UZP_VG4_4Z4Z_S, AArch64::UZP_VG4_4Z4Z_D}))
6815 SelectUnaryMultiIntrinsic(Node, 4, /*IsTupleInput=*/true, Op);
6816 return;
6817 case Intrinsic::aarch64_sve_uzpq_x4:
6818 SelectUnaryMultiIntrinsic(Node, 4, /*IsTupleInput=*/true,
6819 AArch64::UZP_VG4_4Z4Z_Q);
6820 return;
6821 case Intrinsic::aarch64_sve_sel_x2:
6823 Node->getValueType(0),
6824 {AArch64::SEL_VG2_2ZC2Z2Z_B, AArch64::SEL_VG2_2ZC2Z2Z_H,
6825 AArch64::SEL_VG2_2ZC2Z2Z_S, AArch64::SEL_VG2_2ZC2Z2Z_D}))
6826 SelectDestructiveMultiIntrinsic(Node, 2, true, Op, /*HasPred=*/true);
6827 return;
6828 case Intrinsic::aarch64_sve_sel_x4:
6830 Node->getValueType(0),
6831 {AArch64::SEL_VG4_4ZC4Z4Z_B, AArch64::SEL_VG4_4ZC4Z4Z_H,
6832 AArch64::SEL_VG4_4ZC4Z4Z_S, AArch64::SEL_VG4_4ZC4Z4Z_D}))
6833 SelectDestructiveMultiIntrinsic(Node, 4, true, Op, /*HasPred=*/true);
6834 return;
6835 case Intrinsic::aarch64_sve_frinta_x2:
6836 SelectFrintFromVT(Node, 2, AArch64::FRINTA_2Z2Z_S);
6837 return;
6838 case Intrinsic::aarch64_sve_frinta_x4:
6839 SelectFrintFromVT(Node, 4, AArch64::FRINTA_4Z4Z_S);
6840 return;
6841 case Intrinsic::aarch64_sve_frintm_x2:
6842 SelectFrintFromVT(Node, 2, AArch64::FRINTM_2Z2Z_S);
6843 return;
6844 case Intrinsic::aarch64_sve_frintm_x4:
6845 SelectFrintFromVT(Node, 4, AArch64::FRINTM_4Z4Z_S);
6846 return;
6847 case Intrinsic::aarch64_sve_frintn_x2:
6848 SelectFrintFromVT(Node, 2, AArch64::FRINTN_2Z2Z_S);
6849 return;
6850 case Intrinsic::aarch64_sve_frintn_x4:
6851 SelectFrintFromVT(Node, 4, AArch64::FRINTN_4Z4Z_S);
6852 return;
6853 case Intrinsic::aarch64_sve_frintp_x2:
6854 SelectFrintFromVT(Node, 2, AArch64::FRINTP_2Z2Z_S);
6855 return;
6856 case Intrinsic::aarch64_sve_frintp_x4:
6857 SelectFrintFromVT(Node, 4, AArch64::FRINTP_4Z4Z_S);
6858 return;
6859 case Intrinsic::aarch64_sve_sunpk_x2:
6861 Node->getValueType(0),
6862 {0, AArch64::SUNPK_VG2_2ZZ_H, AArch64::SUNPK_VG2_2ZZ_S,
6863 AArch64::SUNPK_VG2_2ZZ_D}))
6864 SelectUnaryMultiIntrinsic(Node, 2, /*IsTupleInput=*/false, Op);
6865 return;
6866 case Intrinsic::aarch64_sve_uunpk_x2:
6868 Node->getValueType(0),
6869 {0, AArch64::UUNPK_VG2_2ZZ_H, AArch64::UUNPK_VG2_2ZZ_S,
6870 AArch64::UUNPK_VG2_2ZZ_D}))
6871 SelectUnaryMultiIntrinsic(Node, 2, /*IsTupleInput=*/false, Op);
6872 return;
6873 case Intrinsic::aarch64_sve_sunpk_x4:
6875 Node->getValueType(0),
6876 {0, AArch64::SUNPK_VG4_4Z2Z_H, AArch64::SUNPK_VG4_4Z2Z_S,
6877 AArch64::SUNPK_VG4_4Z2Z_D}))
6878 SelectUnaryMultiIntrinsic(Node, 4, /*IsTupleInput=*/true, Op);
6879 return;
6880 case Intrinsic::aarch64_sve_uunpk_x4:
6882 Node->getValueType(0),
6883 {0, AArch64::UUNPK_VG4_4Z2Z_H, AArch64::UUNPK_VG4_4Z2Z_S,
6884 AArch64::UUNPK_VG4_4Z2Z_D}))
6885 SelectUnaryMultiIntrinsic(Node, 4, /*IsTupleInput=*/true, Op);
6886 return;
6887 case Intrinsic::aarch64_sve_pext_x2: {
6889 Node->getValueType(0),
6890 {AArch64::PEXT_2PCI_B, AArch64::PEXT_2PCI_H, AArch64::PEXT_2PCI_S,
6891 AArch64::PEXT_2PCI_D}))
6892 SelectPExtPair(Node, Op);
6893 return;
6894 }
6895 }
6896 break;
6897 }
6898 case ISD::INTRINSIC_VOID: {
6899 unsigned IntNo = Node->getConstantOperandVal(1);
6900 if (Node->getNumOperands() >= 3)
6901 VT = Node->getOperand(2)->getValueType(0);
6902 switch (IntNo) {
6903 default:
6904 break;
6905 case Intrinsic::aarch64_neon_st1x2: {
6906 if (VT == MVT::v8i8) {
6907 SelectStore(Node, 2, AArch64::ST1Twov8b);
6908 return;
6909 } else if (VT == MVT::v16i8) {
6910 SelectStore(Node, 2, AArch64::ST1Twov16b);
6911 return;
6912 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6913 VT == MVT::v4bf16) {
6914 SelectStore(Node, 2, AArch64::ST1Twov4h);
6915 return;
6916 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6917 VT == MVT::v8bf16) {
6918 SelectStore(Node, 2, AArch64::ST1Twov8h);
6919 return;
6920 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6921 SelectStore(Node, 2, AArch64::ST1Twov2s);
6922 return;
6923 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6924 SelectStore(Node, 2, AArch64::ST1Twov4s);
6925 return;
6926 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6927 SelectStore(Node, 2, AArch64::ST1Twov2d);
6928 return;
6929 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6930 SelectStore(Node, 2, AArch64::ST1Twov1d);
6931 return;
6932 }
6933 break;
6934 }
6935 case Intrinsic::aarch64_neon_st1x3: {
6936 if (VT == MVT::v8i8) {
6937 SelectStore(Node, 3, AArch64::ST1Threev8b);
6938 return;
6939 } else if (VT == MVT::v16i8) {
6940 SelectStore(Node, 3, AArch64::ST1Threev16b);
6941 return;
6942 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6943 VT == MVT::v4bf16) {
6944 SelectStore(Node, 3, AArch64::ST1Threev4h);
6945 return;
6946 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6947 VT == MVT::v8bf16) {
6948 SelectStore(Node, 3, AArch64::ST1Threev8h);
6949 return;
6950 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6951 SelectStore(Node, 3, AArch64::ST1Threev2s);
6952 return;
6953 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6954 SelectStore(Node, 3, AArch64::ST1Threev4s);
6955 return;
6956 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6957 SelectStore(Node, 3, AArch64::ST1Threev2d);
6958 return;
6959 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6960 SelectStore(Node, 3, AArch64::ST1Threev1d);
6961 return;
6962 }
6963 break;
6964 }
6965 case Intrinsic::aarch64_neon_st1x4: {
6966 if (VT == MVT::v8i8) {
6967 SelectStore(Node, 4, AArch64::ST1Fourv8b);
6968 return;
6969 } else if (VT == MVT::v16i8) {
6970 SelectStore(Node, 4, AArch64::ST1Fourv16b);
6971 return;
6972 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
6973 VT == MVT::v4bf16) {
6974 SelectStore(Node, 4, AArch64::ST1Fourv4h);
6975 return;
6976 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
6977 VT == MVT::v8bf16) {
6978 SelectStore(Node, 4, AArch64::ST1Fourv8h);
6979 return;
6980 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
6981 SelectStore(Node, 4, AArch64::ST1Fourv2s);
6982 return;
6983 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
6984 SelectStore(Node, 4, AArch64::ST1Fourv4s);
6985 return;
6986 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
6987 SelectStore(Node, 4, AArch64::ST1Fourv2d);
6988 return;
6989 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
6990 SelectStore(Node, 4, AArch64::ST1Fourv1d);
6991 return;
6992 }
6993 break;
6994 }
6995 case Intrinsic::aarch64_neon_st2: {
6996 if (VT == MVT::v8i8) {
6997 SelectStore(Node, 2, AArch64::ST2Twov8b);
6998 return;
6999 } else if (VT == MVT::v16i8) {
7000 SelectStore(Node, 2, AArch64::ST2Twov16b);
7001 return;
7002 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7003 VT == MVT::v4bf16) {
7004 SelectStore(Node, 2, AArch64::ST2Twov4h);
7005 return;
7006 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7007 VT == MVT::v8bf16) {
7008 SelectStore(Node, 2, AArch64::ST2Twov8h);
7009 return;
7010 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7011 SelectStore(Node, 2, AArch64::ST2Twov2s);
7012 return;
7013 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7014 SelectStore(Node, 2, AArch64::ST2Twov4s);
7015 return;
7016 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7017 SelectStore(Node, 2, AArch64::ST2Twov2d);
7018 return;
7019 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7020 SelectStore(Node, 2, AArch64::ST1Twov1d);
7021 return;
7022 }
7023 break;
7024 }
7025 case Intrinsic::aarch64_neon_st3: {
7026 if (VT == MVT::v8i8) {
7027 SelectStore(Node, 3, AArch64::ST3Threev8b);
7028 return;
7029 } else if (VT == MVT::v16i8) {
7030 SelectStore(Node, 3, AArch64::ST3Threev16b);
7031 return;
7032 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7033 VT == MVT::v4bf16) {
7034 SelectStore(Node, 3, AArch64::ST3Threev4h);
7035 return;
7036 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7037 VT == MVT::v8bf16) {
7038 SelectStore(Node, 3, AArch64::ST3Threev8h);
7039 return;
7040 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7041 SelectStore(Node, 3, AArch64::ST3Threev2s);
7042 return;
7043 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7044 SelectStore(Node, 3, AArch64::ST3Threev4s);
7045 return;
7046 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7047 SelectStore(Node, 3, AArch64::ST3Threev2d);
7048 return;
7049 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7050 SelectStore(Node, 3, AArch64::ST1Threev1d);
7051 return;
7052 }
7053 break;
7054 }
7055 case Intrinsic::aarch64_neon_st4: {
7056 if (VT == MVT::v8i8) {
7057 SelectStore(Node, 4, AArch64::ST4Fourv8b);
7058 return;
7059 } else if (VT == MVT::v16i8) {
7060 SelectStore(Node, 4, AArch64::ST4Fourv16b);
7061 return;
7062 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 ||
7063 VT == MVT::v4bf16) {
7064 SelectStore(Node, 4, AArch64::ST4Fourv4h);
7065 return;
7066 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 ||
7067 VT == MVT::v8bf16) {
7068 SelectStore(Node, 4, AArch64::ST4Fourv8h);
7069 return;
7070 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7071 SelectStore(Node, 4, AArch64::ST4Fourv2s);
7072 return;
7073 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7074 SelectStore(Node, 4, AArch64::ST4Fourv4s);
7075 return;
7076 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7077 SelectStore(Node, 4, AArch64::ST4Fourv2d);
7078 return;
7079 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7080 SelectStore(Node, 4, AArch64::ST1Fourv1d);
7081 return;
7082 }
7083 break;
7084 }
7085 case Intrinsic::aarch64_neon_st2lane: {
7086 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7087 SelectStoreLane(Node, 2, AArch64::ST2i8);
7088 return;
7089 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7090 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7091 SelectStoreLane(Node, 2, AArch64::ST2i16);
7092 return;
7093 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7094 VT == MVT::v2f32) {
7095 SelectStoreLane(Node, 2, AArch64::ST2i32);
7096 return;
7097 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7098 VT == MVT::v1f64) {
7099 SelectStoreLane(Node, 2, AArch64::ST2i64);
7100 return;
7101 }
7102 break;
7103 }
7104 case Intrinsic::aarch64_neon_st3lane: {
7105 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7106 SelectStoreLane(Node, 3, AArch64::ST3i8);
7107 return;
7108 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7109 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7110 SelectStoreLane(Node, 3, AArch64::ST3i16);
7111 return;
7112 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7113 VT == MVT::v2f32) {
7114 SelectStoreLane(Node, 3, AArch64::ST3i32);
7115 return;
7116 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7117 VT == MVT::v1f64) {
7118 SelectStoreLane(Node, 3, AArch64::ST3i64);
7119 return;
7120 }
7121 break;
7122 }
7123 case Intrinsic::aarch64_neon_st4lane: {
7124 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7125 SelectStoreLane(Node, 4, AArch64::ST4i8);
7126 return;
7127 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7128 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7129 SelectStoreLane(Node, 4, AArch64::ST4i16);
7130 return;
7131 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7132 VT == MVT::v2f32) {
7133 SelectStoreLane(Node, 4, AArch64::ST4i32);
7134 return;
7135 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7136 VT == MVT::v1f64) {
7137 SelectStoreLane(Node, 4, AArch64::ST4i64);
7138 return;
7139 }
7140 break;
7141 }
7142 case Intrinsic::aarch64_sve_st2q: {
7143 SelectPredicatedStore(Node, 2, 4, AArch64::ST2Q, AArch64::ST2Q_IMM);
7144 return;
7145 }
7146 case Intrinsic::aarch64_sve_st3q: {
7147 SelectPredicatedStore(Node, 3, 4, AArch64::ST3Q, AArch64::ST3Q_IMM);
7148 return;
7149 }
7150 case Intrinsic::aarch64_sve_st4q: {
7151 SelectPredicatedStore(Node, 4, 4, AArch64::ST4Q, AArch64::ST4Q_IMM);
7152 return;
7153 }
7154 case Intrinsic::aarch64_sve_st2: {
7155 if (VT == MVT::nxv16i8) {
7156 SelectPredicatedStore(Node, 2, 0, AArch64::ST2B, AArch64::ST2B_IMM);
7157 return;
7158 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7159 VT == MVT::nxv8bf16) {
7160 SelectPredicatedStore(Node, 2, 1, AArch64::ST2H, AArch64::ST2H_IMM);
7161 return;
7162 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7163 SelectPredicatedStore(Node, 2, 2, AArch64::ST2W, AArch64::ST2W_IMM);
7164 return;
7165 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7166 SelectPredicatedStore(Node, 2, 3, AArch64::ST2D, AArch64::ST2D_IMM);
7167 return;
7168 }
7169 break;
7170 }
7171 case Intrinsic::aarch64_sve_st3: {
7172 if (VT == MVT::nxv16i8) {
7173 SelectPredicatedStore(Node, 3, 0, AArch64::ST3B, AArch64::ST3B_IMM);
7174 return;
7175 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7176 VT == MVT::nxv8bf16) {
7177 SelectPredicatedStore(Node, 3, 1, AArch64::ST3H, AArch64::ST3H_IMM);
7178 return;
7179 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7180 SelectPredicatedStore(Node, 3, 2, AArch64::ST3W, AArch64::ST3W_IMM);
7181 return;
7182 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7183 SelectPredicatedStore(Node, 3, 3, AArch64::ST3D, AArch64::ST3D_IMM);
7184 return;
7185 }
7186 break;
7187 }
7188 case Intrinsic::aarch64_sve_st4: {
7189 if (VT == MVT::nxv16i8) {
7190 SelectPredicatedStore(Node, 4, 0, AArch64::ST4B, AArch64::ST4B_IMM);
7191 return;
7192 } else if (VT == MVT::nxv8i16 || VT == MVT::nxv8f16 ||
7193 VT == MVT::nxv8bf16) {
7194 SelectPredicatedStore(Node, 4, 1, AArch64::ST4H, AArch64::ST4H_IMM);
7195 return;
7196 } else if (VT == MVT::nxv4i32 || VT == MVT::nxv4f32) {
7197 SelectPredicatedStore(Node, 4, 2, AArch64::ST4W, AArch64::ST4W_IMM);
7198 return;
7199 } else if (VT == MVT::nxv2i64 || VT == MVT::nxv2f64) {
7200 SelectPredicatedStore(Node, 4, 3, AArch64::ST4D, AArch64::ST4D_IMM);
7201 return;
7202 }
7203 break;
7204 }
7205 }
7206 break;
7207 }
7208 case AArch64ISD::LD2post: {
7209 if (VT == MVT::v8i8) {
7210 SelectPostLoad(Node, 2, AArch64::LD2Twov8b_POST, AArch64::dsub0);
7211 return;
7212 } else if (VT == MVT::v16i8) {
7213 SelectPostLoad(Node, 2, AArch64::LD2Twov16b_POST, AArch64::qsub0);
7214 return;
7215 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7216 SelectPostLoad(Node, 2, AArch64::LD2Twov4h_POST, AArch64::dsub0);
7217 return;
7218 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7219 SelectPostLoad(Node, 2, AArch64::LD2Twov8h_POST, AArch64::qsub0);
7220 return;
7221 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7222 SelectPostLoad(Node, 2, AArch64::LD2Twov2s_POST, AArch64::dsub0);
7223 return;
7224 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7225 SelectPostLoad(Node, 2, AArch64::LD2Twov4s_POST, AArch64::qsub0);
7226 return;
7227 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7228 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7229 return;
7230 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7231 SelectPostLoad(Node, 2, AArch64::LD2Twov2d_POST, AArch64::qsub0);
7232 return;
7233 }
7234 break;
7235 }
7236 case AArch64ISD::LD3post: {
7237 if (VT == MVT::v8i8) {
7238 SelectPostLoad(Node, 3, AArch64::LD3Threev8b_POST, AArch64::dsub0);
7239 return;
7240 } else if (VT == MVT::v16i8) {
7241 SelectPostLoad(Node, 3, AArch64::LD3Threev16b_POST, AArch64::qsub0);
7242 return;
7243 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7244 SelectPostLoad(Node, 3, AArch64::LD3Threev4h_POST, AArch64::dsub0);
7245 return;
7246 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7247 SelectPostLoad(Node, 3, AArch64::LD3Threev8h_POST, AArch64::qsub0);
7248 return;
7249 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7250 SelectPostLoad(Node, 3, AArch64::LD3Threev2s_POST, AArch64::dsub0);
7251 return;
7252 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7253 SelectPostLoad(Node, 3, AArch64::LD3Threev4s_POST, AArch64::qsub0);
7254 return;
7255 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7256 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7257 return;
7258 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7259 SelectPostLoad(Node, 3, AArch64::LD3Threev2d_POST, AArch64::qsub0);
7260 return;
7261 }
7262 break;
7263 }
7264 case AArch64ISD::LD4post: {
7265 if (VT == MVT::v8i8) {
7266 SelectPostLoad(Node, 4, AArch64::LD4Fourv8b_POST, AArch64::dsub0);
7267 return;
7268 } else if (VT == MVT::v16i8) {
7269 SelectPostLoad(Node, 4, AArch64::LD4Fourv16b_POST, AArch64::qsub0);
7270 return;
7271 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7272 SelectPostLoad(Node, 4, AArch64::LD4Fourv4h_POST, AArch64::dsub0);
7273 return;
7274 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7275 SelectPostLoad(Node, 4, AArch64::LD4Fourv8h_POST, AArch64::qsub0);
7276 return;
7277 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7278 SelectPostLoad(Node, 4, AArch64::LD4Fourv2s_POST, AArch64::dsub0);
7279 return;
7280 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7281 SelectPostLoad(Node, 4, AArch64::LD4Fourv4s_POST, AArch64::qsub0);
7282 return;
7283 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7284 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7285 return;
7286 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7287 SelectPostLoad(Node, 4, AArch64::LD4Fourv2d_POST, AArch64::qsub0);
7288 return;
7289 }
7290 break;
7291 }
7292 case AArch64ISD::LD1x2post: {
7293 if (VT == MVT::v8i8) {
7294 SelectPostLoad(Node, 2, AArch64::LD1Twov8b_POST, AArch64::dsub0);
7295 return;
7296 } else if (VT == MVT::v16i8) {
7297 SelectPostLoad(Node, 2, AArch64::LD1Twov16b_POST, AArch64::qsub0);
7298 return;
7299 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7300 SelectPostLoad(Node, 2, AArch64::LD1Twov4h_POST, AArch64::dsub0);
7301 return;
7302 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7303 SelectPostLoad(Node, 2, AArch64::LD1Twov8h_POST, AArch64::qsub0);
7304 return;
7305 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7306 SelectPostLoad(Node, 2, AArch64::LD1Twov2s_POST, AArch64::dsub0);
7307 return;
7308 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7309 SelectPostLoad(Node, 2, AArch64::LD1Twov4s_POST, AArch64::qsub0);
7310 return;
7311 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7312 SelectPostLoad(Node, 2, AArch64::LD1Twov1d_POST, AArch64::dsub0);
7313 return;
7314 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7315 SelectPostLoad(Node, 2, AArch64::LD1Twov2d_POST, AArch64::qsub0);
7316 return;
7317 }
7318 break;
7319 }
7320 case AArch64ISD::LD1x3post: {
7321 if (VT == MVT::v8i8) {
7322 SelectPostLoad(Node, 3, AArch64::LD1Threev8b_POST, AArch64::dsub0);
7323 return;
7324 } else if (VT == MVT::v16i8) {
7325 SelectPostLoad(Node, 3, AArch64::LD1Threev16b_POST, AArch64::qsub0);
7326 return;
7327 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7328 SelectPostLoad(Node, 3, AArch64::LD1Threev4h_POST, AArch64::dsub0);
7329 return;
7330 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7331 SelectPostLoad(Node, 3, AArch64::LD1Threev8h_POST, AArch64::qsub0);
7332 return;
7333 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7334 SelectPostLoad(Node, 3, AArch64::LD1Threev2s_POST, AArch64::dsub0);
7335 return;
7336 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7337 SelectPostLoad(Node, 3, AArch64::LD1Threev4s_POST, AArch64::qsub0);
7338 return;
7339 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7340 SelectPostLoad(Node, 3, AArch64::LD1Threev1d_POST, AArch64::dsub0);
7341 return;
7342 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7343 SelectPostLoad(Node, 3, AArch64::LD1Threev2d_POST, AArch64::qsub0);
7344 return;
7345 }
7346 break;
7347 }
7348 case AArch64ISD::LD1x4post: {
7349 if (VT == MVT::v8i8) {
7350 SelectPostLoad(Node, 4, AArch64::LD1Fourv8b_POST, AArch64::dsub0);
7351 return;
7352 } else if (VT == MVT::v16i8) {
7353 SelectPostLoad(Node, 4, AArch64::LD1Fourv16b_POST, AArch64::qsub0);
7354 return;
7355 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7356 SelectPostLoad(Node, 4, AArch64::LD1Fourv4h_POST, AArch64::dsub0);
7357 return;
7358 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7359 SelectPostLoad(Node, 4, AArch64::LD1Fourv8h_POST, AArch64::qsub0);
7360 return;
7361 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7362 SelectPostLoad(Node, 4, AArch64::LD1Fourv2s_POST, AArch64::dsub0);
7363 return;
7364 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7365 SelectPostLoad(Node, 4, AArch64::LD1Fourv4s_POST, AArch64::qsub0);
7366 return;
7367 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7368 SelectPostLoad(Node, 4, AArch64::LD1Fourv1d_POST, AArch64::dsub0);
7369 return;
7370 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7371 SelectPostLoad(Node, 4, AArch64::LD1Fourv2d_POST, AArch64::qsub0);
7372 return;
7373 }
7374 break;
7375 }
7376 case AArch64ISD::LD1DUPpost: {
7377 if (VT == MVT::v8i8) {
7378 SelectPostLoad(Node, 1, AArch64::LD1Rv8b_POST, AArch64::dsub0);
7379 return;
7380 } else if (VT == MVT::v16i8) {
7381 SelectPostLoad(Node, 1, AArch64::LD1Rv16b_POST, AArch64::qsub0);
7382 return;
7383 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7384 SelectPostLoad(Node, 1, AArch64::LD1Rv4h_POST, AArch64::dsub0);
7385 return;
7386 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7387 SelectPostLoad(Node, 1, AArch64::LD1Rv8h_POST, AArch64::qsub0);
7388 return;
7389 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7390 SelectPostLoad(Node, 1, AArch64::LD1Rv2s_POST, AArch64::dsub0);
7391 return;
7392 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7393 SelectPostLoad(Node, 1, AArch64::LD1Rv4s_POST, AArch64::qsub0);
7394 return;
7395 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7396 SelectPostLoad(Node, 1, AArch64::LD1Rv1d_POST, AArch64::dsub0);
7397 return;
7398 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7399 SelectPostLoad(Node, 1, AArch64::LD1Rv2d_POST, AArch64::qsub0);
7400 return;
7401 }
7402 break;
7403 }
7404 case AArch64ISD::LD2DUPpost: {
7405 if (VT == MVT::v8i8) {
7406 SelectPostLoad(Node, 2, AArch64::LD2Rv8b_POST, AArch64::dsub0);
7407 return;
7408 } else if (VT == MVT::v16i8) {
7409 SelectPostLoad(Node, 2, AArch64::LD2Rv16b_POST, AArch64::qsub0);
7410 return;
7411 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7412 SelectPostLoad(Node, 2, AArch64::LD2Rv4h_POST, AArch64::dsub0);
7413 return;
7414 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7415 SelectPostLoad(Node, 2, AArch64::LD2Rv8h_POST, AArch64::qsub0);
7416 return;
7417 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7418 SelectPostLoad(Node, 2, AArch64::LD2Rv2s_POST, AArch64::dsub0);
7419 return;
7420 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7421 SelectPostLoad(Node, 2, AArch64::LD2Rv4s_POST, AArch64::qsub0);
7422 return;
7423 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7424 SelectPostLoad(Node, 2, AArch64::LD2Rv1d_POST, AArch64::dsub0);
7425 return;
7426 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7427 SelectPostLoad(Node, 2, AArch64::LD2Rv2d_POST, AArch64::qsub0);
7428 return;
7429 }
7430 break;
7431 }
7432 case AArch64ISD::LD3DUPpost: {
7433 if (VT == MVT::v8i8) {
7434 SelectPostLoad(Node, 3, AArch64::LD3Rv8b_POST, AArch64::dsub0);
7435 return;
7436 } else if (VT == MVT::v16i8) {
7437 SelectPostLoad(Node, 3, AArch64::LD3Rv16b_POST, AArch64::qsub0);
7438 return;
7439 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7440 SelectPostLoad(Node, 3, AArch64::LD3Rv4h_POST, AArch64::dsub0);
7441 return;
7442 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7443 SelectPostLoad(Node, 3, AArch64::LD3Rv8h_POST, AArch64::qsub0);
7444 return;
7445 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7446 SelectPostLoad(Node, 3, AArch64::LD3Rv2s_POST, AArch64::dsub0);
7447 return;
7448 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7449 SelectPostLoad(Node, 3, AArch64::LD3Rv4s_POST, AArch64::qsub0);
7450 return;
7451 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7452 SelectPostLoad(Node, 3, AArch64::LD3Rv1d_POST, AArch64::dsub0);
7453 return;
7454 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7455 SelectPostLoad(Node, 3, AArch64::LD3Rv2d_POST, AArch64::qsub0);
7456 return;
7457 }
7458 break;
7459 }
7460 case AArch64ISD::LD4DUPpost: {
7461 if (VT == MVT::v8i8) {
7462 SelectPostLoad(Node, 4, AArch64::LD4Rv8b_POST, AArch64::dsub0);
7463 return;
7464 } else if (VT == MVT::v16i8) {
7465 SelectPostLoad(Node, 4, AArch64::LD4Rv16b_POST, AArch64::qsub0);
7466 return;
7467 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7468 SelectPostLoad(Node, 4, AArch64::LD4Rv4h_POST, AArch64::dsub0);
7469 return;
7470 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7471 SelectPostLoad(Node, 4, AArch64::LD4Rv8h_POST, AArch64::qsub0);
7472 return;
7473 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7474 SelectPostLoad(Node, 4, AArch64::LD4Rv2s_POST, AArch64::dsub0);
7475 return;
7476 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7477 SelectPostLoad(Node, 4, AArch64::LD4Rv4s_POST, AArch64::qsub0);
7478 return;
7479 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7480 SelectPostLoad(Node, 4, AArch64::LD4Rv1d_POST, AArch64::dsub0);
7481 return;
7482 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7483 SelectPostLoad(Node, 4, AArch64::LD4Rv2d_POST, AArch64::qsub0);
7484 return;
7485 }
7486 break;
7487 }
7488 case AArch64ISD::LD1LANEpost: {
7489 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7490 SelectPostLoadLane(Node, 1, AArch64::LD1i8_POST);
7491 return;
7492 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7493 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7494 SelectPostLoadLane(Node, 1, AArch64::LD1i16_POST);
7495 return;
7496 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7497 VT == MVT::v2f32) {
7498 SelectPostLoadLane(Node, 1, AArch64::LD1i32_POST);
7499 return;
7500 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7501 VT == MVT::v1f64) {
7502 SelectPostLoadLane(Node, 1, AArch64::LD1i64_POST);
7503 return;
7504 }
7505 break;
7506 }
7507 case AArch64ISD::LD2LANEpost: {
7508 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7509 SelectPostLoadLane(Node, 2, AArch64::LD2i8_POST);
7510 return;
7511 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7512 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7513 SelectPostLoadLane(Node, 2, AArch64::LD2i16_POST);
7514 return;
7515 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7516 VT == MVT::v2f32) {
7517 SelectPostLoadLane(Node, 2, AArch64::LD2i32_POST);
7518 return;
7519 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7520 VT == MVT::v1f64) {
7521 SelectPostLoadLane(Node, 2, AArch64::LD2i64_POST);
7522 return;
7523 }
7524 break;
7525 }
7526 case AArch64ISD::LD3LANEpost: {
7527 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7528 SelectPostLoadLane(Node, 3, AArch64::LD3i8_POST);
7529 return;
7530 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7531 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7532 SelectPostLoadLane(Node, 3, AArch64::LD3i16_POST);
7533 return;
7534 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7535 VT == MVT::v2f32) {
7536 SelectPostLoadLane(Node, 3, AArch64::LD3i32_POST);
7537 return;
7538 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7539 VT == MVT::v1f64) {
7540 SelectPostLoadLane(Node, 3, AArch64::LD3i64_POST);
7541 return;
7542 }
7543 break;
7544 }
7545 case AArch64ISD::LD4LANEpost: {
7546 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7547 SelectPostLoadLane(Node, 4, AArch64::LD4i8_POST);
7548 return;
7549 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7550 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7551 SelectPostLoadLane(Node, 4, AArch64::LD4i16_POST);
7552 return;
7553 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7554 VT == MVT::v2f32) {
7555 SelectPostLoadLane(Node, 4, AArch64::LD4i32_POST);
7556 return;
7557 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7558 VT == MVT::v1f64) {
7559 SelectPostLoadLane(Node, 4, AArch64::LD4i64_POST);
7560 return;
7561 }
7562 break;
7563 }
7564 case AArch64ISD::ST2post: {
7565 VT = Node->getOperand(1).getValueType();
7566 if (VT == MVT::v8i8) {
7567 SelectPostStore(Node, 2, AArch64::ST2Twov8b_POST);
7568 return;
7569 } else if (VT == MVT::v16i8) {
7570 SelectPostStore(Node, 2, AArch64::ST2Twov16b_POST);
7571 return;
7572 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7573 SelectPostStore(Node, 2, AArch64::ST2Twov4h_POST);
7574 return;
7575 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7576 SelectPostStore(Node, 2, AArch64::ST2Twov8h_POST);
7577 return;
7578 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7579 SelectPostStore(Node, 2, AArch64::ST2Twov2s_POST);
7580 return;
7581 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7582 SelectPostStore(Node, 2, AArch64::ST2Twov4s_POST);
7583 return;
7584 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7585 SelectPostStore(Node, 2, AArch64::ST2Twov2d_POST);
7586 return;
7587 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7588 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7589 return;
7590 }
7591 break;
7592 }
7593 case AArch64ISD::ST3post: {
7594 VT = Node->getOperand(1).getValueType();
7595 if (VT == MVT::v8i8) {
7596 SelectPostStore(Node, 3, AArch64::ST3Threev8b_POST);
7597 return;
7598 } else if (VT == MVT::v16i8) {
7599 SelectPostStore(Node, 3, AArch64::ST3Threev16b_POST);
7600 return;
7601 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7602 SelectPostStore(Node, 3, AArch64::ST3Threev4h_POST);
7603 return;
7604 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7605 SelectPostStore(Node, 3, AArch64::ST3Threev8h_POST);
7606 return;
7607 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7608 SelectPostStore(Node, 3, AArch64::ST3Threev2s_POST);
7609 return;
7610 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7611 SelectPostStore(Node, 3, AArch64::ST3Threev4s_POST);
7612 return;
7613 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7614 SelectPostStore(Node, 3, AArch64::ST3Threev2d_POST);
7615 return;
7616 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7617 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7618 return;
7619 }
7620 break;
7621 }
7622 case AArch64ISD::ST4post: {
7623 VT = Node->getOperand(1).getValueType();
7624 if (VT == MVT::v8i8) {
7625 SelectPostStore(Node, 4, AArch64::ST4Fourv8b_POST);
7626 return;
7627 } else if (VT == MVT::v16i8) {
7628 SelectPostStore(Node, 4, AArch64::ST4Fourv16b_POST);
7629 return;
7630 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7631 SelectPostStore(Node, 4, AArch64::ST4Fourv4h_POST);
7632 return;
7633 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7634 SelectPostStore(Node, 4, AArch64::ST4Fourv8h_POST);
7635 return;
7636 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7637 SelectPostStore(Node, 4, AArch64::ST4Fourv2s_POST);
7638 return;
7639 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7640 SelectPostStore(Node, 4, AArch64::ST4Fourv4s_POST);
7641 return;
7642 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7643 SelectPostStore(Node, 4, AArch64::ST4Fourv2d_POST);
7644 return;
7645 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7646 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7647 return;
7648 }
7649 break;
7650 }
7651 case AArch64ISD::ST1x2post: {
7652 VT = Node->getOperand(1).getValueType();
7653 if (VT == MVT::v8i8) {
7654 SelectPostStore(Node, 2, AArch64::ST1Twov8b_POST);
7655 return;
7656 } else if (VT == MVT::v16i8) {
7657 SelectPostStore(Node, 2, AArch64::ST1Twov16b_POST);
7658 return;
7659 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7660 SelectPostStore(Node, 2, AArch64::ST1Twov4h_POST);
7661 return;
7662 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7663 SelectPostStore(Node, 2, AArch64::ST1Twov8h_POST);
7664 return;
7665 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7666 SelectPostStore(Node, 2, AArch64::ST1Twov2s_POST);
7667 return;
7668 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7669 SelectPostStore(Node, 2, AArch64::ST1Twov4s_POST);
7670 return;
7671 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7672 SelectPostStore(Node, 2, AArch64::ST1Twov1d_POST);
7673 return;
7674 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7675 SelectPostStore(Node, 2, AArch64::ST1Twov2d_POST);
7676 return;
7677 }
7678 break;
7679 }
7680 case AArch64ISD::ST1x3post: {
7681 VT = Node->getOperand(1).getValueType();
7682 if (VT == MVT::v8i8) {
7683 SelectPostStore(Node, 3, AArch64::ST1Threev8b_POST);
7684 return;
7685 } else if (VT == MVT::v16i8) {
7686 SelectPostStore(Node, 3, AArch64::ST1Threev16b_POST);
7687 return;
7688 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7689 SelectPostStore(Node, 3, AArch64::ST1Threev4h_POST);
7690 return;
7691 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16 ) {
7692 SelectPostStore(Node, 3, AArch64::ST1Threev8h_POST);
7693 return;
7694 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7695 SelectPostStore(Node, 3, AArch64::ST1Threev2s_POST);
7696 return;
7697 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7698 SelectPostStore(Node, 3, AArch64::ST1Threev4s_POST);
7699 return;
7700 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7701 SelectPostStore(Node, 3, AArch64::ST1Threev1d_POST);
7702 return;
7703 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7704 SelectPostStore(Node, 3, AArch64::ST1Threev2d_POST);
7705 return;
7706 }
7707 break;
7708 }
7709 case AArch64ISD::ST1x4post: {
7710 VT = Node->getOperand(1).getValueType();
7711 if (VT == MVT::v8i8) {
7712 SelectPostStore(Node, 4, AArch64::ST1Fourv8b_POST);
7713 return;
7714 } else if (VT == MVT::v16i8) {
7715 SelectPostStore(Node, 4, AArch64::ST1Fourv16b_POST);
7716 return;
7717 } else if (VT == MVT::v4i16 || VT == MVT::v4f16 || VT == MVT::v4bf16) {
7718 SelectPostStore(Node, 4, AArch64::ST1Fourv4h_POST);
7719 return;
7720 } else if (VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v8bf16) {
7721 SelectPostStore(Node, 4, AArch64::ST1Fourv8h_POST);
7722 return;
7723 } else if (VT == MVT::v2i32 || VT == MVT::v2f32) {
7724 SelectPostStore(Node, 4, AArch64::ST1Fourv2s_POST);
7725 return;
7726 } else if (VT == MVT::v4i32 || VT == MVT::v4f32) {
7727 SelectPostStore(Node, 4, AArch64::ST1Fourv4s_POST);
7728 return;
7729 } else if (VT == MVT::v1i64 || VT == MVT::v1f64) {
7730 SelectPostStore(Node, 4, AArch64::ST1Fourv1d_POST);
7731 return;
7732 } else if (VT == MVT::v2i64 || VT == MVT::v2f64) {
7733 SelectPostStore(Node, 4, AArch64::ST1Fourv2d_POST);
7734 return;
7735 }
7736 break;
7737 }
7738 case AArch64ISD::ST2LANEpost: {
7739 VT = Node->getOperand(1).getValueType();
7740 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7741 SelectPostStoreLane(Node, 2, AArch64::ST2i8_POST);
7742 return;
7743 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7744 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7745 SelectPostStoreLane(Node, 2, AArch64::ST2i16_POST);
7746 return;
7747 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7748 VT == MVT::v2f32) {
7749 SelectPostStoreLane(Node, 2, AArch64::ST2i32_POST);
7750 return;
7751 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7752 VT == MVT::v1f64) {
7753 SelectPostStoreLane(Node, 2, AArch64::ST2i64_POST);
7754 return;
7755 }
7756 break;
7757 }
7758 case AArch64ISD::ST3LANEpost: {
7759 VT = Node->getOperand(1).getValueType();
7760 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7761 SelectPostStoreLane(Node, 3, AArch64::ST3i8_POST);
7762 return;
7763 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7764 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7765 SelectPostStoreLane(Node, 3, AArch64::ST3i16_POST);
7766 return;
7767 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7768 VT == MVT::v2f32) {
7769 SelectPostStoreLane(Node, 3, AArch64::ST3i32_POST);
7770 return;
7771 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7772 VT == MVT::v1f64) {
7773 SelectPostStoreLane(Node, 3, AArch64::ST3i64_POST);
7774 return;
7775 }
7776 break;
7777 }
7778 case AArch64ISD::ST4LANEpost: {
7779 VT = Node->getOperand(1).getValueType();
7780 if (VT == MVT::v16i8 || VT == MVT::v8i8) {
7781 SelectPostStoreLane(Node, 4, AArch64::ST4i8_POST);
7782 return;
7783 } else if (VT == MVT::v8i16 || VT == MVT::v4i16 || VT == MVT::v4f16 ||
7784 VT == MVT::v8f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16) {
7785 SelectPostStoreLane(Node, 4, AArch64::ST4i16_POST);
7786 return;
7787 } else if (VT == MVT::v4i32 || VT == MVT::v2i32 || VT == MVT::v4f32 ||
7788 VT == MVT::v2f32) {
7789 SelectPostStoreLane(Node, 4, AArch64::ST4i32_POST);
7790 return;
7791 } else if (VT == MVT::v2i64 || VT == MVT::v1i64 || VT == MVT::v2f64 ||
7792 VT == MVT::v1f64) {
7793 SelectPostStoreLane(Node, 4, AArch64::ST4i64_POST);
7794 return;
7795 }
7796 break;
7797 }
7798 }
7799
7800 // Select the default instruction
7801 SelectCode(Node);
7802}
7803
7804/// createAArch64ISelDag - This pass converts a legalized DAG into a
7805/// AArch64-specific DAG, ready for instruction scheduling.
7807 CodeGenOptLevel OptLevel) {
7808 return new AArch64DAGToDAGISelLegacy(TM, OptLevel);
7809}
7810
7811/// When \p PredVT is a scalable vector predicate in the form
7812/// MVT::nx<M>xi1, it builds the correspondent scalable vector of
7813/// integers MVT::nx<M>xi<bits> s.t. M x bits = 128. When targeting
7814/// structured vectors (NumVec >1), the output data type is
7815/// MVT::nx<M*NumVec>xi<bits> s.t. M x bits = 128. If the input
7816/// PredVT is not in the form MVT::nx<M>xi1, it returns an invalid
7817/// EVT.
7819 unsigned NumVec) {
7820 assert(NumVec > 0 && NumVec < 5 && "Invalid number of vectors.");
7821 if (!PredVT.isScalableVectorOf(MVT::i1))
7822 return EVT();
7823
7824 if (PredVT != MVT::nxv16i1 && PredVT != MVT::nxv8i1 &&
7825 PredVT != MVT::nxv4i1 && PredVT != MVT::nxv2i1)
7826 return EVT();
7827
7828 ElementCount EC = PredVT.getVectorElementCount();
7829 EVT ScalarVT =
7830 EVT::getIntegerVT(Ctx, AArch64::SVEBitsPerBlock / EC.getKnownMinValue());
7831 EVT MemVT = EVT::getVectorVT(Ctx, ScalarVT, EC * NumVec);
7832
7833 return MemVT;
7834}
7835
7836/// Builds an integer vector type large enough to hold \p NumVec instances
7837/// of \p VecVT.
7838static EVT getMultipleVectorType(LLVMContext &Ctx, EVT VecVT, unsigned NumVec) {
7840 VecVT.getVectorElementCount() * NumVec);
7841}
7842
7843/// Return the EVT of the data associated to a memory operation in \p
7844/// Root. If such EVT cannot be retrieved, it returns an invalid EVT.
7846 if (auto *MemIntr = dyn_cast<MemIntrinsicSDNode>(Root))
7847 return MemIntr->getMemoryVT();
7848
7849 if (isa<MemSDNode>(Root)) {
7850 EVT MemVT = cast<MemSDNode>(Root)->getMemoryVT();
7851
7852 EVT DataVT;
7853 if (auto *Load = dyn_cast<LoadSDNode>(Root))
7854 DataVT = Load->getValueType(0);
7855 else if (auto *Load = dyn_cast<MaskedLoadSDNode>(Root))
7856 DataVT = Load->getValueType(0);
7857 else if (auto *Store = dyn_cast<StoreSDNode>(Root))
7858 DataVT = Store->getValue().getValueType();
7859 else if (auto *Store = dyn_cast<MaskedStoreSDNode>(Root))
7860 DataVT = Store->getValue().getValueType();
7861 else
7862 llvm_unreachable("Unexpected MemSDNode!");
7863
7864 return DataVT.changeVectorElementType(Ctx, MemVT.getVectorElementType());
7865 }
7866
7867 const unsigned Opcode = Root->getOpcode();
7868 // For custom ISD nodes, we have to look at them individually to extract the
7869 // type of the data moved to/from memory.
7870 switch (Opcode) {
7871 case AArch64ISD::LD1_MERGE_ZERO:
7872 case AArch64ISD::LD1S_MERGE_ZERO:
7873 case AArch64ISD::LDNF1_MERGE_ZERO:
7874 case AArch64ISD::LDNF1S_MERGE_ZERO:
7875 return cast<VTSDNode>(Root->getOperand(3))->getVT();
7876 case AArch64ISD::ST1_PRED:
7877 return cast<VTSDNode>(Root->getOperand(4))->getVT();
7878 default:
7879 break;
7880 }
7881
7882 if (Opcode != ISD::INTRINSIC_VOID && Opcode != ISD::INTRINSIC_W_CHAIN)
7883 return EVT();
7884
7885 switch (Root->getConstantOperandVal(1)) {
7886 default:
7887 return EVT();
7888 case Intrinsic::aarch64_sme_ldr:
7889 case Intrinsic::aarch64_sme_str:
7890 return MVT::nxv16i8;
7891 case Intrinsic::aarch64_sve_prf:
7892 // We are using an SVE prefetch intrinsic. Type must be inferred from the
7893 // width of the predicate.
7895 Ctx, Root->getOperand(2)->getValueType(0), /*NumVec=*/1);
7896 case Intrinsic::aarch64_sve_ld2_sret:
7897 case Intrinsic::aarch64_sve_ld2q_sret:
7899 Ctx, Root->getOperand(2)->getValueType(0), /*NumVec=*/2);
7900 case Intrinsic::aarch64_sve_st2q:
7902 Ctx, Root->getOperand(4)->getValueType(0), /*NumVec=*/2);
7903 case Intrinsic::aarch64_sve_ld3_sret:
7904 case Intrinsic::aarch64_sve_ld3q_sret:
7906 Ctx, Root->getOperand(2)->getValueType(0), /*NumVec=*/3);
7907 case Intrinsic::aarch64_sve_st3q:
7909 Ctx, Root->getOperand(5)->getValueType(0), /*NumVec=*/3);
7910 case Intrinsic::aarch64_sve_ld4_sret:
7911 case Intrinsic::aarch64_sve_ld4q_sret:
7913 Ctx, Root->getOperand(2)->getValueType(0), /*NumVec=*/4);
7914 case Intrinsic::aarch64_sve_st4q:
7916 Ctx, Root->getOperand(6)->getValueType(0), /*NumVec=*/4);
7917 case Intrinsic::aarch64_sve_ld1_pn_x2:
7918 case Intrinsic::aarch64_sve_ldnt1_pn_x2:
7919 return getMultipleVectorType(Ctx, Root->getValueType(0),
7920 /*NumVec=*/2);
7921 case Intrinsic::aarch64_sve_ld1_pn_x4:
7922 case Intrinsic::aarch64_sve_ldnt1_pn_x4:
7923 return getMultipleVectorType(Ctx, Root->getValueType(0),
7924 /*NumVec=*/4);
7925 case Intrinsic::aarch64_sve_st1_pn_x2:
7926 case Intrinsic::aarch64_sve_stnt1_pn_x2:
7927 return getMultipleVectorType(Ctx, Root->getOperand(2).getValueType(),
7928 /*NumVec=*/2);
7929 case Intrinsic::aarch64_sve_st1_pn_x4:
7930 case Intrinsic::aarch64_sve_stnt1_pn_x4:
7931 return getMultipleVectorType(Ctx, Root->getOperand(2).getValueType(),
7932 /*NumVec=*/4);
7933 case Intrinsic::aarch64_sve_ld1udq:
7934 case Intrinsic::aarch64_sve_st1dq:
7935 return EVT(MVT::nxv1i64);
7936 case Intrinsic::aarch64_sve_ld1uwq:
7937 case Intrinsic::aarch64_sve_st1wq:
7938 return EVT(MVT::nxv1i32);
7939 }
7940}
7941
7942/// SelectAddrModeIndexedSVE - Attempt selection of the addressing mode:
7943/// Base + OffImm * sizeof(MemVT) for Min >= OffImm <= Max
7944/// where Root is the memory access using N for its address.
7945template <int64_t Min, int64_t Max>
7946bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue N,
7947 SDValue &Base,
7948 SDValue &OffImm) {
7949 const EVT MemVT = getMemVTFromNode(*(CurDAG->getContext()), Root);
7950 const DataLayout &DL = CurDAG->getDataLayout();
7951 const MachineFrameInfo &MFI = MF->getFrameInfo();
7952
7953 if (N.getOpcode() == ISD::FrameIndex) {
7954 int FI = cast<FrameIndexSDNode>(N)->getIndex();
7955 // We can only encode VL scaled offsets, so only fold in frame indexes
7956 // referencing SVE objects.
7957 if (MFI.hasScalableStackID(FI)) {
7958 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
7959 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i64);
7960 return true;
7961 }
7962
7963 return false;
7964 }
7965
7966 if (MemVT == EVT())
7967 return false;
7968
7969 if (N.getOpcode() != ISD::ADD)
7970 return false;
7971
7972 SDValue VScale = N.getOperand(1);
7973 int64_t MulImm = std::numeric_limits<int64_t>::max();
7974 if (VScale.getOpcode() == ISD::VSCALE) {
7975 MulImm = cast<ConstantSDNode>(VScale.getOperand(0))->getSExtValue();
7976 } else if (auto C = dyn_cast<ConstantSDNode>(VScale)) {
7977 int64_t ByteOffset = C->getSExtValue();
7978 const auto KnownVScale =
7980
7981 if (!KnownVScale || ByteOffset % KnownVScale != 0)
7982 return false;
7983
7984 MulImm = ByteOffset / KnownVScale;
7985 } else
7986 return false;
7987
7988 TypeSize TS = MemVT.getSizeInBits();
7989 int64_t MemWidthBytes = static_cast<int64_t>(TS.getKnownMinValue()) / 8;
7990
7991 if ((MulImm % MemWidthBytes) != 0)
7992 return false;
7993
7994 int64_t Offset = MulImm / MemWidthBytes;
7996 return false;
7997
7998 Base = N.getOperand(0);
7999 if (Base.getOpcode() == ISD::FrameIndex) {
8000 int FI = cast<FrameIndexSDNode>(Base)->getIndex();
8001 // We can only encode VL scaled offsets, so only fold in frame indexes
8002 // referencing SVE objects.
8003 if (MFI.hasScalableStackID(FI))
8004 Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
8005 }
8006
8007 OffImm = CurDAG->getTargetConstant(Offset, SDLoc(N), MVT::i64);
8008 return true;
8009}
8010
8011/// Select register plus register addressing mode for SVE, with scaled
8012/// offset.
8013bool AArch64DAGToDAGISel::SelectSVERegRegAddrMode(SDValue N, unsigned Scale,
8014 SDValue &Base,
8015 SDValue &Offset) {
8016 if (N.getOpcode() != ISD::ADD)
8017 return false;
8018
8019 // Process an ADD node.
8020 const SDValue LHS = N.getOperand(0);
8021 const SDValue RHS = N.getOperand(1);
8022
8023 // 8 bit data does not come with the SHL node, so it is treated
8024 // separately.
8025 if (Scale == 0) {
8026 Base = LHS;
8027 Offset = RHS;
8028 return true;
8029 }
8030
8031 if (auto C = dyn_cast<ConstantSDNode>(RHS)) {
8032 int64_t ImmOff = C->getSExtValue();
8033 unsigned Size = 1 << Scale;
8034
8035 // To use the reg+reg addressing mode, the immediate must be a multiple of
8036 // the vector element's byte size.
8037 if (ImmOff % Size)
8038 return false;
8039
8040 SDLoc DL(N);
8041 Base = LHS;
8042 Offset = CurDAG->getTargetConstant(ImmOff >> Scale, DL, MVT::i64);
8043 SDValue Ops[] = {Offset};
8044 SDNode *MI = CurDAG->getMachineNode(AArch64::MOVi64imm, DL, MVT::i64, Ops);
8045 Offset = SDValue(MI, 0);
8046 return true;
8047 }
8048
8049 // Check if the RHS is a shift node with a constant.
8050 if (RHS.getOpcode() != ISD::SHL)
8051 return false;
8052
8053 const SDValue ShiftRHS = RHS.getOperand(1);
8054 if (auto *C = dyn_cast<ConstantSDNode>(ShiftRHS))
8055 if (C->getZExtValue() == Scale) {
8056 Base = LHS;
8057 Offset = RHS.getOperand(0);
8058 return true;
8059 }
8060
8061 return false;
8062}
8063
8064bool AArch64DAGToDAGISel::SelectAllActivePredicate(SDValue N) {
8065 const AArch64TargetLowering *TLI =
8066 static_cast<const AArch64TargetLowering *>(getTargetLowering());
8067
8068 return TLI->isAllActivePredicate(*CurDAG, N);
8069}
8070
8071bool AArch64DAGToDAGISel::SelectAnyPredicate(SDValue N) {
8072 return N.getValueType().isScalableVectorOf(MVT::i1);
8073}
8074
8075bool AArch64DAGToDAGISel::SelectSMETileSlice(SDValue N, unsigned MaxSize,
8076 SDValue &Base, SDValue &Offset,
8077 unsigned Scale) {
8078 auto MatchConstantOffset = [&](SDValue CN) -> SDValue {
8079 if (auto *C = dyn_cast<ConstantSDNode>(CN)) {
8080 int64_t ImmOff = C->getSExtValue();
8081 if ((ImmOff > 0 && ImmOff <= MaxSize && (ImmOff % Scale == 0)))
8082 return CurDAG->getTargetConstant(ImmOff / Scale, SDLoc(N), MVT::i64);
8083 }
8084 return SDValue();
8085 };
8086
8087 if (SDValue C = MatchConstantOffset(N)) {
8088 Base = getZeroRegister(*CurDAG, SDLoc(N), MVT::i32);
8089 Offset = C;
8090 return true;
8091 }
8092
8093 // Try to untangle an ADD node into a 'reg + offset'
8094 if (CurDAG->isBaseWithConstantOffset(N)) {
8095 if (SDValue C = MatchConstantOffset(N.getOperand(1))) {
8096 Base = N.getOperand(0);
8097 Offset = C;
8098 return true;
8099 }
8100 }
8101
8102 // By default, just match reg + 0.
8103 Base = N;
8104 Offset = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i64);
8105 return true;
8106}
8107
8108bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *P, SDValue N,
8109 SDValue &Imm) {
8111 static_cast<AArch64CC::CondCode>(P->getConstantOperandVal(1));
8112 if (auto *CN = dyn_cast<ConstantSDNode>(N)) {
8113 // Check conservatively if the immediate fits the valid range [0, 64).
8114 // Immediate variants for GE and HS definitely need to be decremented
8115 // when lowering the pseudos later, so an immediate of 1 would become 0.
8116 // For the inverse conditions LT and LO we don't know for sure if they
8117 // will need a decrement but should the decision be made to reverse the
8118 // branch condition, we again end up with the need to decrement.
8119 // The same argument holds for LE, LS, GT and HI and possibly
8120 // incremented immediates. This can lead to slightly less optimal
8121 // codegen, e.g. we never codegen the legal case
8122 // cblt w0, #63, A
8123 // because we could end up with the illegal case
8124 // cbge w0, #64, B
8125 // should the decision to reverse the branch direction be made. For the
8126 // lower bound cases this is no problem since we can express comparisons
8127 // against 0 with either tbz/tnbz or using wzr/xzr.
8128 uint64_t LowerBound = 0, UpperBound = 64;
8129 switch (CC) {
8130 case AArch64CC::GE:
8131 case AArch64CC::HS:
8132 case AArch64CC::LT:
8133 case AArch64CC::LO:
8134 LowerBound = 1;
8135 break;
8136 case AArch64CC::LE:
8137 case AArch64CC::LS:
8138 case AArch64CC::GT:
8139 case AArch64CC::HI:
8140 UpperBound = 63;
8141 break;
8142 default:
8143 break;
8144 }
8145
8146 if (CN->getAPIntValue().uge(LowerBound) &&
8147 CN->getAPIntValue().ult(UpperBound)) {
8148 SDLoc DL(N);
8149 Imm = CurDAG->getTargetConstant(CN->getZExtValue(), DL, N.getValueType());
8150 return true;
8151 }
8152 }
8153
8154 return false;
8155}
8156
8157template <bool MatchCBB>
8158bool AArch64DAGToDAGISel::SelectCmpBranchExtOperand(SDValue N, SDValue &Reg,
8159 SDValue &ExtType) {
8160
8161 // Use an invalid shift-extend value to indicate we don't need to extend later
8162 if (N.getOpcode() == ISD::AssertZext || N.getOpcode() == ISD::AssertSext) {
8163 EVT Ty = cast<VTSDNode>(N.getOperand(1))->getVT();
8164 if (Ty != (MatchCBB ? MVT::i8 : MVT::i16))
8165 return false;
8166 Reg = N.getOperand(0);
8167 ExtType = CurDAG->getSignedTargetConstant(AArch64_AM::InvalidShiftExtend,
8168 SDLoc(N), MVT::i32);
8169 return true;
8170 }
8171
8173
8174 if ((MatchCBB && (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB)) ||
8175 (!MatchCBB && (ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH))) {
8176 Reg = N.getOperand(0);
8177 ExtType =
8178 CurDAG->getTargetConstant(getExtendEncoding(ET), SDLoc(N), MVT::i32);
8179 return true;
8180 }
8181
8182 return false;
8183}
8184
8185/// Try to fold AArch64 CSEL/FCMP patterns to FMAXNM/FMINNM.
8186///
8187/// This is intentionally done in PreprocessISelDAG rather than DAGCombine:
8188/// doing this earlier based on the defining operation of X can be invalidated
8189/// by later DAG combines. At this point the DAG is being prepared for
8190/// instruction selection, so the use of isKnownNeverSNaN(X) applies to the
8191/// final SDValue being selected.
8192/// Only handles FCMP(X, C) with scalar FP types, where C is a non-NaN constant.
8193/// The nsz requirement is needed only when C is zero, to avoid signed-zero
8194/// mismatches. The never-sNaN check is required because AArch64 FMAXNM/FMINNM
8195/// differ from fcmp+fcsel for signaling NaN inputs.
8196bool AArch64DAGToDAGISel::tryFoldCselToFMaxMin(SDNode *N) {
8197 EVT VT = N->getValueType(0);
8198
8199 // Scalar FP only.
8200 if (!VT.isFloatingPoint() || VT.isVector())
8201 return false;
8202
8203 SDValue TVal = N->getOperand(0);
8204 SDValue FVal = N->getOperand(1);
8205 SDValue CCVal = N->getOperand(2);
8206 SDValue Cmp = N->getOperand(3);
8207
8208 if (Cmp.getOpcode() != AArch64ISD::FCMP)
8209 return false;
8210
8211 auto *CC = dyn_cast<ConstantSDNode>(CCVal);
8212 if (!CC)
8213 return false;
8214
8215 SDValue CmpLHS = Cmp.getOperand(0);
8216 SDValue CmpRHS = Cmp.getOperand(1);
8217 unsigned CondCode = CC->getZExtValue();
8218
8219 // Map VT and operation (max/min) to machine opcode.
8220 auto getOpc = [](EVT VT, bool isMax) -> unsigned {
8221 if (VT == MVT::f16)
8222 return isMax ? AArch64::FMAXNMHrr : AArch64::FMINNMHrr;
8223 else if (VT == MVT::f32)
8224 return isMax ? AArch64::FMAXNMSrr : AArch64::FMINNMSrr;
8225 else if (VT == MVT::f64)
8226 return isMax ? AArch64::FMAXNMDrr : AArch64::FMINNMDrr;
8227 else
8228 return 0; // unsupported
8229 };
8230
8231 // Determine whether to use max or min based on condition code and operands.
8232 bool isMax;
8233 if (CondCode == AArch64CC::GT || CondCode == AArch64CC::GE) {
8234 if (TVal == CmpLHS && FVal == CmpRHS)
8235 isMax = true;
8236 else
8237 return false;
8238 } else if (CondCode == AArch64CC::MI || CondCode == AArch64CC::LS) {
8239 if (TVal == CmpLHS && FVal == CmpRHS)
8240 isMax = false;
8241 else
8242 return false;
8243 } else {
8244 return false;
8245 }
8246
8247 // Get the machine opcode for this VT and operation.
8248 unsigned Opc = getOpc(VT, isMax);
8249 if (!Opc)
8250 return false;
8251
8252 // Constant must be non-NaN.
8253 auto *CFP = dyn_cast<ConstantFPSDNode>(CmpRHS);
8254 if (!CFP || CFP->getValueAPF().isNaN())
8255 return false;
8256
8257 // nsz flag required only when constant is zero: fmaxnm(+0,-0)=+0 differs from
8258 // fcmp+select's -0. For non-zero constants, semantics are identical.
8259 if (CFP->isZero() && !N->getFlags().hasNoSignedZeros())
8260 return false;
8261
8262 // Only fold if variable operand is never sNaN.
8263 // This runs after DAG combines, so later combines cannot remove a defining
8264 // operation used by isKnownNeverSNaN().
8265 if (!CurDAG->isKnownNeverSNaN(CmpLHS))
8266 return false;
8267
8268 CurDAG->SelectNodeTo(N, Opc, VT, CmpLHS, CmpRHS);
8269 return true;
8270}
8271
8272void AArch64DAGToDAGISel::PreprocessISelDAG() {
8273 bool MadeChange = false;
8274 for (SDNode &N : llvm::make_early_inc_range(CurDAG->allnodes())) {
8275 if (N.use_empty())
8276 continue;
8277
8278 SDValue Result;
8279 switch (N.getOpcode()) {
8280 case ISD::SCALAR_TO_VECTOR: {
8281 EVT ScalarTy = N.getValueType(0).getVectorElementType();
8282 if ((ScalarTy == MVT::i32 || ScalarTy == MVT::i64) &&
8283 ScalarTy == N.getOperand(0).getValueType())
8284 Result = addBitcastHints(*CurDAG, N);
8285
8286 break;
8287 }
8288 case AArch64ISD::VSHL: {
8289 // Undo mul(shl(A,C),B) -> shl(mul(A,B),C) canonicalisation when A is an
8290 // extend that can be folded into the shift.
8291 EVT VT = N.getValueType(0);
8292 SDValue A, B, C = N.getOperand(1);
8293 if (sd_match(N.getOperand(0),
8295 m_SExt(m_Value()))),
8296 m_Value(B))))) {
8297 // If both mul operands are extended, preserve the smull/umull idiom.
8298 if (B.getOpcode() == A.getOpcode())
8299 break;
8300 SDLoc DL(&N);
8301 SDValue SHL = CurDAG->getNode(AArch64ISD::VSHL, DL, VT, A, C);
8302 Result = CurDAG->getNode(ISD::MUL, DL, VT, SHL, B);
8303 }
8304 break;
8305 }
8306 default:
8307 break;
8308 }
8309
8310 if (Result) {
8311 LLVM_DEBUG(dbgs() << "AArch64 DAG preprocessing replacing:\nOld: ");
8312 LLVM_DEBUG(N.dump(CurDAG));
8313 LLVM_DEBUG(dbgs() << "\nNew: ");
8314 LLVM_DEBUG(Result.dump(CurDAG));
8315 LLVM_DEBUG(dbgs() << "\n");
8316
8317 CurDAG->ReplaceAllUsesOfValueWith(SDValue(&N, 0), Result);
8318 MadeChange = true;
8319 }
8320 }
8321
8322 if (MadeChange)
8323 CurDAG->RemoveDeadNodes();
8324
8326}
static std::optional< APInt > GetNEONSplatValue(SDValue N, const AArch64Subtarget *Subtarget)
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms)
static int getIntOperandFromRegisterString(StringRef RegString)
static SDValue NarrowVector(SDValue V128Reg, SelectionDAG &DAG)
NarrowVector - Given a value in the V128 register class, produce the equivalent value in the V64 regi...
static bool isBitfieldDstMask(uint64_t DstMask, const APInt &BitsToBeInserted, unsigned NumberOfIgnoredHighBits, EVT VT)
Does DstMask form a complementary pair with the mask provided by BitsToBeInserted,...
static SDValue narrowIfNeeded(SelectionDAG *CurDAG, SDValue N)
Instructions that accept extend modifiers like UXTW expect the register being extended to be a GPR32,...
static bool isSeveralBitsPositioningOpFromShl(const uint64_t ShlImm, SDValue Op, SDValue &Src, int &DstLSB, int &Width)
static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, SDValue &Src, int &DstLSB, int &Width)
Does this tree qualify as an attempt to move a bitfield into position, essentially "(and (shl VAL,...
static bool allUsesAreShiftAmounts(SDValue N)
static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc, uint64_t &Imm)
static bool tryBitfieldInsertOpFromOrAndImm(SDNode *N, SelectionDAG *CurDAG)
static std::tuple< SDValue, SDValue > extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG)
static SDValue addBitcastHints(SelectionDAG &DAG, SDNode &N)
addBitcastHints - This method adds bitcast hints to the operands of a node to help instruction select...
static void getUsefulBitsFromOrWithShiftedReg(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromAnd(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB, unsigned NumberOfIgnoredLowBits, bool BiggerPattern)
static bool isBitfieldExtractOp(SelectionDAG *CurDAG, SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, unsigned NumberOfIgnoredLowBits=0, bool BiggerPattern=false)
static bool isShiftedMask(uint64_t Mask, EVT VT)
bool SelectSMETile(unsigned &BaseReg, unsigned TileNum)
static EVT getMemVTFromNode(LLVMContext &Ctx, SDNode *Root)
Return the EVT of the data associated to a memory operation in Root.
static bool checkCVTFixedPointOperandWithFBits(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static bool isWorthFoldingADDlow(SDValue N)
If there's a use of this ADDlow that's not itself a load/store then we'll need to create a real ADD i...
static AArch64_AM::ShiftExtendType getShiftTypeForNode(SDValue N)
getShiftTypeForNode - Translate a shift node to the corresponding ShiftType value.
static bool isSeveralBitsExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &LSB, unsigned &MSB)
static unsigned SelectOpcodeFromVT(EVT VT, ArrayRef< unsigned > Opcodes)
This function selects an opcode from a list of opcodes, which is expected to be the opcode for { 8-bi...
static EVT getPackedVectorTypeFromPredicateType(LLVMContext &Ctx, EVT PredVT, unsigned NumVec)
When PredVT is a scalable vector predicate in the form MVT::nx<M>xi1, it builds the correspondent sca...
static bool checkCVTFixedPointOperandWithFBitsForVectors(SelectionDAG *CurDAG, SDValue N, SDValue &FixedPos, unsigned RegWidth, bool isReciprocal)
static SDValue getZeroRegister(SelectionDAG &DAG, SDLoc DL, EVT VT)
Returns a copy from WZR or XZR.
static bool isPreferredADD(int64_t ImmOff)
static void getUsefulBitsFromBitfieldMoveOpd(SDValue Op, APInt &UsefulBits, uint64_t Imm, uint64_t MSB, unsigned Depth)
static SDValue getLeftShift(SelectionDAG *CurDAG, SDValue Op, int ShlAmount)
Create a machine node performing a notional SHL of Op by ShlAmount.
static bool isWorthFoldingSHL(SDValue V)
Determine whether it is worth it to fold SHL into the addressing mode.
static bool isBitfieldPositioningOpFromAnd(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static void getUsefulBitsFromBFM(SDValue Op, SDValue Orig, APInt &UsefulBits, unsigned Depth)
static bool isBitfieldExtractOpFromShr(SDNode *N, unsigned &Opc, SDValue &Opd0, unsigned &Immr, unsigned &Imms, bool BiggerPattern)
static bool tryOrrWithShift(SDNode *N, SDValue OrOpd0, SDValue OrOpd1, SDValue Src, SDValue Dst, SelectionDAG *CurDAG, const bool BiggerPattern)
static void getUsefulBitsForUse(SDNode *UserNode, APInt &UsefulBits, SDValue Orig, unsigned Depth)
static bool isMemOpOrPrefetch(SDNode *N)
static void getUsefulBitsFromUBFM(SDValue Op, APInt &UsefulBits, unsigned Depth)
static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits, SelectionDAG *CurDAG)
static APInt DecodeFMOVImm(uint64_t Imm, unsigned RegWidth)
static void getUsefulBitsFromAndWithImmediate(SDValue Op, APInt &UsefulBits, unsigned Depth)
static std::optional< APInt > DecodeNEONSplat(SDValue N, const AArch64Subtarget *Subtarget)
static void getUsefulBits(SDValue Op, APInt &UsefulBits, unsigned Depth=0)
static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected)
static EVT getMultipleVectorType(LLVMContext &Ctx, EVT VecVT, unsigned NumVec)
Builds an integer vector type large enough to hold NumVec instances of VecVT.
static AArch64_AM::ShiftExtendType getExtendTypeForNode(SDValue N, bool IsLoadStore=false)
getExtendTypeForNode - Translate an extend node to the corresponding ExtendType value.
static bool isIntImmediate(const SDNode *N, uint64_t &Imm)
isIntImmediate - This method tests to see if the node is a constant operand.
static bool isWorthFoldingIntoOrrWithShift(SDValue Dst, SelectionDAG *CurDAG, SDValue &ShiftedOperand, uint64_t &EncodedShiftImm)
static bool isValidAsScaledImmediate(int64_t Offset, unsigned Range, unsigned Size)
Check if the immediate offset is valid as a scaled immediate.
static bool isBitfieldPositioningOpFromShl(SelectionDAG *CurDAG, SDValue Op, bool BiggerPattern, const uint64_t NonZeroBits, SDValue &Src, int &DstLSB, int &Width)
static SDValue WidenVector(SDValue V64Reg, SelectionDAG &DAG)
WidenVector - Given a value in the V64 register class, produce the equivalent value in the V128 regis...
static Register createDTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of D-registers using the registers in Regs.
static Register createQTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of Q-registers using the registers in Regs.
static Register createTuple(ArrayRef< Register > Regs, const unsigned RegClassIDs[], const unsigned SubRegs[], MachineIRBuilder &MIB)
Create a REG_SEQUENCE instruction using the registers in Regs.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
uint64_t uint64_t
uint64_t Imm
AMDGPU Register Bank Select
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
dxil translate DXIL Translate Metadata
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
#define R2(n)
Promote Memory to Register
Definition Mem2Reg.cpp:110
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t High
OptimizedStructLayoutField Field
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
RISCVCC::CondCode CC
MachineInstr *& Lo
Contains matchers for matching SelectionDAG nodes and values.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define PASS_NAME
Value * RHS
Value * LHS
AArch64DAGToDAGISelPass(AArch64TargetMachine &TM)
const AArch64InstrInfo * getInstrInfo() const override
const AArch64TargetLowering * getTargetLowering() const override
bool isStreaming() const
Returns true if the function has a streaming body.
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
unsigned getSVEVectorSizeInBits() const
bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N) const
Register matchRegisterName(StringRef RegName) const
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static const fltSemantics & IEEEdouble()
Definition APFloat.h:305
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
unsigned popcount() const
Count the number of bits set.
Definition APInt.h:1690
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
Definition APInt.cpp:1078
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:970
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
Definition APInt.h:254
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1659
unsigned countl_zero() const
The APInt version of std::countl_zero.
Definition APInt.h:1618
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
Definition APInt.cpp:648
void flipAllBits()
Toggle every bit to its opposite value.
Definition APInt.h:1472
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
Definition APInt.h:506
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
Definition APInt.h:860
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
Definition APInt.h:853
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
iterator begin() const
Definition ArrayRef.h:129
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
const GlobalValue * getGlobal() const
const TargetRegisterClass * getInlineAsmMemoryOperandRegClass(InlineAsm::ConstraintCode C) const override
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
This class is used to represent ISD::LOAD nodes.
unsigned getID() const
getID() - Return the register class ID number.
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1437
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1443
bool equalsStr(StringRef Str) const
Definition Metadata.h:924
Metadata * get() const
Definition Metadata.h:931
Machine Value Type.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static MVT getVectorVT(MVT VT, unsigned NumElements)
bool hasScalableStackID(int ObjectIdx) const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
A description of a memory reference used in the backend.
const MDNode * getMemCacheHint() const
Return the cache hint metadata for the memory reference.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDNode * SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT)
These are used for target selectors to mutate the specified node to have the specified return type,...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
LLVM Value Representation.
Definition Value.h:75
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:441
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:986
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint32_t parseGenericRegister(StringRef Name)
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static uint64_t decodeAdvSIMDModImmType12(uint8_t Imm)
constexpr bool isLegalArithImmed(const uint64_t C)
isLegalArithImmed -
static uint64_t decodeAdvSIMDModImmType11(uint8_t Imm)
unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET)
Mapping from extend bits to required operation: shifter: 000 ==> uxtb 001 ==> uxth 010 ==> uxtw 011 =...
static uint64_t decodeAdvSIMDModImmType10(uint8_t Imm)
static bool isSVELogicalImm(unsigned SizeInBits, uint64_t ImmVal, uint64_t &Encoding)
constexpr unsigned getArithImmedShift(const uint64_t C)
getArithImmedShift - assumes C is a legal immediate for arithmetic instructions and
static bool isSVECpyDupImm(int SizeInBits, int64_t Val, int32_t &Imm, int32_t &Shift)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
static bool isSignExtendShiftType(AArch64_AM::ShiftExtendType Type)
isSignExtendShiftType - Returns true if Type is sign extending.
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
static constexpr unsigned SVEBitsPerBlock
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:238
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:605
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:879
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:222
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:675
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:235
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:682
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
Definition ISDOpcodes.h:71
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition ISDOpcodes.h:232
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:619
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
Definition ISDOpcodes.h:141
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:581
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:914
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:207
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
Definition ISDOpcodes.h:243
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:64
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:215
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
BinaryOpc_match< LHS, RHS, true > m_Mul(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_SExt(const Opnd &Op)
bool sd_match(SDValue N, Pattern &&P)
UnaryOpc_match< Opnd > m_ZExt(const Opnd &Op)
Value_match m_Value()
Match any valid SDValue.
NUses_match< 1, Value_match > m_OneUse()
Not(const Pred &P) -> Not< Pred >
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:577
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
unsigned CheckFixedPointOperandConstant(APFloat &FVal, unsigned RegWidth, bool isReciprocal)
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition bit.h:315
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
Definition MathExtras.h:268
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
Definition MathExtras.h:274
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
Definition STLExtras.h:2042
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition MathExtras.h:262
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:280
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createAArch64ISelDag(AArch64TargetMachine &TM, CodeGenOptLevel OptLevel)
createAArch64ISelDag - This pass converts a legalized DAG into a AArch64-specific DAG,...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
AArch64MemoryHint toAArch64MemoryHint(Int I)
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Extended Value Type.
Definition ValueTypes.h:35
bool isScalableVectorOf(EVT EltVT) const
Return true if this is a scalable vector with matching element type.
Definition ValueTypes.h:192
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:418
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:129
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:494
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:382
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition ValueTypes.h:98
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
bool is128BitVector() const
Return true if this is a 128-bit vector type.
Definition ValueTypes.h:230
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:404
bool isFixedLengthVector() const
Definition ValueTypes.h:199
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:187
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
bool is64BitVector() const
Return true if this is a 64-bit vector type.
Definition ValueTypes.h:225
Matching combinators.