29#include "llvm/IR/IntrinsicsAArch64.h"
32#include <initializer_list>
34#define DEBUG_TYPE "aarch64-legalinfo"
68 std::initializer_list<LLT> PackedVectorAllTypeList = {
74 std::initializer_list<LLT> ScalarAndPtrTypesList = {s8, s16, s32, s64, p0};
78 const TargetMachine &TM = ST.getTargetLowering()->getTargetMachine();
81 if (!ST.hasNEON() || !ST.hasFPARMv8()) {
88 const bool HasFP16 = ST.hasFullFP16();
89 const LLT &MinFPScalar = HasFP16 ? s16 : s32;
91 const bool HasCSSC = ST.hasCSSC();
92 const bool HasRCPC3 = ST.hasRCPC3();
93 const bool HasSVE = ST.hasSVE();
96 {G_IMPLICIT_DEF, G_FREEZE, G_CONSTANT_FOLD_BARRIER})
97 .legalFor({p0, s8, s16, s32, s64})
98 .legalFor({v2s8, v4s8, v8s8, v16s8, v2s16, v4s16, v8s16, v2s32, v4s32,
100 .widenScalarToNextPow2(0)
113 .legalFor(PackedVectorAllTypeList)
127 .widenScalarToNextPow2(0)
132 .maxScalarIf(
typeInSet(0, {s64, p0}), 1, s32);
137 .widenScalarToNextPow2(1)
142 .maxScalarIf(
typeInSet(1, {s64, p0}), 0, s32)
143 .maxScalarIf(
typeInSet(1, {s128}), 0, s64);
146 .legalFor({s32, s64, v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64})
147 .legalFor(HasSVE, {nxv16s8, nxv8s16, nxv4s32, nxv2s64})
148 .widenScalarToNextPow2(0)
156 return Query.
Types[0].getNumElements() <= 2;
161 return Query.
Types[0].getNumElements() <= 4;
166 return Query.
Types[0].getNumElements() <= 16;
173 .
legalFor({s32, s64, v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64})
174 .widenScalarToNextPow2(0)
182 return Query.
Types[0].getNumElements() <= 2;
187 return Query.
Types[0].getNumElements() <= 4;
192 return Query.
Types[0].getNumElements() <= 16;
200 const auto &SrcTy = Query.
Types[0];
201 const auto &AmtTy = Query.
Types[1];
202 return !SrcTy.isVector() && SrcTy.getSizeInBits() == 32 &&
203 AmtTy.getSizeInBits() == 32;
217 .widenScalarToNextPow2(0)
231 .
legalFor({{p0, s64}, {v2p0, v2s64}})
232 .clampScalarOrElt(1, s64, s64)
238 .legalFor({s32, s64})
240 .clampScalar(0, s32, s64)
245 .lowerFor({s8, s16, s32, s64, v2s32, v4s32, v2s64})
254 .widenScalarToNextPow2(0, 32)
259 .legalFor({s64, v16s8, v8s16, v4s32})
263 .legalFor({v8s8, v16s8, v4s16, v8s16, v2s32, v4s32})
264 .legalFor(HasCSSC, {s32, s64})
265 .minScalar(HasCSSC, 0, s32)
274 .legalFor(PackedVectorAllTypeList)
278 return SrcTy.isScalar() && SrcTy.getSizeInBits() < 128;
282 [=](
const LegalityQuery &Query) {
return std::make_pair(0, v4s16); })
285 [=](
const LegalityQuery &Query) {
return std::make_pair(0, v2s32); })
286 .clampNumElements(0, v8s8, v16s8)
294 {G_ABDS, G_ABDU, G_UAVGFLOOR, G_UAVGCEIL, G_SAVGFLOOR, G_SAVGCEIL})
295 .legalFor({v8s8, v16s8, v4s16, v8s16, v2s32, v4s32})
299 {G_SADDE, G_SSUBE, G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_UADDO, G_USUBO})
300 .legalFor({{s32, s32}, {s64, s32}})
301 .clampScalar(0, s32, s64)
306 .customFor({{s32, s32}, {s32, s64}, {s64, s64}})
312 return Q.
Types[0].isScalar() && Q.
Types[1].getScalarSizeInBits() < 64;
318 .customFor({{s32, s32}, {s64, s64}});
322 .
legalFor(HasCSSC, {{s32, s32}, {s64, s64}})
323 .legalFor({{v8s8, v8s8}, {v16s8, v16s8}})
324 .customFor(!HasCSSC, {{s32, s32}, {s64, s64}})
325 .customFor({{s128, s128},
331 .clampScalar(0, s32, s128)
343 .legalFor({{s32, s32},
351 .widenScalarToNextPow2(1, 32)
368 .customFor(!HasCSSC, {s32, s64});
374 .widenScalarToNextPow2(0, 32)
386 .
legalFor({s32, s64, v4s16, v8s16, v2s32, v4s32, v2s64})
395 .legalFor({v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64})
396 .legalFor(HasSVE, {nxv16s8, nxv8s16, nxv4s32, nxv2s64})
397 .clampNumElements(0, v8s8, v16s8)
406 {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMA, G_FSQRT, G_FMAXNUM, G_FMINNUM,
407 G_FMAXIMUM, G_FMINIMUM, G_FCEIL, G_FFLOOR, G_FRINT, G_FNEARBYINT,
408 G_INTRINSIC_TRUNC, G_INTRINSIC_ROUND, G_INTRINSIC_ROUNDEVEN})
409 .legalFor({s32, s64, v2s32, v4s32, v2s64})
410 .legalFor(HasFP16, {s16, v4s16, v8s16})
420 .legalFor({s32, s64, v2s32, v4s32, v2s64})
421 .legalFor(HasFP16, {s16, v4s16, v8s16})
436 G_FLOG10, G_FTAN, G_FEXP, G_FEXP2, G_FEXP10,
437 G_FACOS, G_FASIN, G_FATAN, G_FATAN2, G_FCOSH,
438 G_FSINH, G_FTANH, G_FMODF})
447 .
libcallFor({{s32, s32}, {s64, s32}, {s128, s32}});
450 .legalFor({{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}})
451 .legalFor(HasFP16, {{s32, s16}, {s64, s16}})
456 .legalFor({{s64, s32}, {s64, s64}})
457 .legalFor(HasFP16, {{s64, s16}})
475 for (
unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {
478 if (
Op == G_SEXTLOAD)
483 .legalForTypesWithMemDesc({{s32, p0, s8, 8},
491 {v2s32, p0, s64, 8}})
492 .widenScalarToNextPow2(0)
493 .clampScalar(0, s32, s64)
496 .unsupportedIfMemSizeNotPow2()
503 return ValTy.isPointerVector() && ValTy.getAddressSpace() == 0;
508 return HasRCPC3 && Query.
Types[0] == s128 &&
512 return Query.
Types[0] == s128 &&
515 .legalForTypesWithMemDesc({{s8, p0, s8, 8},
522 {v16s8, p0, s128, 8},
524 {v8s16, p0, s128, 8},
526 {v4s32, p0, s128, 8},
527 {v2s64, p0, s128, 8}})
529 .legalForTypesWithMemDesc(
530 {{s32, p0, s8, 8}, {s32, p0, s16, 8}, {s64, p0, s32, 8}})
531 .legalForTypesWithMemDesc({
533 {nxv16s8, p0, nxv16s8, 8},
534 {nxv8s16, p0, nxv8s16, 8},
535 {nxv4s32, p0, nxv4s32, 8},
536 {nxv2s64, p0, nxv2s64, 8},
538 .widenScalarToNextPow2(0, 8)
549 return Query.
Types[0].isScalar() &&
551 Query.
Types[0].getSizeInBits() > 32;
560 .customIf(IsPtrVecPred)
566 return HasRCPC3 && Query.
Types[0] == s128 &&
570 return Query.
Types[0] == s128 &&
578 {{s8, p0, s8, 8}, {s16, p0, s8, 8},
581 {s16, p0, s16, 8}, {s32, p0, s16, 8},
583 {s32, p0, s8, 8}, {s32, p0, s16, 8}, {s32, p0, s32, 8},
584 {s64, p0, s64, 8}, {s64, p0, s32, 8},
585 {p0, p0, s64, 8}, {s128, p0, s128, 8}, {v16s8, p0, s128, 8},
586 {v8s8, p0, s64, 8}, {v4s16, p0, s64, 8}, {v8s16, p0, s128, 8},
587 {v2s32, p0, s64, 8}, {v4s32, p0, s128, 8}, {v2s64, p0, s128, 8}})
588 .legalForTypesWithMemDesc({
593 {nxv16s8, p0, nxv16s8, 8},
594 {nxv8s16, p0, nxv8s16, 8},
595 {nxv4s32, p0, nxv4s32, 8},
596 {nxv2s64, p0, nxv2s64, 8},
598 .clampScalar(0, s8, s64)
601 return Query.
Types[0].isScalar() &&
605 .clampMaxNumElements(0, s8, 16)
614 return Query.
Types[0].getSizeInBits() ==
615 Query.
MMODescrs[0].MemoryTy.getSizeInBits();
621 .customIf(IsPtrVecPred)
639 {p0, v16s8, v16s8, 8},
640 {p0, v4s16, v4s16, 8},
641 {p0, v8s16, v8s16, 8},
642 {p0, v2s32, v2s32, 8},
643 {p0, v4s32, v4s32, 8},
644 {p0, v2s64, v2s64, 8},
650 auto IndexedLoadBasicPred = [=](
const LegalityQuery &Query) {
678 return MemTy == s8 || MemTy == s16;
680 return MemTy == s8 || MemTy == s16 || MemTy == s32;
688 .widenScalarToNextPow2(0)
693 .clampScalar(0, MinFPScalar, s128);
697 .
legalFor({{s32, s32}, {s32, s64}, {s32, p0}})
706 return Ty.isVector() && !SrcTy.isPointerVector() &&
707 Ty.getElementType() != SrcTy.getElementType();
715 return Query.
Types[1].isPointerVector();
732 .legalFor(HasFP16, {{s32, s16}, {v4s16, v4s16}, {v8s16, v8s16}})
741 return Ty.isVector() && !SrcTy.isPointerVector() &&
742 Ty.getElementType() != SrcTy.getElementType();
745 .clampNumElements(1, v4s16, v8s16)
753 unsigned DstSize = Query.
Types[0].getSizeInBits();
756 if (Query.
Types[0].isVector())
759 if (DstSize < 8 || DstSize >= 128 || !
isPowerOf2_32(DstSize))
767 unsigned SrcSize = SrcTy.getSizeInBits();
774 .legalIf(ExtLegalFunc)
775 .
legalFor({{v8s16, v8s8}, {v4s32, v4s16}, {v2s64, v2s32}})
776 .clampScalar(0, s64, s64)
783 return (Query.
Types[0].getScalarSizeInBits() >
784 Query.
Types[1].getScalarSizeInBits() * 2) &&
785 Query.
Types[0].isVector() &&
786 (Query.
Types[1].getScalarSizeInBits() == 8 ||
787 Query.
Types[1].getScalarSizeInBits() == 16);
789 .clampMinNumElements(1, s8, 8)
794 .
legalFor({{v8s8, v8s16}, {v4s16, v4s32}, {v2s32, v2s64}})
805 return DstTy.
isVector() && SrcTy.getSizeInBits() > 128 &&
808 .clampMinNumElements(0, s8, 8)
813 .legalFor({{v8s8, v8s16}, {v4s16, v4s32}, {v2s32, v2s64}})
814 .clampNumElements(0, v2s32, v2s32);
818 .legalFor(PackedVectorAllTypeList)
829 {{s16, s32}, {s16, s64}, {s32, s64}, {v4s16, v4s32}, {v2s32, v2s64}})
830 .libcallFor({{s16, s128}, {s32, s128}, {s64, s128}})
836 SrcTy.getScalarSizeInBits() == 64 &&
840 .clampNumElements(1, v4s32, v4s32)
846 {{s32, s16}, {s64, s16}, {s64, s32}, {v4s32, v4s16}, {v2s64, v2s32}})
847 .libcallFor({{s128, s64}, {s128, s32}, {s128, s16}})
853 return SrcTy.isVector() && DstTy.
isVector() &&
854 SrcTy.getScalarSizeInBits() == 16 &&
858 .clampNumElements(0, v4s32, v4s32)
864 .legalFor({{s32, s32},
872 {{s32, s16}, {s64, s16}, {v4s16, v4s16}, {v8s16, v8s16}})
879 return Query.
Types[1] == s16 && Query.
Types[0].getSizeInBits() > 64;
888 return Query.
Types[0].getScalarSizeInBits() <= 64 &&
889 Query.
Types[0].getScalarSizeInBits() >
890 Query.
Types[1].getScalarSizeInBits();
895 return Query.
Types[1].getScalarSizeInBits() <= 64 &&
896 Query.
Types[0].getScalarSizeInBits() <
897 Query.
Types[1].getScalarSizeInBits();
900 .clampNumElements(0, v4s16, v8s16)
904 {{s32, s128}, {s64, s128}, {s128, s128}, {s128, s32}, {s128, s64}});
907 .legalFor({{s32, s32},
916 {{s16, s16}, {s32, s16}, {s64, s16}, {v4s16, v4s16}, {v8s16, v8s16}})
924 return Query.
Types[1] == s16 && Query.
Types[0].getSizeInBits() > 64;
934 unsigned ITySize = Query.
Types[0].getScalarSizeInBits();
935 return (ITySize == 16 || ITySize == 32 || ITySize == 64) &&
936 ITySize > Query.
Types[1].getScalarSizeInBits();
941 unsigned FTySize = Query.
Types[1].getScalarSizeInBits();
942 return (FTySize == 16 || FTySize == 32 || FTySize == 64) &&
943 Query.
Types[0].getScalarSizeInBits() < FTySize;
952 .legalFor({{s32, s32},
960 {{s16, s32}, {s16, s64}, {v4s16, v4s16}, {v8s16, v8s16}})
967 return Query.
Types[1].isVector() &&
968 Query.
Types[1].getScalarSizeInBits() == 64 &&
969 Query.
Types[0].getScalarSizeInBits() == 16;
971 .widenScalarOrEltToNextPow2OrMinSize(0, HasFP16 ? 16 : 32)
975 return Query.
Types[0].getScalarSizeInBits() == 32 &&
976 Query.
Types[1].getScalarSizeInBits() == 64;
981 return Query.
Types[1].getScalarSizeInBits() <= 64 &&
982 Query.
Types[0].getScalarSizeInBits() <
983 Query.
Types[1].getScalarSizeInBits();
988 return Query.
Types[0].getScalarSizeInBits() <= 64 &&
989 Query.
Types[0].getScalarSizeInBits() >
990 Query.
Types[1].getScalarSizeInBits();
993 .clampNumElements(0, v4s16, v8s16)
1007 .clampScalar(0, s32, s32);
1011 .
legalFor({{s32, s32}, {s64, s32}, {p0, s32}})
1012 .widenScalarToNextPow2(0)
1031 .
legalFor({{s64, p0}, {v2s64, v2p0}})
1032 .widenScalarToNextPow2(0, 64)
1038 return Query.
Types[0].getSizeInBits() != Query.
Types[1].getSizeInBits();
1040 .legalFor({{p0, s64}, {v2p0, v2s64}})
1041 .clampMaxNumElements(1, s64, 2);
1048 .legalForCartesianProduct({s64, v8s8, v4s16, v2s32})
1049 .legalForCartesianProduct({s128, v16s8, v8s16, v4s32, v2s64, v2p0})
1054 return DstTy.
isScalar() && SrcTy.isVector() &&
1055 SrcTy.getScalarSizeInBits() == 1;
1058 return Query.
Types[0].isVector() != Query.
Types[1].isVector();
1072 .clampScalar(0, s8, s64)
1079 bool UseOutlineAtomics = ST.outlineAtomics() && !ST.hasLSE();
1082 .
legalFor(!UseOutlineAtomics, {{s32, p0}, {s64, p0}})
1083 .customFor(!UseOutlineAtomics, {{s128, p0}})
1084 .libcallFor(UseOutlineAtomics,
1085 {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}, {s128, p0}})
1086 .clampScalar(0, s32, s64);
1089 G_ATOMICRMW_SUB, G_ATOMICRMW_AND, G_ATOMICRMW_OR,
1091 .legalFor(!UseOutlineAtomics, {{s32, p0}, {s64, p0}})
1092 .libcallFor(UseOutlineAtomics,
1093 {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
1094 .clampScalar(0, s32, s64);
1099 {G_ATOMICRMW_MIN, G_ATOMICRMW_MAX, G_ATOMICRMW_UMIN, G_ATOMICRMW_UMAX})
1101 .clampScalar(0, s32, s64);
1106 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
1107 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
1108 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
1115 switch (Q.
Types[BigTyIdx].getSizeInBits()) {
1123 switch (Q.
Types[LitTyIdx].getSizeInBits()) {
1137 .
legalFor(HasSVE, {{s16, nxv16s8, s64},
1138 {s16, nxv8s16, s64},
1139 {s32, nxv4s32, s64},
1140 {s64, nxv2s64, s64}})
1142 const LLT &EltTy = Query.
Types[1].getElementType();
1143 if (Query.
Types[1].isScalableVector())
1145 return Query.
Types[0] != EltTy;
1150 return VecTy == v8s8 || VecTy == v16s8 || VecTy == v2s16 ||
1151 VecTy == v4s16 || VecTy == v8s16 || VecTy == v2s32 ||
1152 VecTy == v4s32 || VecTy == v2s64 || VecTy == v2p0;
1158 return Query.
Types[1].isFixedVector() &&
1159 Query.
Types[1].getNumElements() <= 2;
1164 return Query.
Types[1].isFixedVector() &&
1165 Query.
Types[1].getNumElements() <= 4;
1170 return Query.
Types[1].isFixedVector() &&
1171 Query.
Types[1].getNumElements() <= 8;
1176 return Query.
Types[1].isFixedVector() &&
1177 Query.
Types[1].getNumElements() <= 16;
1180 .minScalarOrElt(0, s8)
1191 typeInSet(0, {v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64, v2p0}))
1192 .legalFor(HasSVE, {{nxv16s8, s32, s64},
1193 {nxv8s16, s32, s64},
1194 {nxv4s32, s32, s64},
1195 {nxv2s64, s64, s64}})
1214 .clampNumElements(0, v4s32, v4s32)
1232 {v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64}, DstTy);
1236 return Query.
Types[0].getNumElements() >
1237 Query.
Types[1].getNumElements();
1243 return Query.
Types[0].getNumElements() <
1244 Query.
Types[1].getNumElements();
1247 .widenScalarOrEltToNextPow2OrMinSize(0, 8)
1260 .
legalFor({{v16s8, v8s8}, {v8s16, v4s16}, {v4s32, v2s32}})
1263 return Query.
Types[0].isFixedVector() &&
1264 Query.
Types[1].isFixedVector() &&
1265 Query.
Types[0].getSizeInBits() <= 128 &&
1266 Query.
Types[1].getSizeInBits() <= 64;
1275 SrcTy.getNumElements())));
1279 .
legalFor({{v8s8, v16s8}, {v4s16, v8s16}, {v2s32, v4s32}})
1285 .
legalFor(HasSVE, {{nxv4s32, s32}, {nxv2s64, s64}});
1304 .customForCartesianProduct({p0}, {s8}, {s64})
1308 .legalForCartesianProduct({p0}, {p0}, {s64})
1324 .
legalFor({{s32, v2s32}, {s32, v4s32}, {s64, v2s64}})
1325 .legalFor(HasFP16, {{s16, v4s16}, {s16, v8s16}})
1326 .minScalarOrElt(0, MinFPScalar)
1368 G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM})
1369 .legalFor({{s32, v2s32}, {s32, v4s32}, {s64, v2s64}})
1370 .legalFor(HasFP16, {{s16, v4s16}, {s16, v8s16}})
1371 .minScalarOrElt(0, MinFPScalar)
1386 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX})
1387 .legalFor({{s8, v8s8},
1395 return Query.
Types[1].isVector() &&
1396 Query.
Types[1].getElementType() != s8 &&
1397 Query.
Types[1].getNumElements() & 1;
1400 .clampMaxNumElements(1, s64, 2)
1408 {G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
1415 if (SrcTy.isScalar())
1420 return SrcTy.getSizeInBits() > 64;
1424 return std::make_pair(1, SrcTy.divide(2));
1434 G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
1444 verify(*ST.getInstrInfo());
1453 switch (
MI.getOpcode()) {
1457 case TargetOpcode::G_VAARG:
1458 return legalizeVaArg(
MI,
MRI, MIRBuilder);
1459 case TargetOpcode::G_LOAD:
1460 case TargetOpcode::G_STORE:
1461 return legalizeLoadStore(
MI,
MRI, MIRBuilder, Observer);
1462 case TargetOpcode::G_SHL:
1463 case TargetOpcode::G_ASHR:
1464 case TargetOpcode::G_LSHR:
1465 return legalizeShlAshrLshr(
MI,
MRI, MIRBuilder, Observer);
1466 case TargetOpcode::G_GLOBAL_VALUE:
1467 return legalizeSmallCMGlobalValue(
MI,
MRI, MIRBuilder, Observer);
1468 case TargetOpcode::G_SBFX:
1469 case TargetOpcode::G_UBFX:
1470 return legalizeBitfieldExtract(
MI,
MRI, Helper);
1471 case TargetOpcode::G_FSHL:
1472 case TargetOpcode::G_FSHR:
1473 return legalizeFunnelShift(
MI,
MRI, MIRBuilder, Observer, Helper);
1474 case TargetOpcode::G_ROTR:
1475 return legalizeRotate(
MI,
MRI, Helper);
1476 case TargetOpcode::G_CTPOP:
1477 return legalizeCTPOP(
MI,
MRI, Helper);
1478 case TargetOpcode::G_ATOMIC_CMPXCHG:
1479 return legalizeAtomicCmpxchg128(
MI,
MRI, Helper);
1480 case TargetOpcode::G_CTTZ:
1481 return legalizeCTTZ(
MI, Helper);
1482 case TargetOpcode::G_BZERO:
1483 case TargetOpcode::G_MEMCPY:
1484 case TargetOpcode::G_MEMMOVE:
1485 case TargetOpcode::G_MEMSET:
1486 return legalizeMemOps(
MI, Helper);
1487 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1488 return legalizeExtractVectorElt(
MI,
MRI, Helper);
1489 case TargetOpcode::G_DYN_STACKALLOC:
1490 return legalizeDynStackAlloc(
MI, Helper);
1491 case TargetOpcode::G_PREFETCH:
1492 return legalizePrefetch(
MI, Helper);
1493 case TargetOpcode::G_ABS:
1495 case TargetOpcode::G_ICMP:
1496 return legalizeICMP(
MI,
MRI, MIRBuilder);
1497 case TargetOpcode::G_BITCAST:
1498 return legalizeBitcast(
MI, Helper);
1499 case TargetOpcode::G_FPTRUNC:
1502 return legalizeFptrunc(
MI, MIRBuilder,
MRI);
1510 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
"Unexpected opcode");
1511 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
1514 if (!DstTy.isScalar() || !SrcTy.isVector() ||
1519 MI.eraseFromParent();
1528 assert(
MI.getOpcode() == TargetOpcode::G_FSHL ||
1529 MI.getOpcode() == TargetOpcode::G_FSHR);
1533 Register ShiftNo =
MI.getOperand(3).getReg();
1534 LLT ShiftTy =
MRI.getType(ShiftNo);
1539 LLT OperationTy =
MRI.getType(
MI.getOperand(0).getReg());
1543 if (!VRegAndVal || VRegAndVal->Value.urem(
BitWidth) == 0)
1549 Amount =
MI.getOpcode() == TargetOpcode::G_FSHL ?
BitWidth - Amount : Amount;
1553 if (ShiftTy.
getSizeInBits() == 64 &&
MI.getOpcode() == TargetOpcode::G_FSHR &&
1560 if (
MI.getOpcode() == TargetOpcode::G_FSHR) {
1562 MI.getOperand(3).setReg(Cast64.getReg(0));
1567 else if (
MI.getOpcode() == TargetOpcode::G_FSHL) {
1568 MIRBuilder.
buildInstr(TargetOpcode::G_FSHR, {
MI.getOperand(0).getReg()},
1569 {
MI.getOperand(1).getReg(),
MI.getOperand(2).getReg(),
1571 MI.eraseFromParent();
1580 Register SrcReg1 =
MI.getOperand(2).getReg();
1581 Register SrcReg2 =
MI.getOperand(3).getReg();
1582 LLT DstTy =
MRI.getType(DstReg);
1583 LLT SrcTy =
MRI.getType(SrcReg1);
1600 MIRBuilder.
buildNot(DstReg, CmpReg);
1602 MI.eraseFromParent();
1612 LLT AmtTy =
MRI.getType(AmtReg);
1618 MI.getOperand(2).setReg(NewAmt.getReg(0));
1623bool AArch64LegalizerInfo::legalizeSmallCMGlobalValue(
1626 assert(
MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
1631 auto &GlobalOp =
MI.getOperand(1);
1633 if (GlobalOp.isSymbol())
1635 const auto* GV = GlobalOp.getGlobal();
1636 if (GV->isThreadLocal())
1639 auto &TM = ST->getTargetLowering()->getTargetMachine();
1640 unsigned OpFlags = ST->ClassifyGlobalReference(GV, TM);
1645 auto Offset = GlobalOp.getOffset();
1650 MRI.setRegClass(ADRP.getReg(0), &AArch64::GPR64RegClass);
1667 "Should not have folded in an offset for a tagged global!");
1669 .addGlobalAddress(GV, 0x100000000,
1672 MRI.setRegClass(ADRP.getReg(0), &AArch64::GPR64RegClass);
1675 MIRBuilder.
buildInstr(AArch64::G_ADD_LOW, {DstReg}, {ADRP})
1676 .addGlobalAddress(GV,
Offset,
1678 MI.eraseFromParent();
1687 auto LowerUnaryOp = [&
MI, &MIB](
unsigned Opcode) {
1689 MI.eraseFromParent();
1692 auto LowerBinOp = [&
MI, &MIB](
unsigned Opcode) {
1694 {
MI.getOperand(2),
MI.getOperand(3)});
1695 MI.eraseFromParent();
1698 auto LowerTriOp = [&
MI, &MIB](
unsigned Opcode) {
1700 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4)});
1701 MI.eraseFromParent();
1706 switch (IntrinsicID) {
1707 case Intrinsic::vacopy: {
1708 unsigned PtrSize = ST->isTargetILP32() ? 4 : 8;
1709 unsigned VaListSize =
1710 (ST->isTargetDarwin() || ST->isTargetWindows())
1712 : ST->isTargetILP32() ? 20 : 32;
1720 VaListSize,
Align(PtrSize)));
1724 VaListSize,
Align(PtrSize)));
1725 MI.eraseFromParent();
1728 case Intrinsic::get_dynamic_area_offset: {
1730 MI.eraseFromParent();
1733 case Intrinsic::aarch64_mops_memset_tag: {
1734 assert(
MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
1737 auto &
Value =
MI.getOperand(3);
1739 Value.setReg(ExtValueReg);
1742 case Intrinsic::aarch64_prefetch: {
1743 auto &AddrVal =
MI.getOperand(1);
1745 int64_t IsWrite =
MI.getOperand(2).getImm();
1746 int64_t
Target =
MI.getOperand(3).getImm();
1747 int64_t IsStream =
MI.getOperand(4).getImm();
1748 int64_t IsData =
MI.getOperand(5).getImm();
1750 unsigned PrfOp = (IsWrite << 4) |
1756 MI.eraseFromParent();
1759 case Intrinsic::aarch64_range_prefetch: {
1760 auto &AddrVal =
MI.getOperand(1);
1762 int64_t IsWrite =
MI.getOperand(2).getImm();
1763 int64_t IsStream =
MI.getOperand(3).getImm();
1764 unsigned PrfOp = (IsStream << 2) | IsWrite;
1766 MIB.
buildInstr(AArch64::G_AARCH64_RANGE_PREFETCH)
1769 .
addUse(
MI.getOperand(4).getReg());
1770 MI.eraseFromParent();
1773 case Intrinsic::aarch64_prefetch_ir: {
1774 auto &AddrVal =
MI.getOperand(1);
1776 MI.eraseFromParent();
1779 case Intrinsic::aarch64_neon_uaddv:
1780 case Intrinsic::aarch64_neon_saddv:
1781 case Intrinsic::aarch64_neon_umaxv:
1782 case Intrinsic::aarch64_neon_smaxv:
1783 case Intrinsic::aarch64_neon_uminv:
1784 case Intrinsic::aarch64_neon_sminv: {
1785 bool IsSigned = IntrinsicID == Intrinsic::aarch64_neon_saddv ||
1786 IntrinsicID == Intrinsic::aarch64_neon_smaxv ||
1787 IntrinsicID == Intrinsic::aarch64_neon_sminv;
1789 auto OldDst =
MI.getOperand(0).getReg();
1790 auto OldDstTy =
MRI.getType(OldDst);
1791 LLT NewDstTy =
MRI.getType(
MI.getOperand(2).getReg()).getElementType();
1792 if (OldDstTy == NewDstTy)
1795 auto NewDst =
MRI.createGenericVirtualRegister(NewDstTy);
1798 MI.getOperand(0).setReg(NewDst);
1802 MIB.
buildExtOrTrunc(IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT,
1807 case Intrinsic::aarch64_neon_uaddlp:
1808 case Intrinsic::aarch64_neon_saddlp: {
1809 unsigned Opc = IntrinsicID == Intrinsic::aarch64_neon_uaddlp
1811 : AArch64::G_SADDLP;
1813 MI.eraseFromParent();
1817 case Intrinsic::aarch64_neon_uaddlv:
1818 case Intrinsic::aarch64_neon_saddlv: {
1819 unsigned Opc = IntrinsicID == Intrinsic::aarch64_neon_uaddlv
1821 : AArch64::G_SADDLV;
1824 LLT DstTy =
MRI.getType(DstReg);
1848 MI.eraseFromParent();
1852 case Intrinsic::aarch64_neon_smax:
1853 return LowerBinOp(TargetOpcode::G_SMAX);
1854 case Intrinsic::aarch64_neon_smin:
1855 return LowerBinOp(TargetOpcode::G_SMIN);
1856 case Intrinsic::aarch64_neon_umax:
1857 return LowerBinOp(TargetOpcode::G_UMAX);
1858 case Intrinsic::aarch64_neon_umin:
1859 return LowerBinOp(TargetOpcode::G_UMIN);
1860 case Intrinsic::aarch64_neon_fmax:
1861 return LowerBinOp(TargetOpcode::G_FMAXIMUM);
1862 case Intrinsic::aarch64_neon_fmin:
1863 return LowerBinOp(TargetOpcode::G_FMINIMUM);
1864 case Intrinsic::aarch64_neon_fmaxnm:
1865 return LowerBinOp(TargetOpcode::G_FMAXNUM);
1866 case Intrinsic::aarch64_neon_fminnm:
1867 return LowerBinOp(TargetOpcode::G_FMINNUM);
1868 case Intrinsic::aarch64_neon_pmull:
1869 case Intrinsic::aarch64_neon_pmull64:
1870 return LowerBinOp(AArch64::G_PMULL);
1871 case Intrinsic::aarch64_neon_smull:
1872 return LowerBinOp(AArch64::G_SMULL);
1873 case Intrinsic::aarch64_neon_umull:
1874 return LowerBinOp(AArch64::G_UMULL);
1875 case Intrinsic::aarch64_neon_sabd:
1876 return LowerBinOp(TargetOpcode::G_ABDS);
1877 case Intrinsic::aarch64_neon_uabd:
1878 return LowerBinOp(TargetOpcode::G_ABDU);
1879 case Intrinsic::aarch64_neon_uhadd:
1880 return LowerBinOp(TargetOpcode::G_UAVGFLOOR);
1881 case Intrinsic::aarch64_neon_urhadd:
1882 return LowerBinOp(TargetOpcode::G_UAVGCEIL);
1883 case Intrinsic::aarch64_neon_shadd:
1884 return LowerBinOp(TargetOpcode::G_SAVGFLOOR);
1885 case Intrinsic::aarch64_neon_srhadd:
1886 return LowerBinOp(TargetOpcode::G_SAVGCEIL);
1887 case Intrinsic::aarch64_neon_sqshrn: {
1888 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
1892 {
MRI.getType(
MI.getOperand(2).getReg())},
1893 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1895 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {
MI.getOperand(0)}, {Shr});
1896 MI.eraseFromParent();
1899 case Intrinsic::aarch64_neon_sqshrun: {
1900 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
1904 {
MRI.getType(
MI.getOperand(2).getReg())},
1905 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1907 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {
MI.getOperand(0)}, {Shr});
1908 MI.eraseFromParent();
1911 case Intrinsic::aarch64_neon_sqrshrn: {
1912 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
1915 auto Shr = MIB.
buildInstr(AArch64::G_SRSHR_I,
1916 {
MRI.getType(
MI.getOperand(2).getReg())},
1917 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1919 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {
MI.getOperand(0)}, {Shr});
1920 MI.eraseFromParent();
1923 case Intrinsic::aarch64_neon_sqrshrun: {
1924 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
1927 auto Shr = MIB.
buildInstr(AArch64::G_SRSHR_I,
1928 {
MRI.getType(
MI.getOperand(2).getReg())},
1929 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1931 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {
MI.getOperand(0)}, {Shr});
1932 MI.eraseFromParent();
1935 case Intrinsic::aarch64_neon_uqrshrn: {
1936 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
1939 auto Shr = MIB.
buildInstr(AArch64::G_URSHR_I,
1940 {
MRI.getType(
MI.getOperand(2).getReg())},
1941 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1943 MIB.
buildInstr(TargetOpcode::G_TRUNC_USAT_U, {
MI.getOperand(0)}, {Shr});
1944 MI.eraseFromParent();
1947 case Intrinsic::aarch64_neon_uqshrn: {
1948 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
1952 {
MRI.getType(
MI.getOperand(2).getReg())},
1953 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1955 MIB.
buildInstr(TargetOpcode::G_TRUNC_USAT_U, {
MI.getOperand(0)}, {Shr});
1956 MI.eraseFromParent();
1959 case Intrinsic::aarch64_neon_sqshlu: {
1962 *
MRI.getVRegDef(
MI.getOperand(3).getReg()),
MRI);
1965 MIB.
buildInstr(AArch64::G_SQSHLU_I, {
MI.getOperand(0)},
1967 .addImm(ShiftAmount->getSExtValue());
1968 MI.eraseFromParent();
1973 case Intrinsic::aarch64_neon_vsli: {
1975 AArch64::G_SLI, {
MI.getOperand(0)},
1976 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4).getImm()});
1977 MI.eraseFromParent();
1980 case Intrinsic::aarch64_neon_vsri: {
1982 AArch64::G_SRI, {
MI.getOperand(0)},
1983 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4).getImm()});
1984 MI.eraseFromParent();
1987 case Intrinsic::aarch64_neon_abs: {
1989 MIB.
buildInstr(TargetOpcode::G_ABS, {
MI.getOperand(0)}, {
MI.getOperand(2)});
1990 MI.eraseFromParent();
1993 case Intrinsic::aarch64_neon_sqadd: {
1994 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
1995 return LowerBinOp(TargetOpcode::G_SADDSAT);
1998 case Intrinsic::aarch64_neon_sqsub: {
1999 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2000 return LowerBinOp(TargetOpcode::G_SSUBSAT);
2003 case Intrinsic::aarch64_neon_uqadd: {
2004 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2005 return LowerBinOp(TargetOpcode::G_UADDSAT);
2008 case Intrinsic::aarch64_neon_uqsub: {
2009 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2010 return LowerBinOp(TargetOpcode::G_USUBSAT);
2013 case Intrinsic::aarch64_neon_udot:
2014 return LowerTriOp(AArch64::G_UDOT);
2015 case Intrinsic::aarch64_neon_sdot:
2016 return LowerTriOp(AArch64::G_SDOT);
2017 case Intrinsic::aarch64_neon_usdot:
2018 return LowerTriOp(AArch64::G_USDOT);
2019 case Intrinsic::aarch64_neon_sqxtn:
2020 return LowerUnaryOp(TargetOpcode::G_TRUNC_SSAT_S);
2021 case Intrinsic::aarch64_neon_sqxtun:
2022 return LowerUnaryOp(TargetOpcode::G_TRUNC_SSAT_U);
2023 case Intrinsic::aarch64_neon_uqxtn:
2024 return LowerUnaryOp(TargetOpcode::G_TRUNC_USAT_U);
2025 case Intrinsic::aarch64_neon_fcvtzu:
2026 return LowerUnaryOp(TargetOpcode::G_FPTOUI_SAT);
2027 case Intrinsic::aarch64_neon_fcvtzs:
2028 return LowerUnaryOp(TargetOpcode::G_FPTOSI_SAT);
2030 case Intrinsic::vector_reverse:
2038bool AArch64LegalizerInfo::legalizeShlAshrLshr(
2041 assert(
MI.getOpcode() == TargetOpcode::G_ASHR ||
2042 MI.getOpcode() == TargetOpcode::G_LSHR ||
2043 MI.getOpcode() == TargetOpcode::G_SHL);
2056 MI.getOperand(2).setReg(ExtCst.getReg(0));
2077bool AArch64LegalizerInfo::legalizeLoadStore(
2080 assert(
MI.getOpcode() == TargetOpcode::G_STORE ||
2081 MI.getOpcode() == TargetOpcode::G_LOAD);
2092 const LLT ValTy =
MRI.getType(ValReg);
2097 bool IsLoad =
MI.getOpcode() == TargetOpcode::G_LOAD;
2101 ST->hasLSE2() && ST->hasRCPC3() && (IsLoadAcquire || IsStoreRelease);
2107 Opcode = IsLoad ? AArch64::LDIAPPX : AArch64::STILPX;
2113 assert(ST->hasLSE2() &&
"ldp/stp not single copy atomic without +lse2");
2115 Opcode = IsLoad ? AArch64::LDPXi : AArch64::STPXi;
2118 MachineInstrBuilder NewI;
2120 NewI = MIRBuilder.
buildInstr(Opcode, {s64, s64}, {});
2126 Opcode, {}, {
Split->getOperand(0),
Split->getOperand(1)});
2130 NewI.
addUse(
MI.getOperand(1).getReg());
2141 *
MRI.getTargetRegisterInfo(),
2142 *ST->getRegBankInfo());
2143 MI.eraseFromParent();
2149 LLVM_DEBUG(
dbgs() <<
"Tried to do custom legalization on wrong load/store");
2155 auto &MMO = **
MI.memoperands_begin();
2158 if (
MI.getOpcode() == TargetOpcode::G_STORE) {
2162 auto NewLoad = MIRBuilder.
buildLoad(NewTy,
MI.getOperand(1), MMO);
2165 MI.eraseFromParent();
2172 MachineFunction &MF = MIRBuilder.
getMF();
2173 Align Alignment(
MI.getOperand(2).getImm());
2175 Register ListPtr =
MI.getOperand(1).getReg();
2177 LLT PtrTy =
MRI.getType(ListPtr);
2187 MachineInstrBuilder DstPtr;
2188 if (Alignment > PtrAlign) {
2192 auto ListTmp = MIRBuilder.
buildPtrAdd(PtrTy,
List, AlignMinus1.getReg(0));
2197 LLT ValTy =
MRI.getType(Dst);
2202 ValTy, std::max(Alignment, PtrAlign)));
2213 MI.eraseFromParent();
2217bool AArch64LegalizerInfo::legalizeBitfieldExtract(
2248 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2251 LLT Ty =
MRI.getType(Val);
2255 "Expected src and dst to have the same type!");
2263 auto Add = MIRBuilder.
buildAdd(s64, CTPOP1, CTPOP2);
2266 MI.eraseFromParent();
2270 if (!ST->hasNEON() ||
2271 MI.getMF()->getFunction().hasFnAttribute(Attribute::NoImplicitFloat)) {
2283 assert((Size == 32 || Size == 64 || Size == 128) &&
"Expected only 32, 64, or 128 bit scalars!");
2285 Val = MIRBuilder.buildZExt(LLT::scalar(64), Val).getReg(0);
2297 LLT Dt = Ty == LLT::fixed_vector(2, 64) ? LLT::fixed_vector(4, 32) : Ty;
2298 auto Zeros = MIRBuilder.buildConstant(Dt, 0);
2299 auto Ones = MIRBuilder.buildConstant(VTy, 1);
2300 MachineInstrBuilder Sum;
2302 if (Ty == LLT::fixed_vector(2, 64)) {
2304 MIRBuilder.buildInstr(AArch64::G_UDOT, {Dt}, {Zeros, Ones, CTPOP});
2305 Sum = MIRBuilder.buildInstr(AArch64::G_UADDLP, {Ty}, {UDOT});
2307 Sum = MIRBuilder.
buildInstr(AArch64::G_UDOT, {Dt}, {Zeros, Ones,
CTPOP});
2309 Sum = MIRBuilder.
buildInstr(AArch64::G_UDOT, {Dt}, {Zeros, Ones,
CTPOP});
2315 MI.eraseFromParent();
2323 Opc = Intrinsic::aarch64_neon_uaddlv;
2324 HAddTys.push_back(LLT::scalar(32));
2326 Opc = Intrinsic::aarch64_neon_uaddlp;
2329 Opc = Intrinsic::aarch64_neon_uaddlp;
2333 Opc = Intrinsic::aarch64_neon_uaddlp;
2338 Opc = Intrinsic::aarch64_neon_uaddlp;
2341 Opc = Intrinsic::aarch64_neon_uaddlp;
2347 for (
LLT HTy : HAddTys) {
2357 MI.eraseFromParent();
2361bool AArch64LegalizerInfo::legalizeAtomicCmpxchg128(
2363 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2365 auto Addr =
MI.getOperand(1).getReg();
2366 auto DesiredI = MIRBuilder.
buildUnmerge({s64, s64},
MI.getOperand(2));
2367 auto NewI = MIRBuilder.
buildUnmerge({s64, s64},
MI.getOperand(3));
2368 auto DstLo =
MRI.createGenericVirtualRegister(s64);
2369 auto DstHi =
MRI.createGenericVirtualRegister(s64);
2371 MachineInstrBuilder CAS;
2382 auto Ordering = (*
MI.memoperands_begin())->getMergedOrdering();
2386 Opcode = AArch64::CASPAX;
2389 Opcode = AArch64::CASPLX;
2393 Opcode = AArch64::CASPALX;
2396 Opcode = AArch64::CASPX;
2401 auto CASDst =
MRI.createGenericVirtualRegister(s128);
2402 auto CASDesired =
MRI.createGenericVirtualRegister(s128);
2403 auto CASNew =
MRI.createGenericVirtualRegister(s128);
2404 MIRBuilder.
buildInstr(TargetOpcode::REG_SEQUENCE, {CASDesired}, {})
2405 .addUse(DesiredI->getOperand(0).getReg())
2407 .
addUse(DesiredI->getOperand(1).getReg())
2408 .
addImm(AArch64::subo64);
2409 MIRBuilder.
buildInstr(TargetOpcode::REG_SEQUENCE, {CASNew}, {})
2413 .
addImm(AArch64::subo64);
2415 CAS = MIRBuilder.
buildInstr(Opcode, {CASDst}, {CASDesired, CASNew, Addr});
2423 auto Ordering = (*
MI.memoperands_begin())->getMergedOrdering();
2427 Opcode = AArch64::CMP_SWAP_128_ACQUIRE;
2430 Opcode = AArch64::CMP_SWAP_128_RELEASE;
2434 Opcode = AArch64::CMP_SWAP_128;
2437 Opcode = AArch64::CMP_SWAP_128_MONOTONIC;
2441 auto Scratch =
MRI.createVirtualRegister(&AArch64::GPR64RegClass);
2442 CAS = MIRBuilder.
buildInstr(Opcode, {DstLo, DstHi, Scratch},
2443 {Addr, DesiredI->getOperand(0),
2444 DesiredI->getOperand(1), NewI->
getOperand(0),
2450 *
MRI.getTargetRegisterInfo(),
2451 *ST->getRegBankInfo());
2454 MI.eraseFromParent();
2460 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2461 MachineRegisterInfo &
MRI = *MIRBuilder.
getMRI();
2462 LLT Ty =
MRI.getType(
MI.getOperand(1).getReg());
2464 MIRBuilder.
buildCTLZ(
MI.getOperand(0).getReg(), BitReverse);
2465 MI.eraseFromParent();
2471 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2474 if (
MI.getOpcode() == TargetOpcode::G_MEMSET) {
2477 auto &
Value =
MI.getOperand(1);
2480 Value.setReg(ExtValueReg);
2487bool AArch64LegalizerInfo::legalizeExtractVectorElt(
2501bool AArch64LegalizerInfo::legalizeDynStackAlloc(
2503 MachineFunction &MF = *
MI.getParent()->getParent();
2504 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2505 MachineRegisterInfo &
MRI = *MIRBuilder.
getMRI();
2517 Register AllocSize =
MI.getOperand(1).getReg();
2521 "Unexpected type for dynamic alloca");
2523 "Unexpected type for dynamic alloca");
2525 LLT PtrTy =
MRI.getType(Dst);
2531 MIRBuilder.
buildInstr(AArch64::PROBED_STACKALLOC_DYN, {}, {SPTmp});
2532 MRI.setRegClass(NewMI.getReg(0), &AArch64::GPR64commonRegClass);
2533 MIRBuilder.
setInsertPt(*NewMI->getParent(), NewMI);
2536 MI.eraseFromParent();
2543 auto &AddrVal =
MI.getOperand(0);
2545 int64_t IsWrite =
MI.getOperand(1).getImm();
2546 int64_t Locality =
MI.getOperand(2).getImm();
2547 int64_t
IsData =
MI.getOperand(3).getImm();
2549 bool IsStream = Locality == 0;
2550 if (Locality != 0) {
2551 assert(Locality <= 3 &&
"Prefetch locality out-of-range");
2555 Locality = 3 - Locality;
2558 unsigned PrfOp = (IsWrite << 4) | (!IsData << 3) | (Locality << 1) | IsStream;
2561 MI.eraseFromParent();
2568 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
2570 "Expected a power of 2 elements");
2588 int StepSize = ElemCount % 4 ? 2 : 4;
2595 for (
unsigned i = 0; i < ElemCount / 2; ++i)
2596 RegsToUnmergeTo.
push_back(
MRI.createGenericVirtualRegister(v2s64));
2602 for (
auto SrcReg : RegsToUnmergeTo) {
2604 MIRBuilder.
buildInstr(AArch64::G_FPTRUNC_ODD, {v2s32}, {SrcReg})
2612 for (
unsigned LoopIter = 0; LoopIter < ElemCount / StepSize; ++LoopIter) {
2613 if (StepSize == 4) {
2617 {v4s32}, {TruncOddDstRegs[
Index++], TruncOddDstRegs[
Index++]})
2629 if (RegsToMerge.
size() == 1) {
2631 MI.eraseFromParent();
2637 MRI.replaceRegWith(Dst, Fin);
2638 MI.eraseFromParent();
unsigned const MachineRegisterInfo * MRI
static void matchLDPSTPAddrMode(Register Root, Register &Base, int &Offset, MachineRegisterInfo &MRI)
This file declares the targeting of the Machinelegalizer class for AArch64.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr MCPhysReg SPReg
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
AArch64LegalizerInfo(const AArch64Subtarget &ST)
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
int64_t getSExtValue() const
Get sign extended value.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
static constexpr LLT scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits)
Get a low-level scalable vector of some number of elements and element width.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
constexpr bool isPointerVector() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr ElementCount getElementCount() const
constexpr LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isFixedVector() const
Returns true if the LLT is a fixed vector.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
LLVM_ABI void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & widenScalarOrEltToNextPow2OrMinSize(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar or vector element type to the next power of two that is at least MinSize.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & maxScalarEltSameAsIf(LegalityPredicate Predicate, unsigned TypeIdx, unsigned SmallTypeIdx)
Conditionally narrow the scalar or elt to match the size of another.
LegalizeRuleSet & unsupported()
The instruction is unsupported.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & bitcastIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
The specified type index is coerced if predicate is true.
LegalizeRuleSet & libcallFor(std::initializer_list< LLT > Types)
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & minScalarOrElt(unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)
Limit the number of elements in EltTy vectors to at most MaxElements.
LegalizeRuleSet & clampMinNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MinElements)
Limit the number of elements in EltTy vectors to at least MinElements.
LegalizeRuleSet & widenVectorEltsToVectorMinSize(unsigned TypeIdx, unsigned VectorSize)
Ensure the vector size is at least as wide as VectorSize by promoting the element.
LegalizeRuleSet & lowerIfMemSizeNotPow2()
Lower a memory operation if the memory size, rounded to bytes, is not a power of 2.
LegalizeRuleSet & minScalarEltSameAsIf(LegalityPredicate Predicate, unsigned TypeIdx, unsigned LargeTypeIdx)
Conditionally widen the scalar or elt to match the size of another.
LegalizeRuleSet & customForCartesianProduct(std::initializer_list< LLT > Types)
LegalizeRuleSet & lowerIfMemSizeNotByteSizePow2()
Lower a memory operation if the memory access size is not a round power of 2 byte size.
LegalizeRuleSet & moreElementsToNextPow2(unsigned TypeIdx)
Add more elements to the vector to reach the next power of two.
LegalizeRuleSet & narrowScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Narrow the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Add more elements to reach the type selected by the mutation if the predicate is true.
LegalizeRuleSet & lowerFor(std::initializer_list< LLT > Types)
The instruction is lowered when type index 0 is any type in the given list.
LegalizeRuleSet & scalarizeIf(LegalityPredicate Predicate, unsigned TypeIdx)
LegalizeRuleSet & lowerIf(LegalityPredicate Predicate)
The instruction is lowered if predicate is true.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx)
Widen the scalar to match the size of another.
LegalizeRuleSet & unsupportedIf(LegalityPredicate Predicate)
LegalizeRuleSet & minScalarOrEltIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Ensure the scalar or element is at least as wide as Ty.
LegalizeRuleSet & widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation)
Widen the scalar to the one selected by the mutation if the predicate is true.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & clampNumElements(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the number of elements for the given vectors to at least MinTy's number of elements and at most...
LegalizeRuleSet & maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT Ty)
Conditionally limit the maximum size of the scalar.
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & legalForTypesWithMemDesc(std::initializer_list< LegalityPredicates::TypePairAndMemDesc > TypesAndMemDesc)
The instruction is legal when type indexes 0 and 1 along with the memory size and minimum alignment i...
unsigned immIdx(unsigned ImmIdx)
LegalizeRuleSet & widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar or vector element type to the next power of two that is at least MinSize.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
const TargetLowering & getTargetLowering() const
LLVM_ABI LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI)
LLVM_ABI MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val)
Create a store of Val to a stack temporary and return a load as the same type as Res.
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize, Align Alignment, LLT PtrTy)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
const LegacyLegalizerInfo & getLegacyLegalizerInfo() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
MachineInstrBuilder buildAdd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ADD Op0, Op1.
MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0)
Build and insert a bitwise not, NegOne = G_CONSTANT -1 Res = G_OR Op0, NegOne.
MachineInstrBuilder buildUnmerge(ArrayRef< LLT > Res, const SrcOp &Op)
Build and insert Res0, ... = G_UNMERGE_VALUES Op.
MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index)
Build and insert Res0, ... = G_EXTRACT Src, Idx0.
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_ICMP Pred, Op0, Op1.
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef< Register > Res, bool HasSideEffects, bool isConvergent)
Build and insert a G_INTRINSIC instruction.
MachineInstrBuilder buildCTLZ(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_CTLZ Op0, Src0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_PTR_ADD Op0, Op1.
MachineInstrBuilder buildBitReverse(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITREVERSE Src.
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildCTPOP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_CTPOP Op0, Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildExtOrTrunc(unsigned ExtOpc, const DstOp &Res, const SrcOp &Op)
Build and insert Res = ExtOpc, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes of...
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
MachineInstrBuilder buildMaskLowPtrBits(const DstOp &Res, const SrcOp &Op0, uint32_t NumBits)
Build and insert Res = G_PTRMASK Op0, G_CONSTANT (1 << NumBits) - 1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
Wrapper class representing virtual and physical registers.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
Primary interface to the complete machine description for the target machine.
CodeModel::Model getCodeModel() const
Returns the code model.
Target - Wrapper for Target specific information.
LLVM Value Representation.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar or a vector with an element type that's wider than the ...
LLVM_ABI LegalityPredicate isPointerVector(unsigned TypeIdx)
True iff the specified type index is a vector of pointers (with any address space).
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1)
True iff the first type index has a smaller total bit size than second type index.
LLVM_ABI LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx, AtomicOrdering Ordering)
True iff the specified MMO index has at an atomic ordering of at Ordering or stronger.
Predicate any(Predicate P0, Predicate P1)
True iff P0 or P1 are true.
LLVM_ABI LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate scalarWiderThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's wider than the given size.
LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)
True iff the specified type index is a scalar that's narrower than the given size.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
LLVM_ABI LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min=0)
Add more elements to the type for the given type index to the next power of.
LLVM_ABI LegalizeMutation scalarize(unsigned TypeIdx)
Break up the vector type for the given type index into the element type.
LLVM_ABI LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx)
Keep the same scalar or element type as the given type index.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min=0)
Widen the scalar type or vector element type for the given type index to the next power of 2.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx)
Change the scalar size or element size to have the same scalar size as type index FromIndex.
operand_type_match m_Reg()
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
AtomicOrdering
Atomic ordering for LLVM's memory model.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
unsigned Log2(Align A)
Returns the log2 of the alignment.
This struct is a compact representation of a valid (non-zero power of two) alignment.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
This class contains a discriminated union of information about pointers in memory operands,...