51#define DEBUG_TYPE "legalizevectorops"
55class VectorLegalizer {
67 LegalizedNodes.
insert(std::make_pair(
From, To));
70 LegalizedNodes.
insert(std::make_pair(To, To));
142 std::pair<SDValue, SDValue> ExpandLoad(
SDNode *
N);
202bool VectorLegalizer::Run() {
204 bool HasVectors =
false;
206 E = std::prev(DAG.allnodes_end());
I != std::next(E); ++
I) {
226 DAG.AssignTopologicalOrder();
228 E = std::prev(DAG.allnodes_end());
I != std::next(E); ++
I)
232 SDValue OldRoot = DAG.getRoot();
233 assert(LegalizedNodes.count(OldRoot) &&
"Root didn't get legalized?");
234 DAG.setRoot(LegalizedNodes[OldRoot]);
236 LegalizedNodes.clear();
239 DAG.RemoveDeadNodes();
246 "Unexpected number of results");
248 for (
unsigned i = 0, e =
Op->getNumValues(); i != e; ++i)
249 AddLegalizedOperand(
Op.getValue(i),
SDValue(Result, i));
254VectorLegalizer::RecursivelyLegalizeResults(
SDValue Op,
257 "Unexpected number of results");
259 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
261 AddLegalizedOperand(
Op.getValue(i),
Results[i]);
271 if (
I != LegalizedNodes.end())
return I->second;
275 for (
const SDValue &Oper :
Op->op_values())
278 SDNode *
Node = DAG.UpdateNodeOperands(
Op.getNode(), Ops);
280 bool HasVectorValueOrOp =
283 [](
SDValue O) { return O.getValueType().isVector(); });
284 if (!HasVectorValueOrOp)
285 return TranslateLegalizeResults(
Op,
Node);
289 switch (
Op.getOpcode()) {
291 return TranslateLegalizeResults(
Op,
Node);
295 EVT LoadedVT =
LD->getMemoryVT();
297 Action = TLI.getLoadExtAction(ExtType,
LD->getValueType(0), LoadedVT);
302 EVT StVT =
ST->getMemoryVT();
303 MVT ValVT =
ST->getValue().getSimpleValueType();
304 if (StVT.
isVector() &&
ST->isTruncatingStore())
305 Action = TLI.getTruncStoreAction(ValVT, StVT);
309 Action = TLI.getOperationAction(
Node->getOpcode(),
Node->getValueType(0));
312 if (Action == TargetLowering::Legal)
313 Action = TargetLowering::Expand;
315#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
316 case ISD::STRICT_##DAGN:
317#include "llvm/IR/ConstrainedOps.def"
318 ValVT =
Node->getValueType(0);
321 ValVT =
Node->getOperand(1).getValueType();
324 MVT OpVT =
Node->getOperand(1).getSimpleValueType();
326 Action = TLI.getCondCodeAction(CCCode, OpVT);
327 if (Action == TargetLowering::Legal)
328 Action = TLI.getOperationAction(
Node->getOpcode(), OpVT);
330 Action = TLI.getOperationAction(
Node->getOpcode(), ValVT);
337 if (Action == TargetLowering::Expand && !TLI.isStrictFPEnabled() &&
338 TLI.getStrictFPOperationAction(
Node->getOpcode(), ValVT) ==
339 TargetLowering::Legal) {
341 if (TLI.getOperationAction(
Node->getOpcode(), EltVT)
342 == TargetLowering::Expand &&
343 TLI.getStrictFPOperationAction(
Node->getOpcode(), EltVT)
344 == TargetLowering::Legal)
345 Action = TargetLowering::Legal;
470 Action = TLI.getOperationAction(
Node->getOpcode(),
Node->getValueType(0));
480 unsigned Scale =
Node->getConstantOperandVal(2);
481 Action = TLI.getFixedPointOperationAction(
Node->getOpcode(),
482 Node->getValueType(0), Scale);
507 Action = TLI.getOperationAction(
Node->getOpcode(),
508 Node->getOperand(0).getValueType());
512 Action = TLI.getOperationAction(
Node->getOpcode(),
513 Node->getOperand(1).getValueType());
516 MVT OpVT =
Node->getOperand(0).getSimpleValueType();
518 Action = TLI.getCondCodeAction(CCCode, OpVT);
519 if (Action == TargetLowering::Legal)
520 Action = TLI.getOperationAction(
Node->getOpcode(), OpVT);
524#define BEGIN_REGISTER_VP_SDNODE(VPID, LEGALPOS, ...) \
526 EVT LegalizeVT = LEGALPOS < 0 ? Node->getValueType(-(1 + LEGALPOS)) \
527 : Node->getOperand(LEGALPOS).getValueType(); \
528 if (ISD::VPID == ISD::VP_SETCC) { \
529 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get(); \
530 Action = TLI.getCondCodeAction(CCCode, LegalizeVT.getSimpleVT()); \
531 if (Action != TargetLowering::Legal) \
535 if (!Node->getValueType(0).isVector() && \
536 Node->getValueType(0) != MVT::Other) { \
537 Action = TargetLowering::Legal; \
540 Action = TLI.getOperationAction(Node->getOpcode(), LegalizeVT); \
542#include "llvm/IR/VPIntrinsics.def"
550 case TargetLowering::Promote:
552 "This action is not supported yet!");
554 Promote(
Node, ResultVals);
555 assert(!ResultVals.
empty() &&
"No results for promotion?");
557 case TargetLowering::Legal:
560 case TargetLowering::Custom:
562 if (LowerOperationWrapper(
Node, ResultVals))
566 case TargetLowering::Expand:
568 Expand(
Node, ResultVals);
572 if (ResultVals.
empty())
573 return TranslateLegalizeResults(
Op,
Node);
576 return RecursivelyLegalizeResults(
Op, ResultVals);
581bool VectorLegalizer::LowerOperationWrapper(
SDNode *
Node,
593 if (
Node->getNumValues() == 1) {
601 "Lowering returned the wrong number of results!");
604 for (
unsigned I = 0, E =
Node->getNumValues();
I != E; ++
I)
610void VectorLegalizer::PromoteSETCC(
SDNode *
Node,
612 MVT VecVT =
Node->getOperand(0).getSimpleValueType();
613 MVT NewVecVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VecVT);
620 Operands[0] = DAG.getNode(ExtOp,
DL, NewVecVT,
Node->getOperand(0));
621 Operands[1] = DAG.getNode(ExtOp,
DL, NewVecVT,
Node->getOperand(1));
624 if (
Node->getOpcode() == ISD::VP_SETCC) {
635void VectorLegalizer::PromoteSTRICT(
SDNode *
Node,
637 MVT VecVT =
Node->getOperand(1).getSimpleValueType();
638 MVT NewVecVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VecVT);
646 for (
unsigned j = 1;
j !=
Node->getNumOperands(); ++
j)
647 if (
Node->getOperand(j).getValueType().isVector() &&
654 {
Node->getOperand(0),
Node->getOperand(j)});
660 SDVTList VTs = DAG.getVTList(NewVecVT,
Node->getValueType(1));
670 DAG.getIntPtrConstant(0,
DL,
true)});
679 switch (
Node->getOpcode()) {
713 case ISD::VP_FCOPYSIGN:
725 "Can't promote a vector with multiple results!");
726 MVT VT =
Node->getSimpleValueType(0);
727 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
731 for (
unsigned j = 0;
j !=
Node->getNumOperands(); ++
j) {
735 if (
Node->getOperand(j).getValueType().isVector() && !SkipPromote)
736 if (
Node->getOperand(j)
738 .getVectorElementType()
739 .isFloatingPoint() &&
746 DAG.getNode(ISD::VP_FP_EXTEND, dl, NVT,
Node->getOperand(j),
747 Node->getOperand(MaskIdx),
Node->getOperand(EVLIdx));
767 Res = DAG.
getNode(ISD::VP_FP_ROUND, dl, VT, Res,
768 Node->getOperand(MaskIdx),
Node->getOperand(EVLIdx));
771 DAG.getIntPtrConstant(0, dl,
true));
779void VectorLegalizer::PromoteINT_TO_FP(
SDNode *
Node,
783 bool IsStrict =
Node->isStrictFPOpcode();
784 MVT VT =
Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
785 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
787 "Vectors have different number of elements!");
796 for (
unsigned j = 0;
j !=
Node->getNumOperands(); ++
j) {
797 if (
Node->getOperand(j).getValueType().isVector())
798 Operands[j] = DAG.getNode(Opc, dl, NVT,
Node->getOperand(j));
820void VectorLegalizer::PromoteFP_TO_INT(
SDNode *
Node,
822 MVT VT =
Node->getSimpleValueType(0);
823 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
824 bool IsStrict =
Node->isStrictFPOpcode();
826 "Vectors have different number of elements!");
828 unsigned NewOpc =
Node->getOpcode();
842 Promoted = DAG.
getNode(NewOpc, dl, {NVT, MVT::Other},
843 {
Node->getOperand(0),
Node->getOperand(1)});
846 Promoted = DAG.
getNode(NewOpc, dl, NVT,
Node->getOperand(0));
857 Promoted = DAG.
getNode(NewOpc, dl, NVT, Promoted,
865std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(
SDNode *
N) {
867 return TLI.scalarizeVectorLoad(LD, DAG);
872 SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
877 switch (
Node->getOpcode()) {
879 std::pair<SDValue, SDValue> Tmp = ExpandLoad(
Node);
888 for (
unsigned i = 0, e =
Node->getNumValues(); i != e; ++i)
898 Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(
Node));
901 Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(
Node));
904 Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(
Node));
946 case ISD::VP_FCOPYSIGN:
959 if (
Node->getValueType(0).isScalableVector()) {
960 EVT CondVT = TLI.getSetCCResultType(
961 DAG.getDataLayout(), *DAG.getContext(),
Node->getValueType(0));
964 Node->getOperand(1),
Node->getOperand(4));
967 Node->getOperand(3)));
1004 if (
SDValue Expanded = TLI.expandABS(
Node, DAG)) {
1011 if (
SDValue Expanded = TLI.expandABD(
Node, DAG)) {
1020 if (
SDValue Expanded = TLI.expandAVG(
Node, DAG)) {
1031 case ISD::VP_BITREVERSE:
1032 if (
SDValue Expanded = TLI.expandVPBITREVERSE(
Node, DAG)) {
1038 if (
SDValue Expanded = TLI.expandCTPOP(
Node, DAG)) {
1044 if (
SDValue Expanded = TLI.expandVPCTPOP(
Node, DAG)) {
1051 if (
SDValue Expanded = TLI.expandCTLZ(
Node, DAG)) {
1057 case ISD::VP_CTLZ_ZERO_UNDEF:
1058 if (
SDValue Expanded = TLI.expandVPCTLZ(
Node, DAG)) {
1065 if (
SDValue Expanded = TLI.expandCTTZ(
Node, DAG)) {
1071 case ISD::VP_CTTZ_ZERO_UNDEF:
1072 if (
SDValue Expanded = TLI.expandVPCTTZ(
Node, DAG)) {
1081 if (
SDValue Expanded = TLI.expandFunnelShift(
Node, DAG)) {
1088 if (
SDValue Expanded = TLI.expandROT(
Node,
false , DAG)) {
1095 if (
SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(
Node, DAG)) {
1102 Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(
Node, DAG));
1106 Results.push_back(TLI.expandFMINIMUMNUM_FMAXIMUMNUM(
Node, DAG));
1112 if (
SDValue Expanded = TLI.expandIntMINMAX(
Node, DAG)) {
1133 if (
SDValue Expanded = TLI.expandAddSubSat(
Node, DAG)) {
1140 if (
SDValue Expanded = TLI.expandShlSat(
Node, DAG)) {
1148 if (
Node->getValueType(0).isScalableVector()) {
1149 if (
SDValue Expanded = TLI.expandFP_TO_INT_SAT(
Node, DAG)) {
1157 if (
SDValue Expanded = TLI.expandFixedPointMul(
Node, DAG)) {
1176#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1177 case ISD::STRICT_##DAGN:
1178#include "llvm/IR/ConstrainedOps.def"
1196 Results.push_back(TLI.expandVecReduce(
Node, DAG));
1200 Results.push_back(TLI.expandVecReduceSeq(
Node, DAG));
1213 if (tryExpandVecMathCall(
Node, RTLIB::REM_F32, RTLIB::REM_F64,
1214 RTLIB::REM_F80, RTLIB::REM_F128,
1222 if (DAG.expandMultipleResultFPLibCall(LC,
Node,
Results))
1227 Results.push_back(TLI.expandVECTOR_COMPRESS(
Node, DAG));
1230 Results.push_back(TLI.expandVectorFindLastActive(
Node, DAG));
1249 if (
SDValue Expanded = TLI.expandVectorNaryOpBySplitting(
Node, DAG)) {
1257 if (
Node->getNumValues() == 1) {
1261 "VectorLegalizer Expand returned wrong number of results!");
1271 EVT VT =
Node->getValueType(0);
1289 if (TLI.getOperationAction(
ISD::AND, VT) == TargetLowering::Expand ||
1290 TLI.getOperationAction(
ISD::XOR, VT) == TargetLowering::Expand ||
1291 TLI.getOperationAction(
ISD::OR, VT) == TargetLowering::Expand ||
1294 VT) == TargetLowering::Expand)
1303 Mask = DAG.getSelect(
DL, BitTy, Mask, DAG.getAllOnesConstant(
DL, BitTy),
1304 DAG.getConstant(0,
DL, BitTy));
1307 Mask = DAG.getSplat(MaskTy,
DL, Mask);
1315 SDValue NotMask = DAG.getNOT(
DL, Mask, MaskTy);
1324 EVT VT =
Node->getValueType(0);
1327 if (TLI.getOperationAction(
ISD::SRA, VT) == TargetLowering::Expand ||
1328 TLI.getOperationAction(
ISD::SHL, VT) == TargetLowering::Expand)
1332 EVT OrigTy = cast<VTSDNode>(
Node->getOperand(1))->getVT();
1336 SDValue ShiftSz = DAG.getConstant(BW - OrigBW,
DL, VT);
1346 EVT VT =
Node->getValueType(0);
1349 EVT SrcVT = Src.getValueType();
1356 "ANY_EXTEND_VECTOR_INREG vector size mismatch");
1361 Src, DAG.getVectorIdxConstant(0,
DL));
1366 ShuffleMask.
resize(NumSrcElements, -1);
1369 int ExtLaneScale = NumSrcElements / NumElements;
1370 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1371 for (
int i = 0; i < NumElements; ++i)
1372 ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
1376 DAG.getVectorShuffle(SrcVT,
DL, Src, DAG.getUNDEF(SrcVT), ShuffleMask));
1381 EVT VT =
Node->getValueType(0);
1383 EVT SrcVT = Src.getValueType();
1394 SDValue ShiftAmount = DAG.getConstant(EltWidth - SrcEltWidth,
DL, VT);
1405 EVT VT =
Node->getValueType(0);
1408 EVT SrcVT = Src.getValueType();
1415 "ZERO_EXTEND_VECTOR_INREG vector size mismatch");
1420 Src, DAG.getVectorIdxConstant(0,
DL));
1428 auto ShuffleMask = llvm::to_vector<16>(llvm::seq<int>(0, NumSrcElements));
1430 int ExtLaneScale = NumSrcElements / NumElements;
1431 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1432 for (
int i = 0; i < NumElements; ++i)
1433 ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
1436 DAG.getVectorShuffle(SrcVT,
DL, Zero, Src, ShuffleMask));
1442 for (
int J = ScalarSizeInBytes - 1; J >= 0; --J)
1443 ShuffleMask.
push_back((
I * ScalarSizeInBytes) + J);
1447 EVT VT =
Node->getValueType(0);
1451 return TLI.expandBSWAP(
Node, DAG);
1459 if (TLI.isShuffleMaskLegal(ShuffleMask, ByteVT)) {
1462 Op = DAG.getVectorShuffle(ByteVT,
DL,
Op, DAG.getUNDEF(ByteVT), ShuffleMask);
1468 if (TLI.isOperationLegalOrCustom(
ISD::SHL, VT) &&
1469 TLI.isOperationLegalOrCustom(
ISD::SRL, VT) &&
1470 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, VT) &&
1471 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, VT))
1472 return TLI.expandBSWAP(
Node, DAG);
1479 EVT VT =
Node->getValueType(0);
1483 return TLI.expandBITREVERSE(
Node, DAG);
1493 if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
1498 if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
1500 (TLI.isOperationLegalOrCustom(
ISD::SHL, ByteVT) &&
1501 TLI.isOperationLegalOrCustom(
ISD::SRL, ByteVT) &&
1502 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, ByteVT) &&
1503 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, ByteVT)))) {
1506 Op = DAG.getVectorShuffle(ByteVT,
DL,
Op, DAG.getUNDEF(ByteVT),
1516 if (TLI.isOperationLegalOrCustom(
ISD::SHL, VT) &&
1517 TLI.isOperationLegalOrCustom(
ISD::SRL, VT) &&
1518 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, VT) &&
1519 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, VT))
1520 return TLI.expandBITREVERSE(
Node, DAG);
1541 if (TLI.getOperationAction(
ISD::AND, VT) == TargetLowering::Expand ||
1542 TLI.getOperationAction(
ISD::XOR, VT) == TargetLowering::Expand ||
1543 TLI.getOperationAction(
ISD::OR, VT) == TargetLowering::Expand)
1550 auto BoolContents = TLI.getBooleanContents(Op1.
getValueType());
1551 if (BoolContents != TargetLowering::ZeroOrNegativeOneBooleanContent &&
1552 !(BoolContents == TargetLowering::ZeroOrOneBooleanContent &&
1568 SDValue NotMask = DAG.getNOT(
DL, Mask, VT);
1590 if (TLI.getOperationAction(ISD::VP_AND, VT) == TargetLowering::Expand ||
1591 TLI.getOperationAction(ISD::VP_XOR, VT) == TargetLowering::Expand ||
1592 TLI.getOperationAction(ISD::VP_OR, VT) == TargetLowering::Expand)
1599 SDValue Ones = DAG.getAllOnesConstant(
DL, VT);
1602 Op1 = DAG.
getNode(ISD::VP_AND,
DL, VT, Op1, Mask, Ones, EVL);
1603 Op2 = DAG.
getNode(ISD::VP_AND,
DL, VT, Op2, NotMask, Ones, EVL);
1604 return DAG.getNode(ISD::VP_OR,
DL, VT, Op1, Op2, Ones, EVL);
1619 EVT MaskVT =
Mask.getValueType();
1635 if (TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
1636 EVLVecVT) != MaskVT)
1639 SDValue StepVec = DAG.getStepVector(
DL, EVLVecVT);
1640 SDValue SplatEVL = DAG.getSplat(EVLVecVT,
DL, EVL);
1642 DAG.getSetCC(
DL, MaskVT, StepVec, SplatEVL, ISD::CondCode::SETULT);
1645 return DAG.getSelect(
DL,
Node->getValueType(0), FullMask, Op1, Op2);
1650 EVT VT =
Node->getValueType(0);
1652 unsigned DivOpc =
Node->getOpcode() == ISD::VP_SREM ? ISD::VP_SDIV : ISD::VP_UDIV;
1654 if (!TLI.isOperationLegalOrCustom(DivOpc, VT) ||
1655 !TLI.isOperationLegalOrCustom(ISD::VP_MUL, VT) ||
1656 !TLI.isOperationLegalOrCustom(ISD::VP_SUB, VT))
1668 SDValue Mul = DAG.getNode(ISD::VP_MUL,
DL, VT, Divisor, Div, Mask, EVL);
1669 return DAG.getNode(ISD::VP_SUB,
DL, VT, Dividend,
Mul, Mask, EVL);
1673 EVT VT =
Node->getValueType(0);
1676 if (!TLI.isOperationLegalOrCustom(ISD::VP_XOR, IntVT))
1684 SDValue SignMask = DAG.getConstant(
1686 SDValue Xor = DAG.getNode(ISD::VP_XOR,
DL, IntVT, Cast, SignMask, Mask, EVL);
1691 EVT VT =
Node->getValueType(0);
1694 if (!TLI.isOperationLegalOrCustom(ISD::VP_AND, IntVT))
1702 SDValue ClearSignMask = DAG.getConstant(
1705 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Cast, ClearSignMask, Mask, EVL);
1710 EVT VT =
Node->getValueType(0);
1712 if (VT !=
Node->getOperand(1).getValueType())
1716 if (!TLI.isOperationLegalOrCustom(ISD::VP_AND, IntVT) ||
1717 !TLI.isOperationLegalOrCustom(ISD::VP_XOR, IntVT))
1727 SDValue SignMask = DAG.getConstant(
1730 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Sign, SignMask, Mask, EVL);
1732 SDValue ClearSignMask = DAG.getConstant(
1735 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Mag, ClearSignMask, Mask, EVL);
1737 SDValue CopiedSign = DAG.
getNode(ISD::VP_OR,
DL, IntVT, ClearedSign, SignBit,
1743void VectorLegalizer::ExpandFP_TO_UINT(
SDNode *
Node,
1747 if (TLI.expandFP_TO_UINT(
Node, Result, Chain, DAG)) {
1749 if (
Node->isStrictFPOpcode())
1755 if (
Node->isStrictFPOpcode()) {
1763void VectorLegalizer::ExpandUINT_TO_FLOAT(
SDNode *
Node,
1765 bool IsStrict =
Node->isStrictFPOpcode();
1766 unsigned OpNo = IsStrict ? 1 : 0;
1768 EVT SrcVT = Src.getValueType();
1769 EVT DstVT =
Node->getValueType(0);
1775 if (TLI.expandUINT_TO_FP(
Node, Result, Chain, DAG)) {
1784 TargetLowering::Expand) ||
1786 TargetLowering::Expand)) ||
1787 TLI.getOperationAction(
ISD::SRL, SrcVT) == TargetLowering::Expand) {
1798 assert((BW == 64 || BW == 32) &&
1799 "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
1803 if ((!IsStrict && !TLI.isOperationLegalOrCustom(
ISD::FMUL, DstVT)) ||
1805 EVT FPVT = BW == 32 ? MVT::f32 : MVT::f64;
1808 SDValue TargetZero = DAG.getIntPtrConstant(0,
DL,
true);
1812 {
Node->getOperand(0), Src});
1814 {
Node->getOperand(0), UIToFP, TargetZero});
1826 SDValue HalfWord = DAG.getConstant(BW / 2,
DL, SrcVT);
1831 uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1832 SDValue HalfWordMask = DAG.getConstant(HWMask,
DL, SrcVT);
1835 SDValue TWOHW = DAG.getConstantFP(1ULL << (BW / 2),
DL, DstVT);
1846 {
Node->getOperand(0),
HI});
1850 {
Node->getOperand(0),
LO});
1876 EVT VT =
Node->getValueType(0);
1879 if (!TLI.isOperationLegalOrCustom(
ISD::XOR, IntVT))
1883 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1889 SDValue SignMask = DAG.getConstant(
1896 EVT VT =
Node->getValueType(0);
1899 if (!TLI.isOperationLegalOrCustom(
ISD::AND, IntVT))
1903 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1909 SDValue ClearSignMask = DAG.getConstant(
1916 EVT VT =
Node->getValueType(0);
1919 if (VT !=
Node->getOperand(1).getValueType() ||
1920 !TLI.isOperationLegalOrCustom(
ISD::AND, IntVT) ||
1921 !TLI.isOperationLegalOrCustom(
ISD::OR, IntVT))
1925 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1933 SDValue SignMask = DAG.getConstant(
1937 SDValue ClearSignMask = DAG.getConstant(
1947void VectorLegalizer::ExpandFSUB(
SDNode *
Node,
1952 EVT VT =
Node->getValueType(0);
1953 if (TLI.isOperationLegalOrCustom(
ISD::FNEG, VT) &&
1954 TLI.isOperationLegalOrCustom(
ISD::FADD, VT))
1957 if (
SDValue Expanded = TLI.expandVectorNaryOpBySplitting(
Node, DAG)) {
1966void VectorLegalizer::ExpandSETCC(
SDNode *
Node,
1968 bool NeedInvert =
false;
1969 bool IsVP =
Node->getOpcode() == ISD::VP_SETCC;
1973 unsigned Offset = IsStrict ? 1 : 0;
1980 MVT OpVT =
LHS.getSimpleValueType();
1983 if (TLI.getCondCodeAction(CCCode, OpVT) != TargetLowering::Expand) {
2000 TLI.LegalizeSetCCCondCode(DAG,
Node->getValueType(0), LHS, RHS,
CC, Mask,
2001 EVL, NeedInvert, dl, Chain, IsSignaling);
2008 LHS = DAG.getNode(
Node->getOpcode(), dl,
Node->getVTList(),
2009 {Chain, LHS, RHS, CC},
Node->getFlags());
2010 Chain =
LHS.getValue(1);
2012 LHS = DAG.getNode(ISD::VP_SETCC, dl,
Node->getValueType(0),
2013 {LHS, RHS, CC, Mask, EVL},
Node->getFlags());
2024 LHS = DAG.getLogicalNOT(dl, LHS,
LHS->getValueType(0));
2026 LHS = DAG.getVPLogicalNOT(dl, LHS, Mask, EVL,
LHS->getValueType(0));
2029 assert(!IsStrict &&
"Don't know how to expand for strict nodes.");
2033 EVT VT =
Node->getValueType(0);
2036 DAG.getBoolConstant(
true, dl, VT,
LHS.getValueType()),
2037 DAG.getBoolConstant(
false, dl, VT,
LHS.getValueType()),
CC);
2038 LHS->setFlags(
Node->getFlags());
2046void VectorLegalizer::ExpandUADDSUBO(
SDNode *
Node,
2049 TLI.expandUADDSUBO(
Node, Result, Overflow, DAG);
2054void VectorLegalizer::ExpandSADDSUBO(
SDNode *
Node,
2057 TLI.expandSADDSUBO(
Node, Result, Overflow, DAG);
2062void VectorLegalizer::ExpandMULO(
SDNode *
Node,
2065 if (!TLI.expandMULO(
Node, Result, Overflow, DAG))
2066 std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(
Node);
2072void VectorLegalizer::ExpandFixedPointDiv(
SDNode *
Node,
2075 if (
SDValue Expanded = TLI.expandFixedPointDiv(
N->getOpcode(),
SDLoc(
N),
2076 N->getOperand(0),
N->getOperand(1),
N->getConstantOperandVal(2), DAG))
2080void VectorLegalizer::ExpandStrictFPOp(
SDNode *
Node,
2103 "Expected REM node");
2106 if (!TLI.expandREM(
Node, Result, DAG))
2121 assert(!
Node->isStrictFPOpcode() &&
"Unexpected strict fp operation!");
2123 const char *LCName = TLI.getLibcallName(LC);
2126 LLVM_DEBUG(
dbgs() <<
"Looking for vector variant of " << LCName <<
"\n");
2128 EVT VT =
Node->getValueType(0);
2146 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
2147 assert(
Node->getOperand(i).getValueType() == VT &&
2148 "Expected matching vector types!");
2151 FunctionType *ScalarFTy = FunctionType::get(ScalarTy, ArgTys,
false);
2163 if (OptVFInfo->Shape.Parameters.size() !=
2172 Entry.IsSExt =
false;
2173 Entry.IsZExt =
false;
2176 for (
auto &VFParam : OptVFInfo->Shape.Parameters) {
2177 if (VFParam.ParamKind == VFParamKind::GlobalPredicate) {
2178 EVT MaskVT = TLI.getSetCCResultType(DAG.getDataLayout(), *Ctx, VT);
2179 Entry.Node = DAG.getBoolConstant(
true,
DL, MaskVT, VT);
2181 Args.push_back(Entry);
2186 if (VFParam.ParamKind != VFParamKind::Vector)
2191 Args.push_back(Entry);
2196 TLI.getPointerTy(DAG.getDataLayout()));
2199 .setChain(DAG.getEntryNode())
2202 std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
2203 Results.push_back(CallResult.first);
2208bool VectorLegalizer::tryExpandVecMathCall(
2213 Node->getValueType(0).getVectorElementType(), Call_F32, Call_F64,
2214 Call_F80, Call_F128, Call_PPCF128);
2216 if (LC == RTLIB::UNKNOWN_LIBCALL)
2222void VectorLegalizer::UnrollStrictFPOp(
SDNode *
Node,
2224 EVT VT =
Node->getValueType(0);
2227 unsigned NumOpers =
Node->getNumOperands();
2230 EVT TmpEltVT = EltVT;
2234 *DAG.getContext(), TmpEltVT);
2236 EVT ValueVTs[] = {TmpEltVT, MVT::Other};
2242 for (
unsigned i = 0; i < NumElems; ++i) {
2244 SDValue Idx = DAG.getVectorIdxConstant(i, dl);
2250 for (
unsigned j = 1;
j < NumOpers; ++
j) {
2267 ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
2268 DAG.getAllOnesConstant(dl, EltVT),
2269 DAG.getConstant(0, dl, EltVT));
2283 EVT VT =
Node->getValueType(0);
2289 EVT TmpEltVT =
LHS.getValueType().getVectorElementType();
2292 for (
unsigned i = 0; i < NumElems; ++i) {
2294 DAG.getVectorIdxConstant(i, dl));
2296 DAG.getVectorIdxConstant(i, dl));
2300 *DAG.getContext(), TmpEltVT),
2301 LHSElem, RHSElem,
CC);
2302 Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
2303 DAG.getBoolConstant(
true, dl, EltVT, VT),
2304 DAG.getConstant(0, dl, EltVT));
2306 return DAG.getBuildVector(VT, dl, Ops);
2310 return VectorLegalizer(*this).Run();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
BlockVerifier::State From
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl< int > &ShuffleMask)
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file describes how to lower LLVM code to machine code.
DEMANGLE_DUMP_METHOD void dump() const
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
This class represents an Operation in the Expression.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
This is an important class for using LLVM in a threaded context.
This class is used to represent ISD::LOAD nodes.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
bool LegalizeVectors()
This transforms the SelectionDAG into a SelectionDAG that only uses vector math operations supported ...
const TargetLowering & getTargetLoweringInfo() const
ilist< SDNode >::iterator allnodes_iterator
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Provides information about what library functions are available for the current target.
const VecDesc * getVectorMappingInfo(StringRef F, const ElementCount &VF, bool Masked) const
LegalizeAction
This enum indicates whether operations are valid for a target, and if not, what action should be used...
virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const
Return the ValueType of the result of SETCC operations.
std::vector< ArgListEntry > ArgListTy
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
The instances of the Type class are immutable: once they are created, they are never changed.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Provides info so a possible vectorization of a function can be computed.
std::string getVectorFunctionABIVariantString() const
Returns a vector function ABI variant string on the form: ZGV<isa><mask><vlen><vparams><scalarname>(<...
StringRef getVectorFnName() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ VECTOR_FIND_LAST_ACTIVE
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FPTRUNC_ROUND
FPTRUNC_ROUND - This corresponds to the fptrunc_round intrinsic.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ SDIVFIX
RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 2 integers with the same width...
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SSUBO
Same for subtraction.
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two values.
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ SMULO
Same for multiplication.
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
Libcall getFSINCOS(EVT RetVT)
getFSINCOS - Return the FSINCOS_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
Libcall getFPLibCall(EVT VT, Libcall Call_F32, Libcall Call_F64, Libcall Call_F80, Libcall Call_F128, Libcall Call_PPCF128)
GetFPLibCall - Helper to return the right libcall for the given floating point type,...
std::optional< VFInfo > tryDemangleForVFABI(StringRef MangledName, const FunctionType *FTy)
Function to construct a VFInfo out of a mangled names in the following format:
This is an optimization pass for GlobalISel generic memory operations.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
@ Xor
Bitwise or logical XOR of integers.
DWARFExpression::Operation Op
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
bool isFixedLengthVector() const
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This structure contains all information that is necessary for lowering calls.