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;
468 Action = TLI.getOperationAction(
Node->getOpcode(),
Node->getValueType(0));
478 unsigned Scale =
Node->getConstantOperandVal(2);
479 Action = TLI.getFixedPointOperationAction(
Node->getOpcode(),
480 Node->getValueType(0), Scale);
504 Action = TLI.getOperationAction(
Node->getOpcode(),
505 Node->getOperand(0).getValueType());
509 Action = TLI.getOperationAction(
Node->getOpcode(),
510 Node->getOperand(1).getValueType());
513 MVT OpVT =
Node->getOperand(0).getSimpleValueType();
515 Action = TLI.getCondCodeAction(CCCode, OpVT);
516 if (Action == TargetLowering::Legal)
517 Action = TLI.getOperationAction(
Node->getOpcode(), OpVT);
521#define BEGIN_REGISTER_VP_SDNODE(VPID, LEGALPOS, ...) \
523 EVT LegalizeVT = LEGALPOS < 0 ? Node->getValueType(-(1 + LEGALPOS)) \
524 : Node->getOperand(LEGALPOS).getValueType(); \
525 if (ISD::VPID == ISD::VP_SETCC) { \
526 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get(); \
527 Action = TLI.getCondCodeAction(CCCode, LegalizeVT.getSimpleVT()); \
528 if (Action != TargetLowering::Legal) \
532 if (!Node->getValueType(0).isVector() && \
533 Node->getValueType(0) != MVT::Other) { \
534 Action = TargetLowering::Legal; \
537 Action = TLI.getOperationAction(Node->getOpcode(), LegalizeVT); \
539#include "llvm/IR/VPIntrinsics.def"
547 case TargetLowering::Promote:
549 "This action is not supported yet!");
551 Promote(
Node, ResultVals);
552 assert(!ResultVals.
empty() &&
"No results for promotion?");
554 case TargetLowering::Legal:
557 case TargetLowering::Custom:
559 if (LowerOperationWrapper(
Node, ResultVals))
563 case TargetLowering::Expand:
565 Expand(
Node, ResultVals);
569 if (ResultVals.
empty())
570 return TranslateLegalizeResults(
Op,
Node);
573 return RecursivelyLegalizeResults(
Op, ResultVals);
578bool VectorLegalizer::LowerOperationWrapper(
SDNode *
Node,
590 if (
Node->getNumValues() == 1) {
598 "Lowering returned the wrong number of results!");
601 for (
unsigned I = 0, E =
Node->getNumValues();
I != E; ++
I)
607void VectorLegalizer::PromoteSETCC(
SDNode *
Node,
609 MVT VecVT =
Node->getOperand(0).getSimpleValueType();
610 MVT NewVecVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VecVT);
617 Operands[0] = DAG.getNode(ExtOp,
DL, NewVecVT,
Node->getOperand(0));
618 Operands[1] = DAG.getNode(ExtOp,
DL, NewVecVT,
Node->getOperand(1));
621 if (
Node->getOpcode() == ISD::VP_SETCC) {
632void VectorLegalizer::PromoteSTRICT(
SDNode *
Node,
634 MVT VecVT =
Node->getOperand(1).getSimpleValueType();
635 MVT NewVecVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VecVT);
643 for (
unsigned j = 1;
j !=
Node->getNumOperands(); ++
j)
644 if (
Node->getOperand(j).getValueType().isVector() &&
651 {
Node->getOperand(0),
Node->getOperand(j)});
657 SDVTList VTs = DAG.getVTList(NewVecVT,
Node->getValueType(1));
667 DAG.getIntPtrConstant(0,
DL,
true)});
676 switch (
Node->getOpcode()) {
710 case ISD::VP_FCOPYSIGN:
722 "Can't promote a vector with multiple results!");
723 MVT VT =
Node->getSimpleValueType(0);
724 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
728 for (
unsigned j = 0;
j !=
Node->getNumOperands(); ++
j) {
732 if (
Node->getOperand(j).getValueType().isVector() && !SkipPromote)
733 if (
Node->getOperand(j)
735 .getVectorElementType()
736 .isFloatingPoint() &&
752 DAG.getIntPtrConstant(0, dl,
true));
759void VectorLegalizer::PromoteINT_TO_FP(
SDNode *
Node,
763 bool IsStrict =
Node->isStrictFPOpcode();
764 MVT VT =
Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
765 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
767 "Vectors have different number of elements!");
776 for (
unsigned j = 0;
j !=
Node->getNumOperands(); ++
j) {
777 if (
Node->getOperand(j).getValueType().isVector())
778 Operands[j] = DAG.getNode(Opc, dl, NVT,
Node->getOperand(j));
800void VectorLegalizer::PromoteFP_TO_INT(
SDNode *
Node,
802 MVT VT =
Node->getSimpleValueType(0);
803 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
804 bool IsStrict =
Node->isStrictFPOpcode();
806 "Vectors have different number of elements!");
808 unsigned NewOpc =
Node->getOpcode();
822 Promoted = DAG.
getNode(NewOpc, dl, {NVT, MVT::Other},
823 {
Node->getOperand(0),
Node->getOperand(1)});
826 Promoted = DAG.
getNode(NewOpc, dl, NVT,
Node->getOperand(0));
837 Promoted = DAG.
getNode(NewOpc, dl, NVT, Promoted,
845std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(
SDNode *
N) {
847 return TLI.scalarizeVectorLoad(LD, DAG);
852 SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
857 switch (
Node->getOpcode()) {
859 std::pair<SDValue, SDValue> Tmp = ExpandLoad(
Node);
868 for (
unsigned i = 0, e =
Node->getNumValues(); i != e; ++i)
878 Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(
Node));
881 Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(
Node));
884 Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(
Node));
926 case ISD::VP_FCOPYSIGN:
939 if (
Node->getValueType(0).isScalableVector()) {
940 EVT CondVT = TLI.getSetCCResultType(
941 DAG.getDataLayout(), *DAG.getContext(),
Node->getValueType(0));
944 Node->getOperand(1),
Node->getOperand(4));
947 Node->getOperand(3)));
1000 if (
SDValue Expanded = TLI.expandAVG(
Node, DAG)) {
1011 case ISD::VP_BITREVERSE:
1012 if (
SDValue Expanded = TLI.expandVPBITREVERSE(
Node, DAG)) {
1018 if (
SDValue Expanded = TLI.expandCTPOP(
Node, DAG)) {
1024 if (
SDValue Expanded = TLI.expandVPCTPOP(
Node, DAG)) {
1031 if (
SDValue Expanded = TLI.expandCTLZ(
Node, DAG)) {
1037 case ISD::VP_CTLZ_ZERO_UNDEF:
1038 if (
SDValue Expanded = TLI.expandVPCTLZ(
Node, DAG)) {
1045 if (
SDValue Expanded = TLI.expandCTTZ(
Node, DAG)) {
1051 case ISD::VP_CTTZ_ZERO_UNDEF:
1052 if (
SDValue Expanded = TLI.expandVPCTTZ(
Node, DAG)) {
1061 if (
SDValue Expanded = TLI.expandFunnelShift(
Node, DAG)) {
1068 if (
SDValue Expanded = TLI.expandROT(
Node,
false , DAG)) {
1075 if (
SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(
Node, DAG)) {
1082 Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(
Node, DAG));
1088 if (
SDValue Expanded = TLI.expandIntMINMAX(
Node, DAG)) {
1109 if (
SDValue Expanded = TLI.expandAddSubSat(
Node, DAG)) {
1116 if (
SDValue Expanded = TLI.expandShlSat(
Node, DAG)) {
1124 if (
Node->getValueType(0).isScalableVector()) {
1125 if (
SDValue Expanded = TLI.expandFP_TO_INT_SAT(
Node, DAG)) {
1133 if (
SDValue Expanded = TLI.expandFixedPointMul(
Node, DAG)) {
1152#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1153 case ISD::STRICT_##DAGN:
1154#include "llvm/IR/ConstrainedOps.def"
1172 Results.push_back(TLI.expandVecReduce(
Node, DAG));
1176 Results.push_back(TLI.expandVecReduceSeq(
Node, DAG));
1189 if (tryExpandVecMathCall(
Node, RTLIB::REM_F32, RTLIB::REM_F64,
1190 RTLIB::REM_F80, RTLIB::REM_F128,
1198 if (DAG.expandMultipleResultFPLibCall(LC,
Node,
Results))
1203 Results.push_back(TLI.expandVECTOR_COMPRESS(
Node, DAG));
1222 if (
SDValue Expanded = TLI.expandVectorNaryOpBySplitting(
Node, DAG)) {
1230 if (
Node->getNumValues() == 1) {
1234 "VectorLegalizer Expand returned wrong number of results!");
1244 EVT VT =
Node->getValueType(0);
1262 if (TLI.getOperationAction(
ISD::AND, VT) == TargetLowering::Expand ||
1263 TLI.getOperationAction(
ISD::XOR, VT) == TargetLowering::Expand ||
1264 TLI.getOperationAction(
ISD::OR, VT) == TargetLowering::Expand ||
1267 VT) == TargetLowering::Expand)
1276 Mask = DAG.getSelect(
DL, BitTy, Mask, DAG.getAllOnesConstant(
DL, BitTy),
1277 DAG.getConstant(0,
DL, BitTy));
1280 Mask = DAG.getSplat(MaskTy,
DL, Mask);
1288 SDValue NotMask = DAG.getNOT(
DL, Mask, MaskTy);
1297 EVT VT =
Node->getValueType(0);
1300 if (TLI.getOperationAction(
ISD::SRA, VT) == TargetLowering::Expand ||
1301 TLI.getOperationAction(
ISD::SHL, VT) == TargetLowering::Expand)
1305 EVT OrigTy = cast<VTSDNode>(
Node->getOperand(1))->getVT();
1309 SDValue ShiftSz = DAG.getConstant(BW - OrigBW,
DL, VT);
1319 EVT VT =
Node->getValueType(0);
1322 EVT SrcVT = Src.getValueType();
1329 "ANY_EXTEND_VECTOR_INREG vector size mismatch");
1334 Src, DAG.getVectorIdxConstant(0,
DL));
1339 ShuffleMask.
resize(NumSrcElements, -1);
1342 int ExtLaneScale = NumSrcElements / NumElements;
1343 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1344 for (
int i = 0; i < NumElements; ++i)
1345 ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
1349 DAG.getVectorShuffle(SrcVT,
DL, Src, DAG.getUNDEF(SrcVT), ShuffleMask));
1354 EVT VT =
Node->getValueType(0);
1356 EVT SrcVT = Src.getValueType();
1367 SDValue ShiftAmount = DAG.getConstant(EltWidth - SrcEltWidth,
DL, VT);
1378 EVT VT =
Node->getValueType(0);
1381 EVT SrcVT = Src.getValueType();
1388 "ZERO_EXTEND_VECTOR_INREG vector size mismatch");
1393 Src, DAG.getVectorIdxConstant(0,
DL));
1401 auto ShuffleMask = llvm::to_vector<16>(llvm::seq<int>(0, NumSrcElements));
1403 int ExtLaneScale = NumSrcElements / NumElements;
1404 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1405 for (
int i = 0; i < NumElements; ++i)
1406 ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
1409 DAG.getVectorShuffle(SrcVT,
DL, Zero, Src, ShuffleMask));
1415 for (
int J = ScalarSizeInBytes - 1; J >= 0; --J)
1416 ShuffleMask.
push_back((
I * ScalarSizeInBytes) + J);
1420 EVT VT =
Node->getValueType(0);
1424 return TLI.expandBSWAP(
Node, DAG);
1432 if (TLI.isShuffleMaskLegal(ShuffleMask, ByteVT)) {
1435 Op = DAG.getVectorShuffle(ByteVT,
DL,
Op, DAG.getUNDEF(ByteVT), ShuffleMask);
1441 if (TLI.isOperationLegalOrCustom(
ISD::SHL, VT) &&
1442 TLI.isOperationLegalOrCustom(
ISD::SRL, VT) &&
1443 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, VT) &&
1444 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, VT))
1445 return TLI.expandBSWAP(
Node, DAG);
1452 EVT VT =
Node->getValueType(0);
1456 return TLI.expandBITREVERSE(
Node, DAG);
1466 if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
1471 if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
1473 (TLI.isOperationLegalOrCustom(
ISD::SHL, ByteVT) &&
1474 TLI.isOperationLegalOrCustom(
ISD::SRL, ByteVT) &&
1475 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, ByteVT) &&
1476 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, ByteVT)))) {
1479 Op = DAG.getVectorShuffle(ByteVT,
DL,
Op, DAG.getUNDEF(ByteVT),
1489 if (TLI.isOperationLegalOrCustom(
ISD::SHL, VT) &&
1490 TLI.isOperationLegalOrCustom(
ISD::SRL, VT) &&
1491 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, VT) &&
1492 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, VT))
1493 return TLI.expandBITREVERSE(
Node, DAG);
1514 if (TLI.getOperationAction(
ISD::AND, VT) == TargetLowering::Expand ||
1515 TLI.getOperationAction(
ISD::XOR, VT) == TargetLowering::Expand ||
1516 TLI.getOperationAction(
ISD::OR, VT) == TargetLowering::Expand)
1523 auto BoolContents = TLI.getBooleanContents(Op1.
getValueType());
1524 if (BoolContents != TargetLowering::ZeroOrNegativeOneBooleanContent &&
1525 !(BoolContents == TargetLowering::ZeroOrOneBooleanContent &&
1541 SDValue NotMask = DAG.getNOT(
DL, Mask, VT);
1563 if (TLI.getOperationAction(ISD::VP_AND, VT) == TargetLowering::Expand ||
1564 TLI.getOperationAction(ISD::VP_XOR, VT) == TargetLowering::Expand ||
1565 TLI.getOperationAction(ISD::VP_OR, VT) == TargetLowering::Expand)
1572 SDValue Ones = DAG.getAllOnesConstant(
DL, VT);
1575 Op1 = DAG.
getNode(ISD::VP_AND,
DL, VT, Op1, Mask, Ones, EVL);
1576 Op2 = DAG.
getNode(ISD::VP_AND,
DL, VT, Op2, NotMask, Ones, EVL);
1577 return DAG.getNode(ISD::VP_OR,
DL, VT, Op1, Op2, Ones, EVL);
1592 EVT MaskVT =
Mask.getValueType();
1608 if (TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
1609 EVLVecVT) != MaskVT)
1612 SDValue StepVec = DAG.getStepVector(
DL, EVLVecVT);
1613 SDValue SplatEVL = DAG.getSplat(EVLVecVT,
DL, EVL);
1615 DAG.getSetCC(
DL, MaskVT, StepVec, SplatEVL, ISD::CondCode::SETULT);
1618 return DAG.getSelect(
DL,
Node->getValueType(0), FullMask, Op1, Op2);
1623 EVT VT =
Node->getValueType(0);
1625 unsigned DivOpc =
Node->getOpcode() == ISD::VP_SREM ? ISD::VP_SDIV : ISD::VP_UDIV;
1627 if (!TLI.isOperationLegalOrCustom(DivOpc, VT) ||
1628 !TLI.isOperationLegalOrCustom(ISD::VP_MUL, VT) ||
1629 !TLI.isOperationLegalOrCustom(ISD::VP_SUB, VT))
1641 SDValue Mul = DAG.getNode(ISD::VP_MUL,
DL, VT, Divisor, Div, Mask, EVL);
1642 return DAG.getNode(ISD::VP_SUB,
DL, VT, Dividend,
Mul, Mask, EVL);
1646 EVT VT =
Node->getValueType(0);
1649 if (!TLI.isOperationLegalOrCustom(ISD::VP_XOR, IntVT))
1657 SDValue SignMask = DAG.getConstant(
1659 SDValue Xor = DAG.getNode(ISD::VP_XOR,
DL, IntVT, Cast, SignMask, Mask, EVL);
1664 EVT VT =
Node->getValueType(0);
1667 if (!TLI.isOperationLegalOrCustom(ISD::VP_AND, IntVT))
1675 SDValue ClearSignMask = DAG.getConstant(
1678 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Cast, ClearSignMask, Mask, EVL);
1683 EVT VT =
Node->getValueType(0);
1685 if (VT !=
Node->getOperand(1).getValueType())
1689 if (!TLI.isOperationLegalOrCustom(ISD::VP_AND, IntVT) ||
1690 !TLI.isOperationLegalOrCustom(ISD::VP_XOR, IntVT))
1700 SDValue SignMask = DAG.getConstant(
1703 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Sign, SignMask, Mask, EVL);
1705 SDValue ClearSignMask = DAG.getConstant(
1708 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Mag, ClearSignMask, Mask, EVL);
1710 SDValue CopiedSign = DAG.
getNode(ISD::VP_OR,
DL, IntVT, ClearedSign, SignBit,
1716void VectorLegalizer::ExpandFP_TO_UINT(
SDNode *
Node,
1720 if (TLI.expandFP_TO_UINT(
Node, Result, Chain, DAG)) {
1722 if (
Node->isStrictFPOpcode())
1728 if (
Node->isStrictFPOpcode()) {
1736void VectorLegalizer::ExpandUINT_TO_FLOAT(
SDNode *
Node,
1738 bool IsStrict =
Node->isStrictFPOpcode();
1739 unsigned OpNo = IsStrict ? 1 : 0;
1741 EVT VT = Src.getValueType();
1747 if (TLI.expandUINT_TO_FP(
Node, Result, Chain, DAG)) {
1756 TargetLowering::Expand) ||
1758 TargetLowering::Expand)) ||
1759 TLI.getOperationAction(
ISD::SRL, VT) == TargetLowering::Expand) {
1770 assert((BW == 64 || BW == 32) &&
1771 "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
1773 SDValue HalfWord = DAG.getConstant(BW / 2,
DL, VT);
1778 uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1779 SDValue HalfWordMask = DAG.getConstant(HWMask,
DL, VT);
1783 DAG.getConstantFP(1ULL << (BW / 2),
DL,
Node->getValueType(0));
1794 {
Node->getValueType(0), MVT::Other},
1795 {
Node->getOperand(0),
HI});
1799 {
Node->getValueType(0), MVT::Other},
1800 {
Node->getOperand(0),
LO});
1828 EVT VT =
Node->getValueType(0);
1831 if (!TLI.isOperationLegalOrCustom(
ISD::XOR, IntVT))
1835 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1841 SDValue SignMask = DAG.getConstant(
1848 EVT VT =
Node->getValueType(0);
1851 if (!TLI.isOperationLegalOrCustom(
ISD::AND, IntVT))
1855 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1861 SDValue ClearSignMask = DAG.getConstant(
1868 EVT VT =
Node->getValueType(0);
1871 if (VT !=
Node->getOperand(1).getValueType() ||
1872 !TLI.isOperationLegalOrCustom(
ISD::AND, IntVT) ||
1873 !TLI.isOperationLegalOrCustom(
ISD::OR, IntVT))
1877 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1885 SDValue SignMask = DAG.getConstant(
1889 SDValue ClearSignMask = DAG.getConstant(
1899void VectorLegalizer::ExpandFSUB(
SDNode *
Node,
1904 EVT VT =
Node->getValueType(0);
1905 if (TLI.isOperationLegalOrCustom(
ISD::FNEG, VT) &&
1906 TLI.isOperationLegalOrCustom(
ISD::FADD, VT))
1909 if (
SDValue Expanded = TLI.expandVectorNaryOpBySplitting(
Node, DAG)) {
1918void VectorLegalizer::ExpandSETCC(
SDNode *
Node,
1920 bool NeedInvert =
false;
1921 bool IsVP =
Node->getOpcode() == ISD::VP_SETCC;
1925 unsigned Offset = IsStrict ? 1 : 0;
1932 MVT OpVT =
LHS.getSimpleValueType();
1935 if (TLI.getCondCodeAction(CCCode, OpVT) != TargetLowering::Expand) {
1952 TLI.LegalizeSetCCCondCode(DAG,
Node->getValueType(0), LHS, RHS,
CC, Mask,
1953 EVL, NeedInvert, dl, Chain, IsSignaling);
1960 LHS = DAG.getNode(
Node->getOpcode(), dl,
Node->getVTList(),
1961 {Chain, LHS, RHS, CC},
Node->getFlags());
1962 Chain =
LHS.getValue(1);
1964 LHS = DAG.getNode(ISD::VP_SETCC, dl,
Node->getValueType(0),
1965 {LHS, RHS, CC, Mask, EVL},
Node->getFlags());
1976 LHS = DAG.getLogicalNOT(dl, LHS,
LHS->getValueType(0));
1978 LHS = DAG.getVPLogicalNOT(dl, LHS, Mask, EVL,
LHS->getValueType(0));
1981 assert(!IsStrict &&
"Don't know how to expand for strict nodes.");
1985 EVT VT =
Node->getValueType(0);
1988 DAG.getBoolConstant(
true, dl, VT,
LHS.getValueType()),
1989 DAG.getBoolConstant(
false, dl, VT,
LHS.getValueType()),
CC);
1990 LHS->setFlags(
Node->getFlags());
1998void VectorLegalizer::ExpandUADDSUBO(
SDNode *
Node,
2001 TLI.expandUADDSUBO(
Node, Result, Overflow, DAG);
2006void VectorLegalizer::ExpandSADDSUBO(
SDNode *
Node,
2009 TLI.expandSADDSUBO(
Node, Result, Overflow, DAG);
2014void VectorLegalizer::ExpandMULO(
SDNode *
Node,
2017 if (!TLI.expandMULO(
Node, Result, Overflow, DAG))
2018 std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(
Node);
2024void VectorLegalizer::ExpandFixedPointDiv(
SDNode *
Node,
2027 if (
SDValue Expanded = TLI.expandFixedPointDiv(
N->getOpcode(),
SDLoc(
N),
2028 N->getOperand(0),
N->getOperand(1),
N->getConstantOperandVal(2), DAG))
2032void VectorLegalizer::ExpandStrictFPOp(
SDNode *
Node,
2055 "Expected REM node");
2058 if (!TLI.expandREM(
Node, Result, DAG))
2073 assert(!
Node->isStrictFPOpcode() &&
"Unexpected strict fp operation!");
2075 const char *LCName = TLI.getLibcallName(LC);
2078 LLVM_DEBUG(
dbgs() <<
"Looking for vector variant of " << LCName <<
"\n");
2080 EVT VT =
Node->getValueType(0);
2098 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
2099 assert(
Node->getOperand(i).getValueType() == VT &&
2100 "Expected matching vector types!");
2103 FunctionType *ScalarFTy = FunctionType::get(ScalarTy, ArgTys,
false);
2115 if (OptVFInfo->Shape.Parameters.size() !=
2124 Entry.IsSExt =
false;
2125 Entry.IsZExt =
false;
2128 for (
auto &VFParam : OptVFInfo->Shape.Parameters) {
2129 if (VFParam.ParamKind == VFParamKind::GlobalPredicate) {
2130 EVT MaskVT = TLI.getSetCCResultType(DAG.getDataLayout(), *Ctx, VT);
2131 Entry.Node = DAG.getBoolConstant(
true,
DL, MaskVT, VT);
2133 Args.push_back(Entry);
2138 if (VFParam.ParamKind != VFParamKind::Vector)
2143 Args.push_back(Entry);
2148 TLI.getPointerTy(DAG.getDataLayout()));
2151 .setChain(DAG.getEntryNode())
2154 std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
2155 Results.push_back(CallResult.first);
2160bool VectorLegalizer::tryExpandVecMathCall(
2165 Node->getValueType(0).getVectorElementType(), Call_F32, Call_F64,
2166 Call_F80, Call_F128, Call_PPCF128);
2168 if (LC == RTLIB::UNKNOWN_LIBCALL)
2174void VectorLegalizer::UnrollStrictFPOp(
SDNode *
Node,
2176 EVT VT =
Node->getValueType(0);
2179 unsigned NumOpers =
Node->getNumOperands();
2182 EVT TmpEltVT = EltVT;
2186 *DAG.getContext(), TmpEltVT);
2188 EVT ValueVTs[] = {TmpEltVT, MVT::Other};
2194 for (
unsigned i = 0; i < NumElems; ++i) {
2196 SDValue Idx = DAG.getVectorIdxConstant(i, dl);
2202 for (
unsigned j = 1;
j < NumOpers; ++
j) {
2219 ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
2220 DAG.getAllOnesConstant(dl, EltVT),
2221 DAG.getConstant(0, dl, EltVT));
2235 EVT VT =
Node->getValueType(0);
2241 EVT TmpEltVT =
LHS.getValueType().getVectorElementType();
2244 for (
unsigned i = 0; i < NumElems; ++i) {
2246 DAG.getVectorIdxConstant(i, dl));
2248 DAG.getVectorIdxConstant(i, dl));
2251 *DAG.getContext(), TmpEltVT),
2252 LHSElem, RHSElem,
CC);
2253 Ops[i] = DAG.getSelect(dl, EltVT, Ops[i], DAG.getAllOnesConstant(dl, EltVT),
2254 DAG.getConstant(0, dl, EltVT));
2256 return DAG.getBuildVector(VT, dl, Ops);
2260 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.
@ 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)...
@ 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.
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.
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.