107 std::initializer_list<LLT> PackedVectorAllTypeList = {
113 std::initializer_list<LLT> ScalarAndPtrTypesList = {s8, s16, s32, s64, p0};
117 const TargetMachine &TM = ST.getTargetLowering()->getTargetMachine();
120 if (!ST.hasNEON() || !ST.hasFPARMv8())
125 const bool HasFP16 = ST.hasFullFP16();
126 const bool HasCSSC = ST.hasCSSC();
127 const bool HasRCPC3 = ST.hasRCPC3();
128 const bool HasSVE = ST.hasSVE();
131 {G_IMPLICIT_DEF, G_FREEZE, G_CONSTANT_FOLD_BARRIER})
132 .legalFor({p0, s8, s16, s32, s64, s128})
133 .legalFor({v2s8, v4s8, v8s8, v16s8, v2s16, v4s16, v8s16, v2s32, v4s32,
135 .widenScalarToNextPow2(0)
148 .legalFor(PackedVectorAllTypeList)
163 .widenScalarToNextPow2(0)
168 .maxScalarIf(
typeInSet(0, {s64, p0}), 1, s32);
173 .widenScalarToNextPow2(1)
178 .maxScalarIf(
typeInSet(1, {s64, p0}), 0, s32)
179 .maxScalarIf(
typeInSet(1, {s128}), 0, s64);
182 .legalFor({i32, i64, v8i8, v16i8, v4i16, v8i16, v2i32, v4i32, v2i64})
183 .legalFor(HasSVE, {nxv16i8, nxv8i16, nxv4i32, nxv2i64})
184 .widenScalarToNextPow2(0)
192 return Query.
Types[0].getNumElements() <= 2;
197 return Query.
Types[0].getNumElements() <= 4;
202 return Query.
Types[0].getNumElements() <= 16;
209 .
legalFor({i32, i64, v8i8, v16i8, v4i16, v8i16, v2i32, v4i32, v2i64})
210 .widenScalarToNextPow2(0)
218 return Query.
Types[0].getNumElements() <= 2;
223 return Query.
Types[0].getNumElements() <= 4;
228 return Query.
Types[0].getNumElements() <= 16;
236 const auto &SrcTy = Query.
Types[0];
237 const auto &AmtTy = Query.
Types[1];
238 return !SrcTy.isVector() && SrcTy.getSizeInBits() == 32 &&
239 AmtTy.getSizeInBits() == 32;
253 .widenScalarToNextPow2(1)
268 .
legalFor({{p0, i64}, {v2p0, v2i64}})
269 .clampScalarOrElt(1, s64, s64)
275 .legalFor({i32, i64})
277 .clampScalar(0, s32, s64)
282 .lowerFor({i8, i16, i32, i64, v2i32, v4i32, v2i64})
291 .widenScalarToNextPow2(0, 32)
296 .legalFor({i64, v16i8, v8i16, v4i32})
297 .clampMaxNumElements(0, s8, 16)
303 {G_SMULFIX, G_UMULFIX, G_SMULFIXSAT, G_UMULFIXSAT})
307 .legalFor({v8i8, v16i8, v4i16, v8i16, v2i32, v4i32})
308 .legalFor(HasCSSC, {i32, i64})
309 .minScalar(HasCSSC, 0, s32)
318 .legalFor({v16i8, v8i16, v4i32, v2i64, v2p0, v8i8, v4i16, v2i32})
322 return SrcTy.isScalar() && SrcTy.getSizeInBits() < 128;
326 [=](
const LegalityQuery &Query) {
return std::make_pair(0, v4i16); })
329 [=](
const LegalityQuery &Query) {
return std::make_pair(0, v2i32); })
330 .clampNumElements(0, v8s8, v16s8)
338 {G_ABDS, G_ABDU, G_UAVGFLOOR, G_UAVGCEIL, G_SAVGFLOOR, G_SAVGCEIL})
339 .legalFor({v8i8, v16i8, v4i16, v8i16, v2i32, v4i32})
343 {G_SADDE, G_SSUBE, G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_UADDO, G_USUBO})
344 .legalFor({{i32, i32}, {i64, i32}})
345 .clampScalar(0, s32, s64)
351 .customFor({{i32, i32}, {i32, i64}, {i64, i64}})
357 return Q.
Types[0].isScalar() && Q.
Types[1].getScalarSizeInBits() < 64;
363 .customFor({{s32, s32}, {s64, s64}});
367 .
legalFor(HasCSSC, {{i32, i32}, {i64, i64}})
368 .legalFor({{v8i8, v8i8}, {v16i8, v16i8}})
369 .customFor(!HasCSSC, {{s32, s32}, {s64, s64}})
370 .customFor({{s128, s128},
376 .clampScalar(0, s32, s128)
389 .legalFor({{i32, i32},
397 .widenScalarToNextPow2(1, 32)
417 .customFor(!HasCSSC, {s32, s64});
423 .widenScalarToNextPow2(0, 32)
437 .
legalFor({i32, i64, v4i16, v8i16, v2i32, v4i32, v2i64})
446 .legalFor({v8i8, v16i8, v4i16, v8i16, v2i32, v4i32, v2i64})
447 .legalFor(HasSVE, {nxv16i8, nxv8i16, nxv4i32, nxv2i64})
448 .clampNumElements(0, v8s8, v16s8)
457 {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMA, G_FSQRT, G_FMAXNUM, G_FMINNUM,
458 G_FMAXIMUM, G_FMINIMUM, G_FCEIL, G_FFLOOR, G_FRINT, G_FNEARBYINT,
459 G_INTRINSIC_TRUNC, G_INTRINSIC_ROUND, G_INTRINSIC_ROUNDEVEN})
460 .legalFor({f32, f64, v2f32, v4f32, v2f64})
461 .legalFor(HasFP16, {f16, v4f16, v8f16})
466 return (!HasFP16 && Q.
Types[0].getScalarType().isFloat16()) ||
467 Q.
Types[0].getScalarType().isBFloat16();
470 .clampNumElements(0, v4s16, v8s16)
476 .legalFor({f32, f64, v2f32, v4f32, v2f64})
477 .legalFor(HasFP16, {f16, bf16, v4f16, v4bf16, v8f16, v8bf16})
484 .
lowerFor({f16, bf16, v4f16, v4bf16, v8f16, v8bf16});
487 G_FLOG10, G_FTAN, G_FEXP, G_FEXP2, G_FEXP10,
488 G_FACOS, G_FASIN, G_FATAN, G_FATAN2, G_FCOSH,
489 G_FSINH, G_FTANH, G_FMODF})
490 .libcallFor({f32, f64, f128})
494 .libcallFor({{f32, i32}, {f64, i32}, {f128, i32}})
499 .legalFor({{i32, f32}, {i32, f64}, {i64, f32}, {i64, f64}})
500 .legalFor(HasFP16, {{i32, f16}, {i64, f16}})
505 .legalFor({{i64, f32}, {i64, f64}})
506 .legalFor(HasFP16, {{i64, f16}})
524 for (
unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {
527 if (
Op == G_SEXTLOAD)
532 .legalForTypesWithMemDesc({{s32, p0, s8, 8},
540 {v2s32, p0, s64, 8}})
541 .widenScalarToNextPow2(0)
542 .clampScalar(0, s32, s64)
545 .unsupportedIfMemSizeNotPow2()
557 return HasRCPC3 && Query.
Types[0] == s128 &&
561 return Query.
Types[0] == s128 &&
564 .legalForTypesWithMemDesc({{s8, p0, s8, 8},
571 {v16s8, p0, s128, 8},
573 {v8s16, p0, s128, 8},
575 {v4s32, p0, s128, 8},
576 {v2s64, p0, s128, 8}})
578 .legalForTypesWithMemDesc(
579 {{s32, p0, s8, 8}, {s32, p0, s16, 8}, {s64, p0, s32, 8}})
580 .legalForTypesWithMemDesc({
582 {nxv16s8, p0, nxv16s8, 8},
583 {nxv8s16, p0, nxv8s16, 8},
584 {nxv4s32, p0, nxv4s32, 8},
585 {nxv2s64, p0, nxv2s64, 8},
587 .widenScalarToNextPow2(0, 8)
598 return Query.
Types[0].isScalar() &&
600 Query.
Types[0].getSizeInBits() > 32;
609 .customIf(IsPtrVecPred)
615 return HasRCPC3 && Query.
Types[0] == s128 &&
619 return Query.
Types[0] == s128 &&
627 {{s8, p0, s8, 8}, {s16, p0, s8, 8},
630 {s16, p0, s16, 8}, {s32, p0, s16, 8},
632 {s32, p0, s8, 8}, {s32, p0, s16, 8}, {s32, p0, s32, 8},
633 {s64, p0, s64, 8}, {s64, p0, s32, 8},
634 {p0, p0, s64, 8}, {s128, p0, s128, 8}, {v16s8, p0, s128, 8},
635 {v8s8, p0, s64, 8}, {v4s16, p0, s64, 8}, {v8s16, p0, s128, 8},
636 {v2s32, p0, s64, 8}, {v4s32, p0, s128, 8}, {v2s64, p0, s128, 8}})
637 .legalForTypesWithMemDesc({
642 {nxv16s8, p0, nxv16s8, 8},
643 {nxv8s16, p0, nxv8s16, 8},
644 {nxv4s32, p0, nxv4s32, 8},
645 {nxv2s64, p0, nxv2s64, 8},
647 .clampScalar(0, s8, s64)
650 return Query.
Types[0].isScalar() &&
654 .clampMaxNumElements(0, s8, 16)
663 return Query.
Types[0].getSizeInBits() ==
664 Query.
MMODescrs[0].MemoryTy.getSizeInBits();
670 .customIf(IsPtrVecPred)
688 {p0, v16s8, v16s8, 8},
689 {p0, v4s16, v4s16, 8},
690 {p0, v8s16, v8s16, 8},
691 {p0, v2s32, v2s32, 8},
692 {p0, v4s32, v4s32, 8},
693 {p0, v2s64, v2s64, 8},
699 auto IndexedLoadBasicPred = [=](
const LegalityQuery &Query) {
727 return MemTy == s8 || MemTy == s16;
729 return MemTy == s8 || MemTy == s16 || MemTy == s32;
737 .widenScalarToNextPow2(0)
744 .
legalFor({{i32, i32}, {i32, i64}, {i32, p0}})
754 return Ty.isVector() && !SrcTy.isPointerVector() &&
755 Ty.getElementType() != SrcTy.getElementType();
763 return Query.
Types[1].isPointerVector();
780 .legalFor(HasFP16, {{i32, f16}, {v4i16, v4f16}, {v8i16, v8f16}})
785 return (!HasFP16 && Q.
Types[1].getScalarType().isFloat16()) ||
786 Q.
Types[1].getScalarType().isBFloat16();
794 return Ty.isVector() && !SrcTy.isPointerVector() &&
795 Ty.getElementType() != SrcTy.getElementType();
798 .clampNumElements(1, v4s16, v8s16)
806 unsigned DstSize = Query.
Types[0].getSizeInBits();
809 if (Query.
Types[0].isVector())
812 if (DstSize < 8 || DstSize >= 128 || !
isPowerOf2_32(DstSize))
820 unsigned SrcSize = SrcTy.getSizeInBits();
827 .legalIf(ExtLegalFunc)
828 .
legalFor({{v8s16, v8s8}, {v4s32, v4s16}, {v2s64, v2s32}})
829 .clampScalar(0, s64, s64)
836 return (Query.
Types[0].getScalarSizeInBits() >
837 Query.
Types[1].getScalarSizeInBits() * 2) &&
838 Query.
Types[0].isVector() &&
839 (Query.
Types[1].getScalarSizeInBits() == 8 ||
840 Query.
Types[1].getScalarSizeInBits() == 16);
842 .clampMinNumElements(1, s8, 8)
847 .
legalFor({{v8s8, v8s16}, {v4s16, v4s32}, {v2s32, v2s64}})
858 return DstTy.
isVector() && SrcTy.getSizeInBits() > 128 &&
861 .clampMinNumElements(0, s8, 8)
866 .legalFor({{v8i8, v8i16}, {v4i16, v4i32}, {v2i32, v2i64}})
867 .clampNumElements(0, v8s8, v8s8)
873 .
legalFor({i32, i64, v8i8, v16i8, v4i16, v8i16, v2i32, v4i32, v2i64})
884 {{f16, f32}, {f16, f64}, {f32, f64}, {v4f16, v4f32}, {v2f32, v2f64}})
885 .legalFor(ST.hasBF16(), {{bf16, f32}, {v4bf16, v4f32}})
886 .libcallFor({{f16, f128}, {f32, f128}, {f64, f128}})
894 .lowerFor({{bf16, f32}, {v4bf16, v4f32}})
896 .clampNumElements(1, v4s32, v4s32)
900 getActionDefinitionsBuilder(G_FPEXT)
908 .libcallFor({{f128, f64}, {f128, f32}, {f128, f16}})
919 .clampNumElements(0, v4s32, v4s32)
924 getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
925 .legalFor({{i32, f32},
933 {{i32, f16}, {i64, f16}, {v4i16, v4f16}, {v8i16, v8f16}})
940 return Query.
Types[1] == f16 && Query.
Types[0].getSizeInBits() > 64;
948 return (!HasFP16 && Query.
Types[1].getScalarType().isFloat16()) ||
949 Query.
Types[1].getScalarType().isBFloat16();
954 return Query.
Types[0].getScalarSizeInBits() <= 64 &&
955 Query.
Types[0].getScalarSizeInBits() >
956 Query.
Types[1].getScalarSizeInBits();
961 return Query.
Types[1].getScalarSizeInBits() <= 64 &&
962 Query.
Types[0].getScalarSizeInBits() <
963 Query.
Types[1].getScalarSizeInBits();
966 .clampNumElements(0, v4s16, v8s16)
970 {{i32, f128}, {i64, f128}, {i128, f128}, {i128, f32}, {i128, f64}});
972 getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
973 .legalFor({{i32, f32},
982 {{i16, f16}, {i32, f16}, {i64, f16}, {v4i16, v4f16}, {v8i16, v8f16}})
994 return (!HasFP16 && Query.
Types[1].getScalarType().isFloat16()) ||
995 Query.
Types[1].getScalarType().isBFloat16();
1000 unsigned ITySize = Query.
Types[0].getScalarSizeInBits();
1001 return (ITySize == 16 || ITySize == 32 || ITySize == 64) &&
1002 ITySize > Query.
Types[1].getScalarSizeInBits();
1007 unsigned FTySize = Query.
Types[1].getScalarSizeInBits();
1008 return (FTySize == 16 || FTySize == 32 || FTySize == 64) &&
1009 Query.
Types[0].getScalarSizeInBits() < FTySize;
1017 getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
1018 .legalFor({{f32, i32},
1026 {{f16, i32}, {f16, i64}, {v4f16, v4i16}, {v8f16, v8i16}})
1028 return Query.
Types[0].getScalarType().isBFloat16();
1036 return Query.
Types[1].isVector() &&
1037 Query.
Types[1].getScalarSizeInBits() == 64 &&
1038 Query.
Types[0].getScalarSizeInBits() == 16;
1040 .widenScalarOrEltToNextPow2OrMinSize(0, HasFP16 ? 16 : 32)
1044 return Query.
Types[0].getScalarSizeInBits() == 32 &&
1045 Query.
Types[1].getScalarSizeInBits() == 64;
1050 return Query.
Types[1].getScalarSizeInBits() <= 64 &&
1051 Query.
Types[0].getScalarSizeInBits() <
1052 Query.
Types[1].getScalarSizeInBits();
1057 return Query.
Types[0].getScalarSizeInBits() <= 64 &&
1058 Query.
Types[0].getScalarSizeInBits() >
1059 Query.
Types[1].getScalarSizeInBits();
1062 .clampNumElements(0, v4s16, v8s16)
1074 getActionDefinitionsBuilder(G_BRCOND)
1076 .clampScalar(0, s32, s32);
1077 getActionDefinitionsBuilder(G_BRINDIRECT).
legalFor({p0});
1079 getActionDefinitionsBuilder(G_SELECT)
1080 .
legalFor({{s32, s32}, {s64, s32}, {p0, s32}})
1081 .widenScalarToNextPow2(0)
1089 getActionDefinitionsBuilder(G_FRAME_INDEX).
legalFor({p0});
1092 getActionDefinitionsBuilder(G_GLOBAL_VALUE).
custom();
1094 getActionDefinitionsBuilder(G_GLOBAL_VALUE).
legalFor({p0});
1096 getActionDefinitionsBuilder(G_PTRAUTH_GLOBAL_VALUE)
1099 getActionDefinitionsBuilder(G_PTRTOINT)
1100 .
legalFor({{i64, p0}, {v2i64, v2p0}})
1101 .widenScalarToNextPow2(0, 64)
1105 getActionDefinitionsBuilder(G_INTTOPTR)
1107 return Query.
Types[0].getSizeInBits() != Query.
Types[1].getSizeInBits();
1109 .legalFor({{p0, i64}, {v2p0, v2i64}})
1110 .clampMaxNumElements(1, s64, 2);
1114 getActionDefinitionsBuilder(G_BITCAST)
1117 .legalForCartesianProduct({s32, v2s16, v4s8})
1118 .legalForCartesianProduct({s64, v8s8, v4s16, v2s32})
1119 .legalForCartesianProduct({s128, v16s8, v8s16, v4s32, v2s64, v2p0})
1128 return Query.
Types[0].isVector() != Query.
Types[1].isVector();
1146 getActionDefinitionsBuilder(G_VASTART).
legalFor({p0});
1150 getActionDefinitionsBuilder(G_VAARG)
1152 .clampScalar(0, s8, s64)
1155 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG_WITH_SUCCESS)
1159 bool UseOutlineAtomics =
ST.outlineAtomics() && !
ST.hasLSE();
1161 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG)
1162 .legalFor(!UseOutlineAtomics, {{s32, p0}, {s64, p0}})
1163 .customFor(!UseOutlineAtomics, {{s128, p0}})
1164 .libcallFor(UseOutlineAtomics,
1165 {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}, {s128, p0}})
1166 .clampScalar(0, s32, s64);
1168 getActionDefinitionsBuilder({G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD,
1169 G_ATOMICRMW_SUB, G_ATOMICRMW_AND, G_ATOMICRMW_OR,
1171 .legalFor(!UseOutlineAtomics, {{s32, p0}, {s64, p0}})
1172 .libcallFor(UseOutlineAtomics,
1173 {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
1174 .clampScalar(0, s32, s64);
1178 getActionDefinitionsBuilder(
1179 {G_ATOMICRMW_MIN, G_ATOMICRMW_MAX, G_ATOMICRMW_UMIN, G_ATOMICRMW_UMAX})
1181 .clampScalar(0, s32, s64);
1183 getActionDefinitionsBuilder(G_BLOCK_ADDR).legalFor({p0});
1186 for (
unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
1187 unsigned BigTyIdx =
Op == G_MERGE_VALUES ? 0 : 1;
1188 unsigned LitTyIdx =
Op == G_MERGE_VALUES ? 1 : 0;
1189 getActionDefinitionsBuilder(
Op)
1190 .widenScalarToNextPow2(LitTyIdx, 8)
1193 const LLT BigTy = Q.
Types[BigTyIdx];
1197 .widenScalarToNextPow2(BigTyIdx, 32)
1198 .clampScalar(LitTyIdx, s8, s64)
1199 .clampScalar(BigTyIdx, s32, s128)
1201 switch (Q.
Types[BigTyIdx].getSizeInBits()) {
1209 switch (Q.
Types[LitTyIdx].getSizeInBits()) {
1222 getActionDefinitionsBuilder(G_EXTRACT_VECTOR_ELT)
1223 .legalFor(HasSVE, {{s16, nxv16s8, s64},
1224 {s16, nxv8s16, s64},
1225 {s32, nxv4s32, s64},
1226 {s64, nxv2s64, s64}})
1228 const LLT &EltTy = Query.
Types[1].getElementType();
1229 if (Query.
Types[1].isScalableVector())
1231 return Query.
Types[0] != EltTy;
1236 return VecTy == v8s8 || VecTy == v16s8 || VecTy == v2s16 ||
1237 VecTy == v4s16 || VecTy == v8s16 || VecTy == v2s32 ||
1238 VecTy == v4s32 || VecTy == v2s64 || VecTy == v2p0;
1244 return Query.
Types[1].isFixedVector() &&
1245 Query.
Types[1].getNumElements() <= 2;
1250 return Query.
Types[1].isFixedVector() &&
1251 Query.
Types[1].getNumElements() <= 4;
1256 return Query.
Types[1].isFixedVector() &&
1257 Query.
Types[1].getNumElements() <= 8;
1262 return Query.
Types[1].isFixedVector() &&
1263 Query.
Types[1].getNumElements() <= 16;
1266 .minScalarOrElt(0, s8)
1267 .moreElementsToNextPow2(1)
1268 .clampMaxNumElements(1, s64, 2)
1269 .clampMaxNumElements(1, s32, 4)
1270 .clampMaxNumElements(1, s16, 8)
1271 .clampMaxNumElements(1, s8, 16)
1272 .clampMaxNumElements(1, p0, 2)
1275 getActionDefinitionsBuilder(G_INSERT_VECTOR_ELT)
1277 typeInSet(0, {v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64, v2p0}))
1278 .legalFor(HasSVE, {{nxv16s8, s32, s64},
1279 {nxv8s16, s32, s64},
1280 {nxv4s32, s32, s64},
1281 {nxv2s64, s64, s64}})
1283 .widenVectorEltsToVectorMinSize(0, 64)
1284 .clampNumElements(0, v8s8, v16s8)
1285 .clampNumElements(0, v4s16, v8s16)
1286 .clampNumElements(0, v2s32, v4s32)
1287 .clampMaxNumElements(0, s64, 2)
1288 .clampMaxNumElements(0, p0, 2)
1291 getActionDefinitionsBuilder(G_BUILD_VECTOR)
1292 .legalFor({{v8s8, s8},
1300 .clampNumElements(0, v4s32, v4s32)
1301 .clampNumElements(0, v2s64, v2s64)
1302 .minScalarOrElt(0, s8)
1303 .widenVectorEltsToVectorMinSize(0, 64)
1304 .widenScalarOrEltToNextPow2(0)
1305 .minScalarSameAs(1, 0);
1307 getActionDefinitionsBuilder(G_BUILD_VECTOR_TRUNC).lower();
1309 getActionDefinitionsBuilder(G_SPLAT_VECTOR)
1310 .legalFor({{v8s8, s8},
1323 getActionDefinitionsBuilder(G_SHUFFLE_VECTOR)
1332 {v8s8, v16s8, v4s16, v8s16, v2s32, v4s32, v2s64}, DstTy);
1336 return Query.
Types[0].getNumElements() >
1337 Query.
Types[1].getNumElements();
1343 return Query.
Types[0].getNumElements() <
1344 Query.
Types[1].getNumElements();
1347 .widenScalarOrEltToNextPow2OrMinSize(0, 8)
1348 .clampNumElements(0, v8s8, v16s8)
1349 .clampNumElements(0, v4s16, v8s16)
1350 .clampNumElements(0, v4s32, v4s32)
1351 .clampNumElements(0, v2s64, v2s64)
1360 getActionDefinitionsBuilder(G_CONCAT_VECTORS)
1361 .legalFor({{v16s8, v8s8}, {v8s16, v4s16}, {v4s32, v2s32}})
1363 return Query.
Types[0].isFixedVector() &&
1364 Query.
Types[0].getScalarSizeInBits() < 8;
1368 return Query.
Types[0].isFixedVector() &&
1369 Query.
Types[1].isFixedVector() &&
1370 Query.
Types[0].getScalarSizeInBits() >= 8 &&
1372 Query.
Types[0].getSizeInBits() <= 128 &&
1373 Query.
Types[1].getSizeInBits() <= 64;
1385 getActionDefinitionsBuilder(G_EXTRACT_SUBVECTOR)
1386 .legalFor({{v8s8, v16s8}, {v4s16, v8s16}, {v2s32, v4s32}})
1388 .clampMaxNumElements(0, s8, 16)
1389 .clampMaxNumElements(0, s16, 8)
1390 .clampMaxNumElements(0, s32, 4)
1391 .clampNumElements(1, v8s8, v16s8)
1392 .clampNumElements(1, v4s16, v8s16)
1393 .clampNumElements(1, v2s32, v4s32)
1398 getActionDefinitionsBuilder(G_SPLAT_VECTOR)
1399 .legalFor(HasSVE, {{nxv4s32, s32}, {nxv2s64, s64}});
1401 getActionDefinitionsBuilder(G_JUMP_TABLE).legalFor({p0});
1403 getActionDefinitionsBuilder(G_BRJT).legalFor({{p0, s64}});
1405 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP, G_UBSANTRAP}).alwaysLegal();
1407 getActionDefinitionsBuilder(G_DYN_STACKALLOC).custom();
1409 getActionDefinitionsBuilder({G_STACKSAVE, G_STACKRESTORE}).
lower();
1414 getActionDefinitionsBuilder(G_BZERO).unsupported();
1416 getActionDefinitionsBuilder(G_MEMSET)
1417 .legalForCartesianProduct({p0}, {s64}, {s64})
1418 .customForCartesianProduct({p0}, {s8}, {s64})
1421 getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE})
1422 .legalForCartesianProduct({p0}, {p0}, {s64})
1426 getActionDefinitionsBuilder(G_MEMCPY_INLINE)
1427 .legalForCartesianProduct({p0}, {p0}, {s64});
1429 getActionDefinitionsBuilder(G_MEMSET_INLINE)
1430 .legalForCartesianProduct({p0}, {s64}, {s64})
1431 .customForCartesianProduct({p0}, {s8}, {s64});
1433 getActionDefinitionsBuilder({G_BZERO, G_MEMCPY, G_MEMMOVE, G_MEMSET})
1440 getActionDefinitionsBuilder(G_VECREDUCE_FADD)
1441 .legalFor({{f32, v2f32}, {f32, v4f32}, {f64, v2f64}})
1442 .legalFor(HasFP16, {{f16, v4f16}, {f16, v8f16}})
1445 return (!HasFP16 && Query.
Types[0].getScalarType().isFloat16()) ||
1446 Query.
Types[0].getScalarType().isBFloat16();
1449 .clampMaxNumElements(1, s64, 2)
1450 .clampMaxNumElements(1, s32, 4)
1451 .clampMaxNumElements(1, s16, 8)
1452 .moreElementsToNextPow2(1)
1459 getActionDefinitionsBuilder(G_VECREDUCE_FMUL)
1462 return (!HasFP16 && Query.
Types[0].getScalarType().isFloat16()) ||
1463 Query.
Types[0].getScalarType().isBFloat16();
1466 .clampMaxNumElements(1, s64, 2)
1467 .clampMaxNumElements(1, s32, 4)
1468 .clampMaxNumElements(1, s16, 8)
1469 .clampMaxNumElements(1, s32, 2)
1470 .clampMaxNumElements(1, s16, 4)
1474 getActionDefinitionsBuilder({G_VECREDUCE_SEQ_FADD, G_VECREDUCE_SEQ_FMUL})
1478 getActionDefinitionsBuilder(G_VECREDUCE_ADD)
1479 .legalFor({{i8, v8i8},
1487 .clampMaxNumElements(1, s64, 2)
1488 .clampMaxNumElements(1, s32, 4)
1489 .clampMaxNumElements(1, s16, 8)
1490 .clampMaxNumElements(1, s8, 16)
1491 .widenVectorEltsToVectorMinSize(1, 64)
1494 getActionDefinitionsBuilder({G_VECREDUCE_FMIN, G_VECREDUCE_FMAX,
1495 G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM})
1496 .legalFor({{f32, v2f32}, {f32, v4f32}, {f64, v2f64}})
1497 .legalFor(HasFP16, {{f16, v4f16}, {f16, v8f16}})
1500 return (!HasFP16 && Query.
Types[0].getScalarType().isFloat16()) ||
1501 Query.
Types[0].getScalarType().isBFloat16();
1504 .clampMaxNumElements(1, s64, 2)
1505 .clampMaxNumElements(1, s32, 4)
1506 .clampMaxNumElements(1, s16, 8)
1510 getActionDefinitionsBuilder(G_VECREDUCE_MUL)
1511 .clampMaxNumElements(1, s32, 2)
1512 .clampMaxNumElements(1, s16, 4)
1513 .clampMaxNumElements(1, s8, 8)
1517 getActionDefinitionsBuilder(
1518 {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX})
1519 .legalFor({{i8, v8i8},
1527 return Query.
Types[1].isVector() &&
1528 Query.
Types[1].getElementType() != s8 &&
1529 Query.
Types[1].getNumElements() & 1;
1532 .clampMaxNumElements(1, s64, 2)
1533 .clampMaxNumElements(1, s32, 4)
1534 .clampMaxNumElements(1, s16, 8)
1535 .clampMaxNumElements(1, s8, 16)
1539 getActionDefinitionsBuilder(
1540 {G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
1556 return std::make_pair(1, SrcTy.
divide(2));
1562 getActionDefinitionsBuilder(G_VECTOR_COMPRESS).lower();
1565 getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV,
1566 G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})
1569 getActionDefinitionsBuilder({G_GET_ROUNDING, G_SET_ROUNDING})
1572 getActionDefinitionsBuilder(G_IS_FPCLASS).lower();
1574 getActionDefinitionsBuilder(G_PREFETCH).custom();
1576 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).
lower();
1578 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS})
1580 getActionDefinitionsBuilder(G_FENCE).alwaysLegal();
1581 getActionDefinitionsBuilder(G_INVOKE_REGION_START).alwaysLegal();
1833 auto LowerUnaryOp = [&
MI, &MIB](
unsigned Opcode) {
1835 MI.eraseFromParent();
1838 auto LowerBinOp = [&
MI, &MIB](
unsigned Opcode) {
1840 {
MI.getOperand(2),
MI.getOperand(3)});
1841 MI.eraseFromParent();
1844 auto LowerTriOp = [&
MI, &MIB](
unsigned Opcode) {
1846 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4)});
1847 MI.eraseFromParent();
1852 switch (IntrinsicID) {
1853 case Intrinsic::vacopy: {
1856 unsigned PtrSize =
DL.getPointerSize();
1857 unsigned VaListSize = ST->getTargetLowering()->getVaListSizeInBits(
DL) / 8;
1863 VaListSize,
Align(PtrSize)));
1867 VaListSize,
Align(PtrSize)));
1868 MI.eraseFromParent();
1871 case Intrinsic::get_dynamic_area_offset: {
1873 MI.eraseFromParent();
1876 case Intrinsic::aarch64_mops_memset_tag: {
1877 assert(
MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
1880 auto &
Value =
MI.getOperand(3);
1882 Value.setReg(ExtValueReg);
1885 case Intrinsic::aarch64_prefetch: {
1886 auto &AddrVal =
MI.getOperand(1);
1888 int64_t IsWrite =
MI.getOperand(2).getImm();
1889 int64_t
Target =
MI.getOperand(3).getImm();
1890 int64_t IsStream =
MI.getOperand(4).getImm();
1891 int64_t IsData =
MI.getOperand(5).getImm();
1893 unsigned PrfOp = (IsWrite << 4) |
1899 MI.eraseFromParent();
1902 case Intrinsic::aarch64_range_prefetch: {
1903 auto &AddrVal =
MI.getOperand(1);
1905 int64_t IsWrite =
MI.getOperand(2).getImm();
1906 int64_t IsStream =
MI.getOperand(3).getImm();
1907 unsigned PrfOp = (IsStream << 2) | IsWrite;
1909 MIB.
buildInstr(AArch64::G_AARCH64_RANGE_PREFETCH)
1912 .
addUse(
MI.getOperand(4).getReg());
1913 MI.eraseFromParent();
1916 case Intrinsic::aarch64_prefetch_ir: {
1917 auto &AddrVal =
MI.getOperand(1);
1919 MI.eraseFromParent();
1922 case Intrinsic::aarch64_neon_uaddv:
1923 case Intrinsic::aarch64_neon_saddv:
1924 case Intrinsic::aarch64_neon_umaxv:
1925 case Intrinsic::aarch64_neon_smaxv:
1926 case Intrinsic::aarch64_neon_uminv:
1927 case Intrinsic::aarch64_neon_sminv: {
1928 bool IsSigned = IntrinsicID == Intrinsic::aarch64_neon_saddv ||
1929 IntrinsicID == Intrinsic::aarch64_neon_smaxv ||
1930 IntrinsicID == Intrinsic::aarch64_neon_sminv;
1932 auto OldDst =
MI.getOperand(0).getReg();
1933 auto OldDstTy =
MRI.getType(OldDst);
1934 LLT NewDstTy =
MRI.getType(
MI.getOperand(2).getReg()).getElementType();
1935 if (OldDstTy == NewDstTy)
1938 auto NewDst =
MRI.createGenericVirtualRegister(NewDstTy);
1941 MI.getOperand(0).setReg(NewDst);
1945 MIB.
buildExtOrTrunc(IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT,
1950 case Intrinsic::aarch64_neon_uaddlp:
1951 case Intrinsic::aarch64_neon_saddlp: {
1952 unsigned Opc = IntrinsicID == Intrinsic::aarch64_neon_uaddlp
1954 : AArch64::G_SADDLP;
1956 MI.eraseFromParent();
1960 case Intrinsic::aarch64_neon_uaddlv:
1961 case Intrinsic::aarch64_neon_saddlv: {
1962 unsigned Opc = IntrinsicID == Intrinsic::aarch64_neon_uaddlv
1964 : AArch64::G_SADDLV;
1967 LLT DstTy =
MRI.getType(DstReg);
1991 MI.eraseFromParent();
1995 case Intrinsic::aarch64_neon_fmax:
1996 return LowerBinOp(TargetOpcode::G_FMAXIMUM);
1997 case Intrinsic::aarch64_neon_fmin:
1998 return LowerBinOp(TargetOpcode::G_FMINIMUM);
1999 case Intrinsic::aarch64_neon_fmaxnm:
2000 return LowerBinOp(TargetOpcode::G_FMAXNUM);
2001 case Intrinsic::aarch64_neon_fminnm:
2002 return LowerBinOp(TargetOpcode::G_FMINNUM);
2003 case Intrinsic::aarch64_neon_pmul:
2004 return LowerBinOp(TargetOpcode::G_CLMUL);
2005 case Intrinsic::aarch64_neon_pmull:
2006 case Intrinsic::aarch64_neon_pmull64:
2007 return LowerBinOp(AArch64::G_PMULL);
2008 case Intrinsic::aarch64_neon_smull:
2009 return LowerBinOp(AArch64::G_SMULL);
2010 case Intrinsic::aarch64_neon_umull:
2011 return LowerBinOp(AArch64::G_UMULL);
2012 case Intrinsic::aarch64_neon_sabd:
2013 return LowerBinOp(TargetOpcode::G_ABDS);
2014 case Intrinsic::aarch64_neon_uabd:
2015 return LowerBinOp(TargetOpcode::G_ABDU);
2016 case Intrinsic::aarch64_neon_uhadd:
2017 return LowerBinOp(TargetOpcode::G_UAVGFLOOR);
2018 case Intrinsic::aarch64_neon_urhadd:
2019 return LowerBinOp(TargetOpcode::G_UAVGCEIL);
2020 case Intrinsic::aarch64_neon_shadd:
2021 return LowerBinOp(TargetOpcode::G_SAVGFLOOR);
2022 case Intrinsic::aarch64_neon_srhadd:
2023 return LowerBinOp(TargetOpcode::G_SAVGCEIL);
2024 case Intrinsic::aarch64_neon_sqshrn: {
2025 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2029 {
MRI.getType(
MI.getOperand(2).getReg())},
2030 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
2032 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {
MI.getOperand(0)}, {Shr});
2033 MI.eraseFromParent();
2036 case Intrinsic::aarch64_neon_sqshrun: {
2037 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2041 {
MRI.getType(
MI.getOperand(2).getReg())},
2042 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
2044 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {
MI.getOperand(0)}, {Shr});
2045 MI.eraseFromParent();
2048 case Intrinsic::aarch64_neon_sqrshrn: {
2049 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2052 auto Shr = MIB.
buildInstr(AArch64::G_SRSHR_I,
2053 {
MRI.getType(
MI.getOperand(2).getReg())},
2054 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
2056 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {
MI.getOperand(0)}, {Shr});
2057 MI.eraseFromParent();
2060 case Intrinsic::aarch64_neon_sqrshrun: {
2061 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2064 auto Shr = MIB.
buildInstr(AArch64::G_SRSHR_I,
2065 {
MRI.getType(
MI.getOperand(2).getReg())},
2066 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
2068 MIB.
buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {
MI.getOperand(0)}, {Shr});
2069 MI.eraseFromParent();
2072 case Intrinsic::aarch64_neon_uqrshrn: {
2073 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2076 auto Shr = MIB.
buildInstr(AArch64::G_URSHR_I,
2077 {
MRI.getType(
MI.getOperand(2).getReg())},
2078 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
2080 MIB.
buildInstr(TargetOpcode::G_TRUNC_USAT_U, {
MI.getOperand(0)}, {Shr});
2081 MI.eraseFromParent();
2084 case Intrinsic::aarch64_neon_uqshrn: {
2085 if (!
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2089 {
MRI.getType(
MI.getOperand(2).getReg())},
2090 {
MI.getOperand(2),
MI.getOperand(3).getImm()});
2092 MIB.
buildInstr(TargetOpcode::G_TRUNC_USAT_U, {
MI.getOperand(0)}, {Shr});
2093 MI.eraseFromParent();
2096 case Intrinsic::aarch64_neon_sqshlu: {
2102 MIB.
buildInstr(AArch64::G_SQSHLU_I, {
MI.getOperand(0)},
2104 .addImm(ShiftAmount->getSExtValue());
2105 MI.eraseFromParent();
2110 case Intrinsic::aarch64_neon_vsli: {
2112 AArch64::G_SLI, {
MI.getOperand(0)},
2113 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4).getImm()});
2114 MI.eraseFromParent();
2117 case Intrinsic::aarch64_neon_vsri: {
2119 AArch64::G_SRI, {
MI.getOperand(0)},
2120 {
MI.getOperand(2),
MI.getOperand(3),
MI.getOperand(4).getImm()});
2121 MI.eraseFromParent();
2124 case Intrinsic::aarch64_neon_abs: {
2126 MIB.
buildInstr(TargetOpcode::G_ABS, {
MI.getOperand(0)}, {
MI.getOperand(2)});
2127 MI.eraseFromParent();
2130 case Intrinsic::aarch64_neon_addhn:
2131 return LowerBinOp(AArch64::G_ADDHN);
2132 case Intrinsic::aarch64_neon_sqadd: {
2133 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2134 return LowerBinOp(TargetOpcode::G_SADDSAT);
2137 case Intrinsic::aarch64_neon_sqsub: {
2138 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2139 return LowerBinOp(TargetOpcode::G_SSUBSAT);
2142 case Intrinsic::aarch64_neon_uqadd: {
2143 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2144 return LowerBinOp(TargetOpcode::G_UADDSAT);
2147 case Intrinsic::aarch64_neon_uqsub: {
2148 if (
MRI.getType(
MI.getOperand(0).getReg()).isVector())
2149 return LowerBinOp(TargetOpcode::G_USUBSAT);
2152 case Intrinsic::aarch64_neon_udot:
2153 return LowerTriOp(AArch64::G_UDOT);
2154 case Intrinsic::aarch64_neon_sdot:
2155 return LowerTriOp(AArch64::G_SDOT);
2156 case Intrinsic::aarch64_neon_usdot:
2157 return LowerTriOp(AArch64::G_USDOT);
2158 case Intrinsic::aarch64_neon_sqxtn:
2159 return LowerUnaryOp(TargetOpcode::G_TRUNC_SSAT_S);
2160 case Intrinsic::aarch64_neon_sqxtun:
2161 return LowerUnaryOp(TargetOpcode::G_TRUNC_SSAT_U);
2162 case Intrinsic::aarch64_neon_uqxtn:
2163 return LowerUnaryOp(TargetOpcode::G_TRUNC_USAT_U);
2164 case Intrinsic::aarch64_neon_fcvtzu:
2165 return LowerUnaryOp(TargetOpcode::G_FPTOUI_SAT);
2166 case Intrinsic::aarch64_neon_fcvtzs:
2167 return LowerUnaryOp(TargetOpcode::G_FPTOSI_SAT);
2168 case Intrinsic::aarch64_neon_cls:
2169 return LowerUnaryOp(TargetOpcode::G_CTLS);
2171 case Intrinsic::vector_reverse: