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);
506 Action = TLI.getOperationAction(
Node->getOpcode(),
507 Node->getOperand(0).getValueType());
511 Action = TLI.getOperationAction(
Node->getOpcode(),
512 Node->getOperand(1).getValueType());
515 MVT OpVT =
Node->getOperand(0).getSimpleValueType();
517 Action = TLI.getCondCodeAction(CCCode, OpVT);
518 if (Action == TargetLowering::Legal)
519 Action = TLI.getOperationAction(
Node->getOpcode(), OpVT);
523#define BEGIN_REGISTER_VP_SDNODE(VPID, LEGALPOS, ...) \
525 EVT LegalizeVT = LEGALPOS < 0 ? Node->getValueType(-(1 + LEGALPOS)) \
526 : Node->getOperand(LEGALPOS).getValueType(); \
527 if (ISD::VPID == ISD::VP_SETCC) { \
528 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get(); \
529 Action = TLI.getCondCodeAction(CCCode, LegalizeVT.getSimpleVT()); \
530 if (Action != TargetLowering::Legal) \
534 if (!Node->getValueType(0).isVector() && \
535 Node->getValueType(0) != MVT::Other) { \
536 Action = TargetLowering::Legal; \
539 Action = TLI.getOperationAction(Node->getOpcode(), LegalizeVT); \
541#include "llvm/IR/VPIntrinsics.def"
549 case TargetLowering::Promote:
551 "This action is not supported yet!");
553 Promote(
Node, ResultVals);
554 assert(!ResultVals.
empty() &&
"No results for promotion?");
556 case TargetLowering::Legal:
559 case TargetLowering::Custom:
561 if (LowerOperationWrapper(
Node, ResultVals))
565 case TargetLowering::Expand:
567 Expand(
Node, ResultVals);
571 if (ResultVals.
empty())
572 return TranslateLegalizeResults(
Op,
Node);
575 return RecursivelyLegalizeResults(
Op, ResultVals);
580bool VectorLegalizer::LowerOperationWrapper(
SDNode *
Node,
592 if (
Node->getNumValues() == 1) {
600 "Lowering returned the wrong number of results!");
603 for (
unsigned I = 0, E =
Node->getNumValues();
I != E; ++
I)
609void VectorLegalizer::PromoteSETCC(
SDNode *
Node,
611 MVT VecVT =
Node->getOperand(0).getSimpleValueType();
612 MVT NewVecVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VecVT);
619 Operands[0] = DAG.getNode(ExtOp,
DL, NewVecVT,
Node->getOperand(0));
620 Operands[1] = DAG.getNode(ExtOp,
DL, NewVecVT,
Node->getOperand(1));
623 if (
Node->getOpcode() == ISD::VP_SETCC) {
634void VectorLegalizer::PromoteSTRICT(
SDNode *
Node,
636 MVT VecVT =
Node->getOperand(1).getSimpleValueType();
637 MVT NewVecVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VecVT);
645 for (
unsigned j = 1;
j !=
Node->getNumOperands(); ++
j)
646 if (
Node->getOperand(j).getValueType().isVector() &&
653 {
Node->getOperand(0),
Node->getOperand(j)});
659 SDVTList VTs = DAG.getVTList(NewVecVT,
Node->getValueType(1));
669 DAG.getIntPtrConstant(0,
DL,
true)});
678 switch (
Node->getOpcode()) {
712 case ISD::VP_FCOPYSIGN:
724 "Can't promote a vector with multiple results!");
725 MVT VT =
Node->getSimpleValueType(0);
726 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
730 for (
unsigned j = 0;
j !=
Node->getNumOperands(); ++
j) {
734 if (
Node->getOperand(j).getValueType().isVector() && !SkipPromote)
735 if (
Node->getOperand(j)
737 .getVectorElementType()
738 .isFloatingPoint() &&
745 DAG.getNode(ISD::VP_FP_EXTEND, dl, NVT,
Node->getOperand(j),
746 Node->getOperand(MaskIdx),
Node->getOperand(EVLIdx));
766 Res = DAG.
getNode(ISD::VP_FP_ROUND, dl, VT, Res,
767 Node->getOperand(MaskIdx),
Node->getOperand(EVLIdx));
770 DAG.getIntPtrConstant(0, dl,
true));
778void VectorLegalizer::PromoteINT_TO_FP(
SDNode *
Node,
782 bool IsStrict =
Node->isStrictFPOpcode();
783 MVT VT =
Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
784 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
786 "Vectors have different number of elements!");
795 for (
unsigned j = 0;
j !=
Node->getNumOperands(); ++
j) {
796 if (
Node->getOperand(j).getValueType().isVector())
797 Operands[j] = DAG.getNode(Opc, dl, NVT,
Node->getOperand(j));
819void VectorLegalizer::PromoteFP_TO_INT(
SDNode *
Node,
821 MVT VT =
Node->getSimpleValueType(0);
822 MVT NVT = TLI.getTypeToPromoteTo(
Node->getOpcode(), VT);
823 bool IsStrict =
Node->isStrictFPOpcode();
825 "Vectors have different number of elements!");
827 unsigned NewOpc =
Node->getOpcode();
841 Promoted = DAG.
getNode(NewOpc, dl, {NVT, MVT::Other},
842 {
Node->getOperand(0),
Node->getOperand(1)});
845 Promoted = DAG.
getNode(NewOpc, dl, NVT,
Node->getOperand(0));
856 Promoted = DAG.
getNode(NewOpc, dl, NVT, Promoted,
864std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(
SDNode *
N) {
866 return TLI.scalarizeVectorLoad(LD, DAG);
871 SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
876 switch (
Node->getOpcode()) {
878 std::pair<SDValue, SDValue> Tmp = ExpandLoad(
Node);
887 for (
unsigned i = 0, e =
Node->getNumValues(); i != e; ++i)
897 Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(
Node));
900 Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(
Node));
903 Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(
Node));
945 case ISD::VP_FCOPYSIGN:
958 if (
Node->getValueType(0).isScalableVector()) {
959 EVT CondVT = TLI.getSetCCResultType(
960 DAG.getDataLayout(), *DAG.getContext(),
Node->getValueType(0));
963 Node->getOperand(1),
Node->getOperand(4));
966 Node->getOperand(3)));
1003 if (
SDValue Expanded = TLI.expandABS(
Node, DAG)) {
1010 if (
SDValue Expanded = TLI.expandABD(
Node, DAG)) {
1019 if (
SDValue Expanded = TLI.expandAVG(
Node, DAG)) {
1030 case ISD::VP_BITREVERSE:
1031 if (
SDValue Expanded = TLI.expandVPBITREVERSE(
Node, DAG)) {
1037 if (
SDValue Expanded = TLI.expandCTPOP(
Node, DAG)) {
1043 if (
SDValue Expanded = TLI.expandVPCTPOP(
Node, DAG)) {
1050 if (
SDValue Expanded = TLI.expandCTLZ(
Node, DAG)) {
1056 case ISD::VP_CTLZ_ZERO_UNDEF:
1057 if (
SDValue Expanded = TLI.expandVPCTLZ(
Node, DAG)) {
1064 if (
SDValue Expanded = TLI.expandCTTZ(
Node, DAG)) {
1070 case ISD::VP_CTTZ_ZERO_UNDEF:
1071 if (
SDValue Expanded = TLI.expandVPCTTZ(
Node, DAG)) {
1080 if (
SDValue Expanded = TLI.expandFunnelShift(
Node, DAG)) {
1087 if (
SDValue Expanded = TLI.expandROT(
Node,
false , DAG)) {
1094 if (
SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(
Node, DAG)) {
1101 Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(
Node, DAG));
1105 Results.push_back(TLI.expandFMINIMUMNUM_FMAXIMUMNUM(
Node, DAG));
1111 if (
SDValue Expanded = TLI.expandIntMINMAX(
Node, DAG)) {
1132 if (
SDValue Expanded = TLI.expandAddSubSat(
Node, DAG)) {
1139 if (
SDValue Expanded = TLI.expandShlSat(
Node, DAG)) {
1147 if (
Node->getValueType(0).isScalableVector()) {
1148 if (
SDValue Expanded = TLI.expandFP_TO_INT_SAT(
Node, DAG)) {
1156 if (
SDValue Expanded = TLI.expandFixedPointMul(
Node, DAG)) {
1175#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1176 case ISD::STRICT_##DAGN:
1177#include "llvm/IR/ConstrainedOps.def"
1195 Results.push_back(TLI.expandVecReduce(
Node, DAG));
1199 Results.push_back(TLI.expandVecReduceSeq(
Node, DAG));
1212 if (tryExpandVecMathCall(
Node, RTLIB::REM_F32, RTLIB::REM_F64,
1213 RTLIB::REM_F80, RTLIB::REM_F128,
1221 if (DAG.expandMultipleResultFPLibCall(LC,
Node,
Results))
1226 Results.push_back(TLI.expandVECTOR_COMPRESS(
Node, DAG));
1245 if (
SDValue Expanded = TLI.expandVectorNaryOpBySplitting(
Node, DAG)) {
1253 if (
Node->getNumValues() == 1) {
1257 "VectorLegalizer Expand returned wrong number of results!");
1267 EVT VT =
Node->getValueType(0);
1285 if (TLI.getOperationAction(
ISD::AND, VT) == TargetLowering::Expand ||
1286 TLI.getOperationAction(
ISD::XOR, VT) == TargetLowering::Expand ||
1287 TLI.getOperationAction(
ISD::OR, VT) == TargetLowering::Expand ||
1290 VT) == TargetLowering::Expand)
1299 Mask = DAG.getSelect(
DL, BitTy, Mask, DAG.getAllOnesConstant(
DL, BitTy),
1300 DAG.getConstant(0,
DL, BitTy));
1303 Mask = DAG.getSplat(MaskTy,
DL, Mask);
1311 SDValue NotMask = DAG.getNOT(
DL, Mask, MaskTy);
1320 EVT VT =
Node->getValueType(0);
1323 if (TLI.getOperationAction(
ISD::SRA, VT) == TargetLowering::Expand ||
1324 TLI.getOperationAction(
ISD::SHL, VT) == TargetLowering::Expand)
1328 EVT OrigTy = cast<VTSDNode>(
Node->getOperand(1))->getVT();
1332 SDValue ShiftSz = DAG.getConstant(BW - OrigBW,
DL, VT);
1342 EVT VT =
Node->getValueType(0);
1345 EVT SrcVT = Src.getValueType();
1352 "ANY_EXTEND_VECTOR_INREG vector size mismatch");
1357 Src, DAG.getVectorIdxConstant(0,
DL));
1362 ShuffleMask.
resize(NumSrcElements, -1);
1365 int ExtLaneScale = NumSrcElements / NumElements;
1366 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1367 for (
int i = 0; i < NumElements; ++i)
1368 ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
1372 DAG.getVectorShuffle(SrcVT,
DL, Src, DAG.getUNDEF(SrcVT), ShuffleMask));
1377 EVT VT =
Node->getValueType(0);
1379 EVT SrcVT = Src.getValueType();
1390 SDValue ShiftAmount = DAG.getConstant(EltWidth - SrcEltWidth,
DL, VT);
1401 EVT VT =
Node->getValueType(0);
1404 EVT SrcVT = Src.getValueType();
1411 "ZERO_EXTEND_VECTOR_INREG vector size mismatch");
1416 Src, DAG.getVectorIdxConstant(0,
DL));
1424 auto ShuffleMask = llvm::to_vector<16>(llvm::seq<int>(0, NumSrcElements));
1426 int ExtLaneScale = NumSrcElements / NumElements;
1427 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1428 for (
int i = 0; i < NumElements; ++i)
1429 ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
1432 DAG.getVectorShuffle(SrcVT,
DL, Zero, Src, ShuffleMask));
1438 for (
int J = ScalarSizeInBytes - 1; J >= 0; --J)
1439 ShuffleMask.
push_back((
I * ScalarSizeInBytes) + J);
1443 EVT VT =
Node->getValueType(0);
1447 return TLI.expandBSWAP(
Node, DAG);
1455 if (TLI.isShuffleMaskLegal(ShuffleMask, ByteVT)) {
1458 Op = DAG.getVectorShuffle(ByteVT,
DL,
Op, DAG.getUNDEF(ByteVT), ShuffleMask);
1464 if (TLI.isOperationLegalOrCustom(
ISD::SHL, VT) &&
1465 TLI.isOperationLegalOrCustom(
ISD::SRL, VT) &&
1466 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, VT) &&
1467 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, VT))
1468 return TLI.expandBSWAP(
Node, DAG);
1475 EVT VT =
Node->getValueType(0);
1479 return TLI.expandBITREVERSE(
Node, DAG);
1489 if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
1494 if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
1496 (TLI.isOperationLegalOrCustom(
ISD::SHL, ByteVT) &&
1497 TLI.isOperationLegalOrCustom(
ISD::SRL, ByteVT) &&
1498 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, ByteVT) &&
1499 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, ByteVT)))) {
1502 Op = DAG.getVectorShuffle(ByteVT,
DL,
Op, DAG.getUNDEF(ByteVT),
1512 if (TLI.isOperationLegalOrCustom(
ISD::SHL, VT) &&
1513 TLI.isOperationLegalOrCustom(
ISD::SRL, VT) &&
1514 TLI.isOperationLegalOrCustomOrPromote(
ISD::AND, VT) &&
1515 TLI.isOperationLegalOrCustomOrPromote(
ISD::OR, VT))
1516 return TLI.expandBITREVERSE(
Node, DAG);
1537 if (TLI.getOperationAction(
ISD::AND, VT) == TargetLowering::Expand ||
1538 TLI.getOperationAction(
ISD::XOR, VT) == TargetLowering::Expand ||
1539 TLI.getOperationAction(
ISD::OR, VT) == TargetLowering::Expand)
1546 auto BoolContents = TLI.getBooleanContents(Op1.
getValueType());
1547 if (BoolContents != TargetLowering::ZeroOrNegativeOneBooleanContent &&
1548 !(BoolContents == TargetLowering::ZeroOrOneBooleanContent &&
1564 SDValue NotMask = DAG.getNOT(
DL, Mask, VT);
1586 if (TLI.getOperationAction(ISD::VP_AND, VT) == TargetLowering::Expand ||
1587 TLI.getOperationAction(ISD::VP_XOR, VT) == TargetLowering::Expand ||
1588 TLI.getOperationAction(ISD::VP_OR, VT) == TargetLowering::Expand)
1595 SDValue Ones = DAG.getAllOnesConstant(
DL, VT);
1598 Op1 = DAG.
getNode(ISD::VP_AND,
DL, VT, Op1, Mask, Ones, EVL);
1599 Op2 = DAG.
getNode(ISD::VP_AND,
DL, VT, Op2, NotMask, Ones, EVL);
1600 return DAG.getNode(ISD::VP_OR,
DL, VT, Op1, Op2, Ones, EVL);
1615 EVT MaskVT =
Mask.getValueType();
1631 if (TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
1632 EVLVecVT) != MaskVT)
1635 SDValue StepVec = DAG.getStepVector(
DL, EVLVecVT);
1636 SDValue SplatEVL = DAG.getSplat(EVLVecVT,
DL, EVL);
1638 DAG.getSetCC(
DL, MaskVT, StepVec, SplatEVL, ISD::CondCode::SETULT);
1641 return DAG.getSelect(
DL,
Node->getValueType(0), FullMask, Op1, Op2);
1646 EVT VT =
Node->getValueType(0);
1648 unsigned DivOpc =
Node->getOpcode() == ISD::VP_SREM ? ISD::VP_SDIV : ISD::VP_UDIV;
1650 if (!TLI.isOperationLegalOrCustom(DivOpc, VT) ||
1651 !TLI.isOperationLegalOrCustom(ISD::VP_MUL, VT) ||
1652 !TLI.isOperationLegalOrCustom(ISD::VP_SUB, VT))
1664 SDValue Mul = DAG.getNode(ISD::VP_MUL,
DL, VT, Divisor, Div, Mask, EVL);
1665 return DAG.getNode(ISD::VP_SUB,
DL, VT, Dividend,
Mul, Mask, EVL);
1669 EVT VT =
Node->getValueType(0);
1672 if (!TLI.isOperationLegalOrCustom(ISD::VP_XOR, IntVT))
1680 SDValue SignMask = DAG.getConstant(
1682 SDValue Xor = DAG.getNode(ISD::VP_XOR,
DL, IntVT, Cast, SignMask, Mask, EVL);
1687 EVT VT =
Node->getValueType(0);
1690 if (!TLI.isOperationLegalOrCustom(ISD::VP_AND, IntVT))
1698 SDValue ClearSignMask = DAG.getConstant(
1701 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Cast, ClearSignMask, Mask, EVL);
1706 EVT VT =
Node->getValueType(0);
1708 if (VT !=
Node->getOperand(1).getValueType())
1712 if (!TLI.isOperationLegalOrCustom(ISD::VP_AND, IntVT) ||
1713 !TLI.isOperationLegalOrCustom(ISD::VP_XOR, IntVT))
1723 SDValue SignMask = DAG.getConstant(
1726 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Sign, SignMask, Mask, EVL);
1728 SDValue ClearSignMask = DAG.getConstant(
1731 DAG.
getNode(ISD::VP_AND,
DL, IntVT, Mag, ClearSignMask, Mask, EVL);
1733 SDValue CopiedSign = DAG.
getNode(ISD::VP_OR,
DL, IntVT, ClearedSign, SignBit,
1739void VectorLegalizer::ExpandFP_TO_UINT(
SDNode *
Node,
1743 if (TLI.expandFP_TO_UINT(
Node, Result, Chain, DAG)) {
1745 if (
Node->isStrictFPOpcode())
1751 if (
Node->isStrictFPOpcode()) {
1759void VectorLegalizer::ExpandUINT_TO_FLOAT(
SDNode *
Node,
1761 bool IsStrict =
Node->isStrictFPOpcode();
1762 unsigned OpNo = IsStrict ? 1 : 0;
1764 EVT SrcVT = Src.getValueType();
1765 EVT DstVT =
Node->getValueType(0);
1771 if (TLI.expandUINT_TO_FP(
Node, Result, Chain, DAG)) {
1780 TargetLowering::Expand) ||
1782 TargetLowering::Expand)) ||
1783 TLI.getOperationAction(
ISD::SRL, SrcVT) == TargetLowering::Expand) {
1794 assert((BW == 64 || BW == 32) &&
1795 "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
1799 if ((!IsStrict && !TLI.isOperationLegalOrCustom(
ISD::FMUL, DstVT)) ||
1801 EVT FPVT = BW == 32 ? MVT::f32 : MVT::f64;
1804 SDValue TargetZero = DAG.getIntPtrConstant(0,
DL,
true);
1808 {
Node->getOperand(0), Src});
1810 {
Node->getOperand(0), UIToFP, TargetZero});
1822 SDValue HalfWord = DAG.getConstant(BW / 2,
DL, SrcVT);
1827 uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1828 SDValue HalfWordMask = DAG.getConstant(HWMask,
DL, SrcVT);
1831 SDValue TWOHW = DAG.getConstantFP(1ULL << (BW / 2),
DL, DstVT);
1842 {
Node->getOperand(0),
HI});
1846 {
Node->getOperand(0),
LO});
1872 EVT VT =
Node->getValueType(0);
1875 if (!TLI.isOperationLegalOrCustom(
ISD::XOR, IntVT))
1879 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1885 SDValue SignMask = DAG.getConstant(
1892 EVT VT =
Node->getValueType(0);
1895 if (!TLI.isOperationLegalOrCustom(
ISD::AND, IntVT))
1899 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1905 SDValue ClearSignMask = DAG.getConstant(
1912 EVT VT =
Node->getValueType(0);
1915 if (VT !=
Node->getOperand(1).getValueType() ||
1916 !TLI.isOperationLegalOrCustom(
ISD::AND, IntVT) ||
1917 !TLI.isOperationLegalOrCustom(
ISD::OR, IntVT))
1921 if (!TLI.isOperationLegalOrCustomOrPromote(
ISD::FSUB, VT) &&
1929 SDValue SignMask = DAG.getConstant(
1933 SDValue ClearSignMask = DAG.getConstant(
1943void VectorLegalizer::ExpandFSUB(
SDNode *
Node,
1948 EVT VT =
Node->getValueType(0);
1949 if (TLI.isOperationLegalOrCustom(
ISD::FNEG, VT) &&
1950 TLI.isOperationLegalOrCustom(
ISD::FADD, VT))
1953 if (
SDValue Expanded = TLI.expandVectorNaryOpBySplitting(
Node, DAG)) {
1962void VectorLegalizer::ExpandSETCC(
SDNode *
Node,
1964 bool NeedInvert =
false;
1965 bool IsVP =
Node->getOpcode() == ISD::VP_SETCC;
1969 unsigned Offset = IsStrict ? 1 : 0;
1976 MVT OpVT =
LHS.getSimpleValueType();
1979 if (TLI.getCondCodeAction(CCCode, OpVT) != TargetLowering::Expand) {
1996 TLI.LegalizeSetCCCondCode(DAG,
Node->getValueType(0), LHS, RHS,
CC, Mask,
1997 EVL, NeedInvert, dl, Chain, IsSignaling);
2004 LHS = DAG.getNode(
Node->getOpcode(), dl,
Node->getVTList(),
2005 {Chain, LHS, RHS, CC},
Node->getFlags());
2006 Chain =
LHS.getValue(1);
2008 LHS = DAG.getNode(ISD::VP_SETCC, dl,
Node->getValueType(0),
2009 {LHS, RHS, CC, Mask, EVL},
Node->getFlags());
2020 LHS = DAG.getLogicalNOT(dl, LHS,
LHS->getValueType(0));
2022 LHS = DAG.getVPLogicalNOT(dl, LHS, Mask, EVL,
LHS->getValueType(0));
2025 assert(!IsStrict &&
"Don't know how to expand for strict nodes.");
2029 EVT VT =
Node->getValueType(0);
2032 DAG.getBoolConstant(
true, dl, VT,
LHS.getValueType()),
2033 DAG.getBoolConstant(
false, dl, VT,
LHS.getValueType()),
CC);
2034 LHS->setFlags(
Node->getFlags());
2042void VectorLegalizer::ExpandUADDSUBO(
SDNode *
Node,
2045 TLI.expandUADDSUBO(
Node, Result, Overflow, DAG);
2050void VectorLegalizer::ExpandSADDSUBO(
SDNode *
Node,
2053 TLI.expandSADDSUBO(
Node, Result, Overflow, DAG);
2058void VectorLegalizer::ExpandMULO(
SDNode *
Node,
2061 if (!TLI.expandMULO(
Node, Result, Overflow, DAG))
2062 std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(
Node);
2068void VectorLegalizer::ExpandFixedPointDiv(
SDNode *
Node,
2071 if (
SDValue Expanded = TLI.expandFixedPointDiv(
N->getOpcode(),
SDLoc(
N),
2072 N->getOperand(0),
N->getOperand(1),
N->getConstantOperandVal(2), DAG))
2076void VectorLegalizer::ExpandStrictFPOp(
SDNode *
Node,
2099 "Expected REM node");
2102 if (!TLI.expandREM(
Node, Result, DAG))
2117 assert(!
Node->isStrictFPOpcode() &&
"Unexpected strict fp operation!");
2119 const char *LCName = TLI.getLibcallName(LC);
2122 LLVM_DEBUG(
dbgs() <<
"Looking for vector variant of " << LCName <<
"\n");
2124 EVT VT =
Node->getValueType(0);
2142 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
2143 assert(
Node->getOperand(i).getValueType() == VT &&
2144 "Expected matching vector types!");
2147 FunctionType *ScalarFTy = FunctionType::get(ScalarTy, ArgTys,
false);
2159 if (OptVFInfo->Shape.Parameters.size() !=
2168 Entry.IsSExt =
false;
2169 Entry.IsZExt =
false;
2172 for (
auto &VFParam : OptVFInfo->Shape.Parameters) {
2173 if (VFParam.ParamKind == VFParamKind::GlobalPredicate) {
2174 EVT MaskVT = TLI.getSetCCResultType(DAG.getDataLayout(), *Ctx, VT);
2175 Entry.Node = DAG.getBoolConstant(
true,
DL, MaskVT, VT);
2177 Args.push_back(Entry);
2182 if (VFParam.ParamKind != VFParamKind::Vector)
2187 Args.push_back(Entry);
2192 TLI.getPointerTy(DAG.getDataLayout()));
2195 .setChain(DAG.getEntryNode())
2198 std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
2199 Results.push_back(CallResult.first);
2204bool VectorLegalizer::tryExpandVecMathCall(
2209 Node->getValueType(0).getVectorElementType(), Call_F32, Call_F64,
2210 Call_F80, Call_F128, Call_PPCF128);
2212 if (LC == RTLIB::UNKNOWN_LIBCALL)
2218void VectorLegalizer::UnrollStrictFPOp(
SDNode *
Node,
2220 EVT VT =
Node->getValueType(0);
2223 unsigned NumOpers =
Node->getNumOperands();
2226 EVT TmpEltVT = EltVT;
2230 *DAG.getContext(), TmpEltVT);
2232 EVT ValueVTs[] = {TmpEltVT, MVT::Other};
2238 for (
unsigned i = 0; i < NumElems; ++i) {
2240 SDValue Idx = DAG.getVectorIdxConstant(i, dl);
2246 for (
unsigned j = 1;
j < NumOpers; ++
j) {
2263 ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
2264 DAG.getAllOnesConstant(dl, EltVT),
2265 DAG.getConstant(0, dl, EltVT));
2279 EVT VT =
Node->getValueType(0);
2285 EVT TmpEltVT =
LHS.getValueType().getVectorElementType();
2288 for (
unsigned i = 0; i < NumElems; ++i) {
2290 DAG.getVectorIdxConstant(i, dl));
2292 DAG.getVectorIdxConstant(i, dl));
2296 *DAG.getContext(), TmpEltVT),
2297 LHSElem, RHSElem,
CC);
2298 Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
2299 DAG.getBoolConstant(
true, dl, EltVT, VT),
2300 DAG.getConstant(0, dl, EltVT));
2302 return DAG.getBuildVector(VT, dl, Ops);
2306 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)...
@ 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.