29#include "llvm/IR/IntrinsicsAArch64.h"
32#include <initializer_list>
34#define DEBUG_TYPE "aarch64-legalinfo"
100 std::initializer_list<LLT> PackedVectorAllTypeList = {
106 std::initializer_list<LLT> ScalarAndPtrTypesList = {s8, s16, s32, s64, p0};
110 const TargetMachine &TM = ST.getTargetLowering()->getTargetMachine();
113 if (!ST.hasNEON() || !ST.hasFPARMv8()) {
120 const bool HasFP16 = ST.hasFullFP16();
121 const LLT &MinFPScalar = HasFP16 ? f16 : f32;
123 const bool HasCSSC = ST.hasCSSC();
124 const bool HasRCPC3 = ST.hasRCPC3();
125 const bool HasSVE = ST.hasSVE();
128 {G_IMPLICIT_DEF, G_FREEZE, G_CONSTANT_FOLD_BARRIER})
129 .legalFor({p0, s8, s16, s32, s64})
130 .legalFor({v2s8, v4s8, v8s8, v16s8, v2s16, v4s16, v8s16, v2s32, v4s32,
132 .widenScalarToNextPow2(0)
145 .legalFor(PackedVectorAllTypeList)
159 .widenScalarToNextPow2(0)
164 .maxScalarIf(
typeInSet(0, {s64, p0}), 1, s32);
169 .widenScalarToNextPow2(1)
174 .maxScalarIf(
typeInSet(1, {s64, p0}), 0, s32)
175 .maxScalarIf(
typeInSet(1, {s128}), 0, s64);
178 .legalFor({i32, i64, v8i8, v16i8, v4i16, v8i16, v2i32, v4i32, v2i64})
179 .legalFor(HasSVE, {nxv16s8, nxv8s16, nxv4s32, nxv2s64})
180 .widenScalarToNextPow2(0)
188 return Query.
Types[0].getNumElements() <= 2;
193 return Query.
Types[0].getNumElements() <= 4;
198 return Query.
Types[0].getNumElements() <= 16;
205 .
legalFor({i32, i64, v8i8, v16i8, v4i16, v8i16, v2i32, v4i32, v2i64})
206 .widenScalarToNextPow2(0)
214 return Query.
Types[0].getNumElements() <= 2;
219 return Query.
Types[0].getNumElements() <= 4;
224 return Query.
Types[0].getNumElements() <= 16;
232 const auto &SrcTy = Query.
Types[0];
233 const auto &AmtTy = Query.
Types[1];
234 return !SrcTy.isVector() && SrcTy.getSizeInBits() == 32 &&
235 AmtTy.getSizeInBits() == 32;
249 .widenScalarToNextPow2(0)
263 .
legalFor({{p0, i64}, {v2p0, v2i64}})
264 .clampScalarOrElt(1, s64, s64)
270 .legalFor({i32, i64})
272 .clampScalar(0, s32, s64)
277 .lowerFor({i8, i16, i32, i64, v2i32, v4i32, v2i64})
286 .widenScalarToNextPow2(0, 32)
291 .legalFor({s64, v16s8, v8s16, v4s32})
295 .legalFor({v8i8, v16i8, v4i16, v8i16, v2i32, v4i32})
296 .legalFor(HasCSSC, {i32, i64})
297 .minScalar(HasCSSC, 0, s32)
306 .legalFor({v16i8, v8i16, v4i32, v2i64, v2p0, v8i8, v4i16, v2i32})
310 return SrcTy.isScalar() && SrcTy.getSizeInBits() < 128;
314 [=](
const LegalityQuery &Query) {
return std::make_pair(0, v4i16); })
317 [=](
const LegalityQuery &Query) {
return std::make_pair(0, v2i32); })
318 .clampNumElements(0, v8s8, v16s8)
326 {G_ABDS, G_ABDU, G_UAVGFLOOR, G_UAVGCEIL, G_SAVGFLOOR, G_SAVGCEIL})
327 .legalFor({v8s8, v16s8, v4s16, v8s16, v2s32, v4s32})
331 {G_SADDE, G_SSUBE, G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_UADDO, G_USUBO})
332 .legalFor({{s32, s32}, {s64, s32}})
333 .clampScalar(0, s32, s64)
338 .customFor({{i32, i32}, {i32, i64}, {i64, i64}})
344 return Q.
Types[0].isScalar() && Q.
Types[1].getScalarSizeInBits() < 64;
350 .customFor({{s32, s32}, {s64, s64}});
354 .
legalFor(HasCSSC, {{s32, s32}, {s64, s64}})
355 .legalFor({{v8s8, v8s8}, {v16s8, v16s8}})
356 .customFor(!HasCSSC, {{s32, s32}, {s64, s64}})
357 .customFor({{s128, s128},
363 .clampScalar(0, s32, s128)
376 .legalFor({{s32, s32},
384 .widenScalarToNextPow2(1, 32)
402 .customFor(!HasCSSC, {s32, s64});
408 .widenScalarToNextPow2(0, 32)
420 .
legalFor({s32, s64, v4s16, v8s16, v2s32, v4s32, v2s64})
429 .legalFor({v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64})
430 .legalFor(HasSVE, {nxv16s8, nxv8s16, nxv4s32, nxv2s64})
431 .clampNumElements(0, v8s8, v16s8)
440 {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMA, G_FSQRT, G_FMAXNUM, G_FMINNUM,
441 G_FMAXIMUM, G_FMINIMUM, G_FCEIL, G_FFLOOR, G_FRINT, G_FNEARBYINT,
442 G_INTRINSIC_TRUNC, G_INTRINSIC_ROUND, G_INTRINSIC_ROUNDEVEN})
443 .legalFor({f32, f64, v2f32, v4f32, v2f64})
444 .legalFor(HasFP16, {f16, v4f16, v8f16})
454 .legalFor({f32, f64, v2f32, v4f32, v2f64})
455 .legalFor(HasFP16, {f16, v4f16, v8f16})
470 G_FLOG10, G_FTAN, G_FEXP, G_FEXP2, G_FEXP10,
471 G_FACOS, G_FASIN, G_FATAN, G_FATAN2, G_FCOSH,
472 G_FSINH, G_FTANH, G_FMODF})
481 .
libcallFor({{f32, i32}, {f64, i32}, {f128, i32}});
484 .legalFor({{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}})
485 .legalFor(HasFP16, {{s32, s16}, {s64, s16}})
490 .legalFor({{s64, s32}, {s64, s64}})
491 .legalFor(HasFP16, {{s64, s16}})
509 for (
unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {
512 if (
Op == G_SEXTLOAD)
517 .legalForTypesWithMemDesc({{s32, p0, s8, 8},
525 {v2s32, p0, s64, 8}})
526 .widenScalarToNextPow2(0)
527 .clampScalar(0, s32, s64)
530 .unsupportedIfMemSizeNotPow2()
542 return HasRCPC3 && Query.
Types[0] == s128 &&
546 return Query.
Types[0] == s128 &&
549 .legalForTypesWithMemDesc({{s8, p0, s8, 8},
556 {v16s8, p0, s128, 8},
558 {v8s16, p0, s128, 8},
560 {v4s32, p0, s128, 8},
561 {v2s64, p0, s128, 8}})
563 .legalForTypesWithMemDesc(
564 {{s32, p0, s8, 8}, {s32, p0, s16, 8}, {s64, p0, s32, 8}})
565 .legalForTypesWithMemDesc({
567 {nxv16s8, p0, nxv16s8, 8},
568 {nxv8s16, p0, nxv8s16, 8},
569 {nxv4s32, p0, nxv4s32, 8},
570 {nxv2s64, p0, nxv2s64, 8},
572 .widenScalarToNextPow2(0, 8)
583 return Query.
Types[0].isScalar() &&
585 Query.
Types[0].getSizeInBits() > 32;
594 .customIf(IsPtrVecPred)
600 return HasRCPC3 && Query.
Types[0] == s128 &&
604 return Query.
Types[0] == s128 &&
612 {{s8, p0, s8, 8}, {s16, p0, s8, 8},
615 {s16, p0, s16, 8}, {s32, p0, s16, 8},
617 {s32, p0, s8, 8}, {s32, p0, s16, 8}, {s32, p0, s32, 8},
618 {s64, p0, s64, 8}, {s64, p0, s32, 8},
619 {p0, p0, s64, 8}, {s128, p0, s128, 8}, {v16s8, p0, s128, 8},
620 {v8s8, p0, s64, 8}, {v4s16, p0, s64, 8}, {v8s16, p0, s128, 8},
621 {v2s32, p0, s64, 8}, {v4s32, p0, s128, 8}, {v2s64, p0, s128, 8}})
622 .legalForTypesWithMemDesc({
627 {nxv16s8, p0, nxv16s8, 8},
628 {nxv8s16, p0, nxv8s16, 8},
629 {nxv4s32, p0, nxv4s32, 8},
630 {nxv2s64, p0, nxv2s64, 8},
632 .clampScalar(0, s8, s64)
635 return Query.
Types[0].isScalar() &&
639 .clampMaxNumElements(0, s8, 16)
648 return Query.
Types[0].getSizeInBits() ==
649 Query.
MMODescrs[0].MemoryTy.getSizeInBits();
655 .customIf(IsPtrVecPred)
673 {p0, v16s8, v16s8, 8},
674 {p0, v4s16, v4s16, 8},
675 {p0, v8s16, v8s16, 8},
676 {p0, v2s32, v2s32, 8},
677 {p0, v4s32, v4s32, 8},
678 {p0, v2s64, v2s64, 8},
684 auto IndexedLoadBasicPred = [=](
const LegalityQuery &Query) {
712 return MemTy == s8 || MemTy == s16;
714 return MemTy == s8 || MemTy == s16 || MemTy == s32;
722 .widenScalarToNextPow2(0)
726 .clampScalar(0, MinFPScalar, s128);
730 .
legalFor({{i32, i32}, {i32, i64}, {i32, p0}})
740 return Ty.isVector() && !SrcTy.isPointerVector() &&
741 Ty.getElementType() != SrcTy.getElementType();
749 return Query.
Types[1].isPointerVector();
766 .legalFor(HasFP16, {{s32, f16}, {v4s16, v4f16}, {v8s16, v8f16}})
775 return Ty.isVector() && !SrcTy.isPointerVector() &&
776 Ty.getElementType() != SrcTy.getElementType();
779 .clampNumElements(1, v4s16, v8s16)
787 unsigned DstSize = Query.
Types[0].getSizeInBits();
790 if (Query.
Types[0].isVector())
793 if (DstSize < 8 || DstSize >= 128 || !
isPowerOf2_32(DstSize))
801 unsigned SrcSize = SrcTy.getSizeInBits();
808 .legalIf(ExtLegalFunc)
809 .
legalFor({{v8s16, v8s8}, {v4s32, v4s16}, {v2s64, v2s32}})
810 .clampScalar(0, s64, s64)
817 return (Query.
Types[0].getScalarSizeInBits() >
818 Query.
Types[1].getScalarSizeInBits() * 2) &&
819 Query.
Types[0].isVector() &&
820 (Query.
Types[1].getScalarSizeInBits() == 8 ||
821 Query.
Types[1].getScalarSizeInBits() == 16);
823 .clampMinNumElements(1, s8, 8)
828 .
legalFor({{v8s8, v8s16}, {v4s16, v4s32}, {v2s32, v2s64}})
839 return DstTy.
isVector() && SrcTy.getSizeInBits() > 128 &&
842 .clampMinNumElements(0, s8, 8)
847 .legalFor({{v8s8, v8s16}, {v4s16, v4s32}, {v2s32, v2s64}})
848 .clampNumElements(0, v2s32, v2s32);
852 .legalFor(PackedVectorAllTypeList)
863 {{f16, f32}, {f16, f64}, {f32, f64}, {v4f16, v4f32}, {v2f32, v2f64}})
864 .libcallFor({{f16, f128}, {f32, f128}, {f64, f128}})
870 SrcTy.getScalarSizeInBits() == 64 &&
874 .clampNumElements(1, v4s32, v4s32)
880 {{f32, f16}, {f64, f16}, {f64, f32}, {v4f32, v4f16}, {v2f64, v2f32}})
881 .libcallFor({{f128, f64}, {f128, f32}, {f128, f16}})
887 return SrcTy.isVector() && DstTy.
isVector() &&
888 SrcTy.getScalarSizeInBits() == 16 &&
892 .clampNumElements(0, v4s32, v4s32)
898 .legalFor({{i32, f32},
906 {{i32, f16}, {i64, f16}, {v4i16, v4f16}, {v8i16, v8f16}})
913 return Query.
Types[1] == f16 && Query.
Types[0].getSizeInBits() > 64;
922 return Query.
Types[0].getScalarSizeInBits() <= 64 &&
923 Query.
Types[0].getScalarSizeInBits() >
924 Query.
Types[1].getScalarSizeInBits();
929 return Query.
Types[1].getScalarSizeInBits() <= 64 &&
930 Query.
Types[0].getScalarSizeInBits() <
931 Query.
Types[1].getScalarSizeInBits();
934 .clampNumElements(0, v4s16, v8s16)
938 {{i32, f128}, {i64, f128}, {i128, f128}, {i128, f32}, {i128, f64}});
941 .legalFor({{i32, f32},
950 {{i16, f16}, {i32, f16}, {i64, f16}, {v4i16, v4f16}, {v8i16, v8f16}})
958 return Query.
Types[1] == f16 && Query.
Types[0].getSizeInBits() > 64;
968 unsigned ITySize = Query.
Types[0].getScalarSizeInBits();
969 return (ITySize == 16 || ITySize == 32 || ITySize == 64) &&
970 ITySize > Query.
Types[1].getScalarSizeInBits();
975 unsigned FTySize = Query.
Types[1].getScalarSizeInBits();
976 return (FTySize == 16 || FTySize == 32 || FTySize == 64) &&
977 Query.
Types[0].getScalarSizeInBits() < FTySize;
986 .legalFor({{f32, i32},
994 {{f16, i32}, {f16, i64}, {v4f16, v4i16}, {v8f16, v8i16}})
1001 return Query.
Types[1].isVector() &&
1002 Query.
Types[1].getScalarSizeInBits() == 64 &&
1003 Query.
Types[0].getScalarSizeInBits() == 16;
1007 return Query.
Types[0].getScalarType() == bf16;
1010 .widenScalarOrEltToNextPow2OrMinSize(0, HasFP16 ? 16 : 32)
1014 return Query.
Types[0].getScalarSizeInBits() == 32 &&
1015 Query.
Types[1].getScalarSizeInBits() == 64;
1020 return Query.
Types[1].getScalarSizeInBits() <= 64 &&
1021 Query.
Types[0].getScalarSizeInBits() <
1022 Query.
Types[1].getScalarSizeInBits();
1027 return Query.
Types[0].getScalarSizeInBits() <= 64 &&
1028 Query.
Types[0].getScalarSizeInBits() >
1029 Query.
Types[1].getScalarSizeInBits();
1032 .clampNumElements(0, v4s16, v8s16)
1046 .clampScalar(0, s32, s32);
1050 .
legalFor({{s32, s32}, {s64, s32}, {p0, s32}})
1051 .widenScalarToNextPow2(0)
1070 .
legalFor({{i64, p0}, {v2i64, v2p0}})
1071 .widenScalarToNextPow2(0, 64)
1077 return Query.
Types[0].getSizeInBits() != Query.
Types[1].getSizeInBits();
1079 .legalFor({{p0, i64}, {v2p0, v2i64}})
1080 .clampMaxNumElements(1, s64, 2);
1087 .legalForCartesianProduct({s32, v2s16, v4s8})
1088 .legalForCartesianProduct({s64, v8s8, v4s16, v2s32})
1089 .legalForCartesianProduct({s128, v16s8, v8s16, v4s32, v2s64, v2p0})
1094 return DstTy.
isScalar() && SrcTy.isVector() &&
1095 SrcTy.getScalarSizeInBits() == 1;
1098 return Query.
Types[0].isVector() != Query.
Types[1].isVector();
1113 .clampScalar(0, s8, s64)
1120 bool UseOutlineAtomics = ST.outlineAtomics() && !ST.hasLSE();
1123 .
legalFor(!UseOutlineAtomics, {{s32, p0}, {s64, p0}})
1124 .customFor(!UseOutlineAtomics, {{s128, p0}})
1125 .libcallFor(UseOutlineAtomics,
1126 {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}, {s128, p0}})
1127 .clampScalar(0, s32, s64);
1130 G_ATOMICRMW_SUB, G_ATOMICRMW_AND, G_ATOMICRMW_OR,
1132 .legalFor(!UseOutlineAtomics, {{s32, p0}, {s64, p0}})
1133 .libcallFor(UseOutlineAtomics,
1134 {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
1135 .clampScalar(0, s32, s64);
1140 {G_ATOMICRMW_MIN, G_ATOMICRMW_MAX, G_ATOMICRMW_UMIN, G_ATOMICRMW_UMAX})
1142 .clampScalar(0, s32, s64);
1147 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
1148 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
1149 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
1156 switch (Q.
Types[BigTyIdx].getSizeInBits()) {
1164 switch (Q.
Types[LitTyIdx].getSizeInBits()) {
1178 .
legalFor(HasSVE, {{s16, nxv16s8, s64},
1179 {s16, nxv8s16, s64},
1180 {s32, nxv4s32, s64},
1181 {s64, nxv2s64, s64}})
1183 const LLT &EltTy = Query.
Types[1].getElementType();
1184 if (Query.
Types[1].isScalableVector())
1186 return Query.
Types[0] != EltTy;
1191 return VecTy == v8s8 || VecTy == v16s8 || VecTy == v2s16 ||
1192 VecTy == v4s16 || VecTy == v8s16 || VecTy == v2s32 ||
1193 VecTy == v4s32 || VecTy == v2s64 || VecTy == v2p0;
1199 return Query.
Types[1].isFixedVector() &&
1200 Query.
Types[1].getNumElements() <= 2;
1205 return Query.
Types[1].isFixedVector() &&
1206 Query.
Types[1].getNumElements() <= 4;
1211 return Query.
Types[1].isFixedVector() &&
1212 Query.
Types[1].getNumElements() <= 8;
1217 return Query.
Types[1].isFixedVector() &&
1218 Query.
Types[1].getNumElements() <= 16;
1221 .minScalarOrElt(0, s8)
1232 typeInSet(0, {v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64, v2p0}))
1233 .legalFor(HasSVE, {{nxv16s8, s32, s64},
1234 {nxv8s16, s32, s64},
1235 {nxv4s32, s32, s64},
1236 {nxv2s64, s64, s64}})
1255 .clampNumElements(0, v4s32, v4s32)
1273 {v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64}, DstTy);
1277 return Query.
Types[0].getNumElements() >
1278 Query.
Types[1].getNumElements();
1284 return Query.
Types[0].getNumElements() <
1285 Query.
Types[1].getNumElements();
1288 .widenScalarOrEltToNextPow2OrMinSize(0, 8)
1302 .
legalFor({{v16s8, v8s8}, {v8s16, v4s16}, {v4s32, v2s32}})
1304 return Query.
Types[0].isFixedVector() &&
1305 Query.
Types[0].getScalarSizeInBits() < 8;
1309 return Query.
Types[0].isFixedVector() &&
1310 Query.
Types[1].isFixedVector() &&
1311 Query.
Types[0].getScalarSizeInBits() >= 8 &&
1313 Query.
Types[0].getSizeInBits() <= 128 &&
1314 Query.
Types[1].getSizeInBits() <= 64;
1323 SrcTy.getNumElements())));
1327 .
legalFor({{v8s8, v16s8}, {v4s16, v8s16}, {v2s32, v4s32}})
1333 .
legalFor(HasSVE, {{nxv4s32, s32}, {nxv2s64, s64}});
1352 .customForCartesianProduct({p0}, {s8}, {s64})
1356 .legalForCartesianProduct({p0}, {p0}, {s64})
1372 .
legalFor({{f32, v2f32}, {f32, v4f32}, {f64, v2f64}})
1373 .legalFor(HasFP16, {{f16, v4f16}, {f16, v8f16}})
1374 .minScalarOrElt(0, MinFPScalar)
1416 G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM})
1417 .legalFor({{f32, v2f32}, {f32, v4f32}, {f64, v2f64}})
1418 .legalFor(HasFP16, {{f16, v4f16}, {f16, v8f16}})
1419 .minScalarOrElt(0, MinFPScalar)
1434 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX})
1435 .legalFor({{i8, v8i8},
1443 return Query.
Types[1].isVector() &&
1444 Query.
Types[1].getElementType() != s8 &&
1445 Query.
Types[1].getNumElements() & 1;
1448 .clampMaxNumElements(1, s64, 2)
1456 {G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
1463 if (SrcTy.isScalar())
1468 return SrcTy.getSizeInBits() > 64;
1472 return std::make_pair(1, SrcTy.divide(2));
1482 G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
1492 verify(*ST.getInstrInfo());
1501 switch (
MI.getOpcode()) {
1505 case TargetOpcode::G_VAARG:
1506 return legalizeVaArg(
MI, MRI, MIRBuilder);
1507 case TargetOpcode::G_LOAD:
1508 case TargetOpcode::G_STORE:
1509 return legalizeLoadStore(
MI, MRI, MIRBuilder, Observer);
1510 case TargetOpcode::G_SHL:
1511 case TargetOpcode::G_ASHR:
1512 case TargetOpcode::G_LSHR:
1513 return legalizeShlAshrLshr(
MI, MRI, MIRBuilder, Observer);
1514 case TargetOpcode::G_GLOBAL_VALUE:
1515 return legalizeSmallCMGlobalValue(
MI, MRI, MIRBuilder, Observer);
1516 case TargetOpcode::G_SBFX:
1517 case TargetOpcode::G_UBFX:
1518 return legalizeBitfieldExtract(
MI, MRI, Helper);
1519 case TargetOpcode::G_FSHL:
1520 case TargetOpcode::G_FSHR:
1521 return legalizeFunnelShift(
MI, MRI, MIRBuilder, Observer, Helper);
1522 case TargetOpcode::G_ROTR:
1523 return legalizeRotate(
MI, MRI, Helper);
1524 case TargetOpcode::G_CTPOP:
1525 return legalizeCTPOP(
MI, MRI, Helper);
1526 case TargetOpcode::G_ATOMIC_CMPXCHG:
1527 return legalizeAtomicCmpxchg128(
MI, MRI, Helper);
1528 case TargetOpcode::G_CTTZ:
1529 return legalizeCTTZ(
MI, Helper);
1530 case TargetOpcode::G_BZERO:
1531 case TargetOpcode::G_MEMCPY:
1532 case TargetOpcode::G_MEMMOVE:
1533 case TargetOpcode::G_MEMSET:
1534 return legalizeMemOps(
MI, Helper);
1535 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1536 return legalizeExtractVectorElt(
MI, MRI, Helper);
1537 case TargetOpcode::G_DYN_STACKALLOC:
1538 return legalizeDynStackAlloc(
MI, Helper);
1539 case TargetOpcode::G_PREFETCH:
1540 return legalizePrefetch(
MI, Helper);
1541 case TargetOpcode::G_ABS:
1543 case TargetOpcode::G_ICMP:
1544 return legalizeICMP(
MI, MRI, MIRBuilder);
1545 case TargetOpcode::G_BITCAST:
1546 return legalizeBitcast(
MI, Helper);
1547 case TargetOpcode::G_CONCAT_VECTORS:
1548 return legalizeConcatVectors(
MI, MRI, MIRBuilder);
1549 case TargetOpcode::G_FPTRUNC:
1552 return legalizeFptrunc(
MI, MIRBuilder, MRI);
1560 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
"Unexpected opcode");
1561 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
1564 if (!DstTy.isScalar() || !SrcTy.isVector() ||
1569 MI.eraseFromParent();
1578 assert(
MI.getOpcode() == TargetOpcode::G_FSHL ||
1579 MI.getOpcode() == TargetOpcode::G_FSHR);
1583 Register ShiftNo =
MI.getOperand(3).getReg();
1589 LLT OperationTy = MRI.
getType(
MI.getOperand(0).getReg());
1593 if (!VRegAndVal || VRegAndVal->Value.urem(
BitWidth) == 0)
1599 Amount =
MI.getOpcode() == TargetOpcode::G_FSHL ?
BitWidth - Amount : Amount;
1603 if (ShiftTy.
getSizeInBits() == 64 &&
MI.getOpcode() == TargetOpcode::G_FSHR &&
1610 if (
MI.getOpcode() == TargetOpcode::G_FSHR) {
1612 MI.getOperand(3).setReg(Cast64.getReg(0));
1617 else if (
MI.getOpcode() == TargetOpcode::G_FSHL) {
1618 MIRBuilder.
buildInstr(TargetOpcode::G_FSHR, {
MI.getOperand(0).getReg()},
1619 {
MI.getOperand(1).getReg(),
MI.getOperand(2).getReg(),
1621 MI.eraseFromParent();
1630 Register SrcReg1 =
MI.getOperand(2).getReg();
1631 Register SrcReg2 =
MI.getOperand(3).getReg();
1632 LLT DstTy = MRI.
getType(DstReg);
1633 LLT SrcTy = MRI.
getType(SrcReg1);
1650 MIRBuilder.
buildNot(DstReg, CmpReg);
1652 MI.eraseFromParent();
1662 LLT AmtTy = MRI.
getType(AmtReg);
1668 MI.getOperand(2).setReg(NewAmt.getReg(0));
1673bool AArch64LegalizerInfo::legalizeSmallCMGlobalValue(
1676 assert(
MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
1681 auto &GlobalOp =
MI.getOperand(1);
1683 if (GlobalOp.isSymbol())
1685 const auto* GV = GlobalOp.getGlobal();
1686 if (GV->isThreadLocal())
1689 auto &TM = ST->getTargetLowering()->getTargetMachine();
1690 unsigned OpFlags = ST->ClassifyGlobalReference(GV, TM);
1695 auto Offset = GlobalOp.getOffset();
1700 MRI.
setRegClass(ADRP.getReg(0), &AArch64::GPR64RegClass);
1717 "Should not have folded in an offset for a tagged global!");
1719 .addGlobalAddress(GV, 0x100000000,
1722 MRI.
setRegClass(ADRP.getReg(0), &AArch64::GPR64RegClass);
1725 MIRBuilder.
buildInstr(AArch64::G_ADD_LOW, {DstReg}, {ADRP})
1726 .addGlobalAddress(GV,
Offset,
1728 MI.eraseFromParent();
1737 auto LowerUnaryOp = [&
MI, &MIB](
unsigned Opcode) {
1739 MI.eraseFromParent();
1742 auto LowerBinOp = [&
MI, &MIB](
unsigned Opcode) {
1744 {
MI.getOperand(2),
MI.getOperand(3)});
1745 MI.eraseFromParent();
1748 auto LowerTriOp = [&
MI, &MIB](
unsigned Opcode) {
1750 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4)});
1751 MI.eraseFromParent();
1756 switch (IntrinsicID) {
1757 case Intrinsic::vacopy: {
1758 unsigned PtrSize = ST->isTargetILP32() ? 4 : 8;
1759 unsigned VaListSize =
1760 (ST->isTargetDarwin() || ST->isTargetWindows())
1762 : ST->isTargetILP32() ? 20 : 32;
1770 VaListSize,
Align(PtrSize)));
1774 VaListSize,
Align(PtrSize)));
1775 MI.eraseFromParent();
1778 case Intrinsic::get_dynamic_area_offset: {
1780 MI.eraseFromParent();
1783 case Intrinsic::aarch64_mops_memset_tag: {
1784 assert(
MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
1787 auto &
Value =
MI.getOperand(3);
1789 Value.setReg(ExtValueReg);
1792 case Intrinsic::aarch64_prefetch: {
1793 auto &AddrVal =
MI.getOperand(1);
1795 int64_t IsWrite =
MI.getOperand(2).getImm();
1796 int64_t
Target =
MI.getOperand(3).getImm();
1797 int64_t IsStream =
MI.getOperand(4).getImm();
1798 int64_t IsData =
MI.getOperand(5).getImm();
1800 unsigned PrfOp = (IsWrite << 4) |
1806 MI.eraseFromParent();
1809 case Intrinsic::aarch64_range_prefetch: {
1810 auto &AddrVal =
MI.getOperand(1);
1812 int64_t IsWrite =
MI.getOperand(2).getImm();
1813 int64_t IsStream =
MI.getOperand(3).getImm();
1814 unsigned PrfOp = (IsStream << 2) | IsWrite;
1816 MIB.
buildInstr(AArch64::G_AARCH64_RANGE_PREFETCH)
1819 .
addUse(
MI.getOperand(4).getReg());
1820 MI.eraseFromParent();
1823 case Intrinsic::aarch64_prefetch_ir: {
1824 auto &AddrVal =
MI.getOperand(1);
1826 MI.eraseFromParent();
1829 case Intrinsic::aarch64_neon_uaddv:
1830 case Intrinsic::aarch64_neon_saddv:
1831 case Intrinsic::aarch64_neon_umaxv:
1832 case Intrinsic::aarch64_neon_smaxv:
1833 case Intrinsic::aarch64_neon_uminv:
1834 case Intrinsic::aarch64_neon_sminv: {
1835 bool IsSigned = IntrinsicID == Intrinsic::aarch64_neon_saddv ||
1836 IntrinsicID == Intrinsic::aarch64_neon_smaxv ||
1837 IntrinsicID == Intrinsic::aarch64_neon_sminv;
1839 auto OldDst =
MI.getOperand(0).getReg();
1840 auto OldDstTy = MRI.
getType(OldDst);
1842 if (OldDstTy == NewDstTy)
1848 MI.getOperand(0).setReg(NewDst);
1852 MIB.
buildExtOrTrunc(IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT,
1857 case Intrinsic::aarch64_neon_uaddlp:
1858 case Intrinsic::aarch64_neon_saddlp: {
1859 unsigned Opc = IntrinsicID == Intrinsic::aarch64_neon_uaddlp
1861 : AArch64::G_SADDLP;
1863 MI.eraseFromParent();
1867 case Intrinsic::aarch64_neon_uaddlv:
1868 case Intrinsic::aarch64_neon_saddlv: {
1869 unsigned Opc = IntrinsicID == Intrinsic::aarch64_neon_uaddlv
1871 : AArch64::G_SADDLV;
1898 MI.eraseFromParent();
1902 case Intrinsic::aarch64_neon_smax:
1903 return LowerBinOp(TargetOpcode::G_SMAX);
1904 case Intrinsic::aarch64_neon_smin:
1905 return LowerBinOp(TargetOpcode::G_SMIN);
1906 case Intrinsic::aarch64_neon_umax:
1907 return LowerBinOp(TargetOpcode::G_UMAX);
1908 case Intrinsic::aarch64_neon_umin:
1909 return LowerBinOp(TargetOpcode::G_UMIN);
1910 case Intrinsic::aarch64_neon_fmax:
1911 return LowerBinOp(TargetOpcode::G_FMAXIMUM);
1912 case Intrinsic::aarch64_neon_fmin:
1913 return LowerBinOp(TargetOpcode::G_FMINIMUM);
1914 case Intrinsic::aarch64_neon_fmaxnm:
1915 return LowerBinOp(TargetOpcode::G_FMAXNUM);
1916 case Intrinsic::aarch64_neon_fminnm:
1917 return LowerBinOp(TargetOpcode::G_FMINNUM);
1918 case Intrinsic::aarch64_neon_pmull:
1919 case Intrinsic::aarch64_neon_pmull64:
1920 return LowerBinOp(AArch64::G_PMULL);
1921 case Intrinsic::aarch64_neon_smull:
1922 return LowerBinOp(AArch64::G_SMULL);
1923 case Intrinsic::aarch64_neon_umull:
1924 return LowerBinOp(AArch64::G_UMULL);
1925 case Intrinsic::aarch64_neon_sabd:
1926 return LowerBinOp(TargetOpcode::G_ABDS);
1927 case Intrinsic::aarch64_neon_uabd:
1928 return LowerBinOp(TargetOpcode::G_ABDU);
1929 case Intrinsic::aarch64_neon_uhadd:
1930 return LowerBinOp(TargetOpcode::G_UAVGFLOOR);
1931 case Intrinsic::aarch64_neon_urhadd:
1932 return LowerBinOp(TargetOpcode::G_UAVGCEIL);
1933 case Intrinsic::aarch64_neon_shadd:
1934 return LowerBinOp(TargetOpcode::G_SAVGFLOOR);
1935 case Intrinsic::aarch64_neon_srhadd:
1936 return LowerBinOp(TargetOpcode::G_SAVGCEIL);
1937 case Intrinsic::aarch64_neon_sqshrn: {
1942 {MRI.
getType(
MI.getOperand(2).getReg())},
1943 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1945 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {
MI.getOperand(0)}, {Shr});
1946 MI.eraseFromParent();
1949 case Intrinsic::aarch64_neon_sqshrun: {
1954 {MRI.
getType(
MI.getOperand(2).getReg())},
1955 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1957 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {
MI.getOperand(0)}, {Shr});
1958 MI.eraseFromParent();
1961 case Intrinsic::aarch64_neon_sqrshrn: {
1965 auto Shr = MIB.
buildInstr(AArch64::G_SRSHR_I,
1966 {MRI.
getType(
MI.getOperand(2).getReg())},
1967 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1969 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {
MI.getOperand(0)}, {Shr});
1970 MI.eraseFromParent();
1973 case Intrinsic::aarch64_neon_sqrshrun: {
1977 auto Shr = MIB.
buildInstr(AArch64::G_SRSHR_I,
1978 {MRI.
getType(
MI.getOperand(2).getReg())},
1979 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1981 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {
MI.getOperand(0)}, {Shr});
1982 MI.eraseFromParent();
1985 case Intrinsic::aarch64_neon_uqrshrn: {
1989 auto Shr = MIB.
buildInstr(AArch64::G_URSHR_I,
1990 {MRI.
getType(
MI.getOperand(2).getReg())},
1991 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
1993 MIB.
buildInstr(TargetOpcode::G_TRUNC_USAT_U, {
MI.getOperand(0)}, {Shr});
1994 MI.eraseFromParent();
1997 case Intrinsic::aarch64_neon_uqshrn: {
2002 {MRI.
getType(
MI.getOperand(2).getReg())},
2003 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
2005 MIB.
buildInstr(TargetOpcode::G_TRUNC_USAT_U, {
MI.getOperand(0)}, {Shr});
2006 MI.eraseFromParent();
2009 case Intrinsic::aarch64_neon_sqshlu: {
2015 MIB.
buildInstr(AArch64::G_SQSHLU_I, {
MI.getOperand(0)},
2017 .addImm(ShiftAmount->getSExtValue());
2018 MI.eraseFromParent();
2023 case Intrinsic::aarch64_neon_vsli: {
2025 AArch64::G_SLI, {
MI.getOperand(0)},
2026 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4).getImm()});
2027 MI.eraseFromParent();
2030 case Intrinsic::aarch64_neon_vsri: {
2032 AArch64::G_SRI, {
MI.getOperand(0)},
2033 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4).getImm()});
2034 MI.eraseFromParent();
2037 case Intrinsic::aarch64_neon_abs: {
2039 MIB.
buildInstr(TargetOpcode::G_ABS, {
MI.getOperand(0)}, {
MI.getOperand(2)});
2040 MI.eraseFromParent();
2043 case Intrinsic::aarch64_neon_sqadd: {
2045 return LowerBinOp(TargetOpcode::G_SADDSAT);
2048 case Intrinsic::aarch64_neon_sqsub: {
2050 return LowerBinOp(TargetOpcode::G_SSUBSAT);
2053 case Intrinsic::aarch64_neon_uqadd: {
2055 return LowerBinOp(TargetOpcode::G_UADDSAT);
2058 case Intrinsic::aarch64_neon_uqsub: {
2060 return LowerBinOp(TargetOpcode::G_USUBSAT);
2063 case Intrinsic::aarch64_neon_udot:
2064 return LowerTriOp(AArch64::G_UDOT);
2065 case Intrinsic::aarch64_neon_sdot:
2066 return LowerTriOp(AArch64::G_SDOT);
2067 case Intrinsic::aarch64_neon_usdot:
2068 return LowerTriOp(AArch64::G_USDOT);
2069 case Intrinsic::aarch64_neon_sqxtn:
2070 return LowerUnaryOp(TargetOpcode::G_TRUNC_SSAT_S);
2071 case Intrinsic::aarch64_neon_sqxtun:
2072 return LowerUnaryOp(TargetOpcode::G_TRUNC_SSAT_U);
2073 case Intrinsic::aarch64_neon_uqxtn:
2074 return LowerUnaryOp(TargetOpcode::G_TRUNC_USAT_U);
2075 case Intrinsic::aarch64_neon_fcvtzu:
2076 return LowerUnaryOp(TargetOpcode::G_FPTOUI_SAT);
2077 case Intrinsic::aarch64_neon_fcvtzs:
2078 return LowerUnaryOp(TargetOpcode::G_FPTOSI_SAT);
2080 case Intrinsic::vector_reverse:
2088bool AArch64LegalizerInfo::legalizeShlAshrLshr(
2091 assert(
MI.getOpcode() == TargetOpcode::G_ASHR ||
2092 MI.getOpcode() == TargetOpcode::G_LSHR ||
2093 MI.getOpcode() == TargetOpcode::G_SHL);
2108 MI.getOperand(2).setReg(ExtCst.getReg(0));
2129bool AArch64LegalizerInfo::legalizeLoadStore(
2132 assert(
MI.getOpcode() == TargetOpcode::G_STORE ||
2133 MI.getOpcode() == TargetOpcode::G_LOAD);
2144 const LLT ValTy = MRI.
getType(ValReg);
2149 bool IsLoad =
MI.getOpcode() == TargetOpcode::G_LOAD;
2153 ST->hasLSE2() && ST->hasRCPC3() && (IsLoadAcquire || IsStoreRelease);
2159 Opcode = IsLoad ? AArch64::LDIAPPX : AArch64::STILPX;
2165 assert(ST->hasLSE2() &&
"ldp/stp not single copy atomic without +lse2");
2167 Opcode = IsLoad ? AArch64::LDPXi : AArch64::STPXi;
2170 MachineInstrBuilder NewI;
2172 NewI = MIRBuilder.
buildInstr(Opcode, {s64, s64}, {});
2178 Opcode, {}, {
Split->getOperand(0),
Split->getOperand(1)});
2182 NewI.
addUse(
MI.getOperand(1).getReg());
2194 *ST->getRegBankInfo());
2195 MI.eraseFromParent();
2201 LLVM_DEBUG(
dbgs() <<
"Tried to do custom legalization on wrong load/store");
2207 auto &MMO = **
MI.memoperands_begin();
2210 if (
MI.getOpcode() == TargetOpcode::G_STORE) {
2214 auto NewLoad = MIRBuilder.
buildLoad(NewTy,
MI.getOperand(1), MMO);
2217 MI.eraseFromParent();
2224 MachineFunction &MF = MIRBuilder.
getMF();
2225 Align Alignment(
MI.getOperand(2).getImm());
2227 Register ListPtr =
MI.getOperand(1).getReg();
2229 LLT PtrTy = MRI.
getType(ListPtr);
2239 MachineInstrBuilder DstPtr;
2240 if (Alignment > PtrAlign) {
2244 auto ListTmp = MIRBuilder.
buildPtrAdd(PtrTy,
List, AlignMinus1.getReg(0));
2254 ValTy, std::max(Alignment, PtrAlign)));
2265 MI.eraseFromParent();
2269bool AArch64LegalizerInfo::legalizeBitfieldExtract(
2300 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2312 "Expected src and dst to have the same type!");
2319 auto Add = MIRBuilder.
buildAdd(i64, CTPOP1, CTPOP2);
2322 MI.eraseFromParent();
2326 if (!ST->hasNEON() ||
2327 MI.getMF()->getFunction().hasFnAttribute(Attribute::NoImplicitFloat)) {
2339 assert((Size == 32 || Size == 64 || Size == 128) &&
"Expected only 32, 64, or 128 bit scalars!");
2341 Val = MIRBuilder.buildZExt(i64, Val).getReg(0);
2352 LLT Dt = Ty == LLT::fixed_vector(2, i64) ? LLT::fixed_vector(4, i32) : Ty;
2353 auto Zeros = MIRBuilder.buildConstant(Dt, 0);
2354 auto Ones = MIRBuilder.buildConstant(VTy, 1);
2355 MachineInstrBuilder Sum;
2357 if (Ty == LLT::fixed_vector(2, i64)) {
2359 MIRBuilder.buildInstr(AArch64::G_UDOT, {Dt}, {Zeros, Ones, CTPOP});
2360 Sum = MIRBuilder.buildInstr(AArch64::G_UADDLP, {Ty}, {UDOT});
2362 Sum = MIRBuilder.
buildInstr(AArch64::G_UDOT, {Dt}, {Zeros, Ones,
CTPOP});
2364 Sum = MIRBuilder.
buildInstr(AArch64::G_UDOT, {Dt}, {Zeros, Ones,
CTPOP});
2370 MI.eraseFromParent();
2378 Opc = Intrinsic::aarch64_neon_uaddlv;
2379 HAddTys.push_back(i32);
2381 Opc = Intrinsic::aarch64_neon_uaddlp;
2384 Opc = Intrinsic::aarch64_neon_uaddlp;
2388 Opc = Intrinsic::aarch64_neon_uaddlp;
2393 Opc = Intrinsic::aarch64_neon_uaddlp;
2396 Opc = Intrinsic::aarch64_neon_uaddlp;
2402 for (
LLT HTy : HAddTys) {
2412 MI.eraseFromParent();
2416bool AArch64LegalizerInfo::legalizeAtomicCmpxchg128(
2418 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2420 auto Addr =
MI.getOperand(1).getReg();
2421 auto DesiredI = MIRBuilder.
buildUnmerge({i64, i64},
MI.getOperand(2));
2422 auto NewI = MIRBuilder.
buildUnmerge({i64, i64},
MI.getOperand(3));
2426 MachineInstrBuilder CAS;
2437 auto Ordering = (*
MI.memoperands_begin())->getMergedOrdering();
2441 Opcode = AArch64::CASPAX;
2444 Opcode = AArch64::CASPLX;
2448 Opcode = AArch64::CASPALX;
2451 Opcode = AArch64::CASPX;
2459 MIRBuilder.
buildInstr(TargetOpcode::REG_SEQUENCE, {CASDesired}, {})
2460 .addUse(DesiredI->getOperand(0).getReg())
2462 .
addUse(DesiredI->getOperand(1).getReg())
2463 .
addImm(AArch64::subo64);
2464 MIRBuilder.
buildInstr(TargetOpcode::REG_SEQUENCE, {CASNew}, {})
2468 .
addImm(AArch64::subo64);
2470 CAS = MIRBuilder.
buildInstr(Opcode, {CASDst}, {CASDesired, CASNew, Addr});
2478 auto Ordering = (*
MI.memoperands_begin())->getMergedOrdering();
2482 Opcode = AArch64::CMP_SWAP_128_ACQUIRE;
2485 Opcode = AArch64::CMP_SWAP_128_RELEASE;
2489 Opcode = AArch64::CMP_SWAP_128;
2492 Opcode = AArch64::CMP_SWAP_128_MONOTONIC;
2497 CAS = MIRBuilder.
buildInstr(Opcode, {DstLo, DstHi, Scratch},
2498 {Addr, DesiredI->getOperand(0),
2499 DesiredI->getOperand(1), NewI->
getOperand(0),
2506 *ST->getRegBankInfo());
2509 MI.eraseFromParent();
2515 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2516 MachineRegisterInfo &MRI = *MIRBuilder.
getMRI();
2517 LLT Ty = MRI.
getType(
MI.getOperand(1).getReg());
2519 MIRBuilder.
buildCTLZ(
MI.getOperand(0).getReg(), BitReverse);
2520 MI.eraseFromParent();
2526 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2529 if (
MI.getOpcode() == TargetOpcode::G_MEMSET) {
2532 auto &
Value =
MI.getOperand(1);
2535 Value.setReg(ExtValueReg);
2542bool AArch64LegalizerInfo::legalizeExtractVectorElt(
2556bool AArch64LegalizerInfo::legalizeDynStackAlloc(
2558 MachineFunction &MF = *
MI.getParent()->getParent();
2559 MachineIRBuilder &MIRBuilder = Helper.
MIRBuilder;
2560 MachineRegisterInfo &MRI = *MIRBuilder.
getMRI();
2572 Register AllocSize =
MI.getOperand(1).getReg();
2576 "Unexpected type for dynamic alloca");
2578 "Unexpected type for dynamic alloca");
2586 MIRBuilder.
buildInstr(AArch64::PROBED_STACKALLOC_DYN, {}, {SPTmp});
2587 MRI.
setRegClass(NewMI.getReg(0), &AArch64::GPR64commonRegClass);
2588 MIRBuilder.
setInsertPt(*NewMI->getParent(), NewMI);
2591 MI.eraseFromParent();
2598 auto &AddrVal =
MI.getOperand(0);
2600 int64_t IsWrite =
MI.getOperand(1).getImm();
2601 int64_t Locality =
MI.getOperand(2).getImm();
2602 int64_t
IsData =
MI.getOperand(3).getImm();
2604 bool IsStream = Locality == 0;
2605 if (Locality != 0) {
2606 assert(Locality <= 3 &&
"Prefetch locality out-of-range");
2610 Locality = 3 - Locality;
2613 unsigned PrfOp = (IsWrite << 4) | (!IsData << 3) | (Locality << 1) | IsStream;
2616 MI.eraseFromParent();
2620bool AArch64LegalizerInfo::legalizeConcatVectors(
2627 LLT DstTy = MRI.
getType(DstReg);
2630 unsigned WideEltSize =
2637 for (
unsigned I = 0;
I <
Concat.getNumSources(); ++
I) {
2644 MI.eraseFromParent();
2651 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
2653 "Expected a power of 2 elements");
2657 LLT v2s16 = DstTy.changeElementCount(2);
2658 LLT v4s16 = DstTy.changeElementCount(4);
2670 int StepSize = ElemCount % 4 ? 2 : 4;
2677 for (
unsigned i = 0; i < ElemCount / 2; ++i)
2684 for (
auto SrcReg : RegsToUnmergeTo) {
2686 MIRBuilder.
buildInstr(AArch64::G_FPTRUNC_ODD, {v2s32}, {SrcReg})
2694 for (
unsigned LoopIter = 0; LoopIter < ElemCount / StepSize; ++LoopIter) {
2695 if (StepSize == 4) {
2699 {v4s32}, {TruncOddDstRegs[
Index++], TruncOddDstRegs[
Index++]})
2711 if (RegsToMerge.
size() == 1) {
2713 MI.eraseFromParent();
2720 MI.eraseFromParent();
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
static constexpr int Concat[]
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.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
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.
LLT getScalarType() const
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.
static constexpr LLT float128()
Get a 128-bit IEEE quad value.
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 ElementCount getElementCount() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
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.
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
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.
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 buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
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 MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
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...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
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.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
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.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
AtomicOrdering
Atomic ordering for LLVM's memory model.
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,...