21#include "llvm/IR/IntrinsicsHexagon.h"
32 cl::desc(
"Lower threshold (in bytes) for widening to HVX vectors"));
44 return std::make_tuple(5, 15, 10);
46 return std::make_tuple(8, 127, 23);
48 return std::make_tuple(11, 1023, 52);
56HexagonTargetLowering::initializeHVXLowering() {
102 auto setPromoteTo = [
this] (
unsigned Opc,
MVT FromTy,
MVT ToTy) {
126 for (
MVT T : FloatV) {
161 for (
MVT P : FloatW) {
191 for (
MVT T : LegalV) {
268 for (
MVT T : LegalW) {
367 for (
MVT T : LegalW) {
384 for (
MVT T : LegalV) {
411 int ElemWidth = ElemTy.getFixedSizeInBits();
412 int MaxElems = (8*HwLen) / ElemWidth;
413 for (
int N = 2;
N < MaxElems;
N *= 2) {
442HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
448 if (ElemTy ==
MVT::i1 && VecLen > HwLen)
469 unsigned HwWidth = 8*HwLen;
470 if (VecWidth > 2*HwWidth)
476 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
485HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &Op)
const {
486 unsigned Opc =
Op.getOpcode();
506HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
507 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
511 Tys.second.getVectorNumElements());
514HexagonTargetLowering::TypePair
515HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
518 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
520 return { HalfTy, HalfTy };
524HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
531HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
538HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
547HexagonTargetLowering::opJoin(
const VectorPair &Ops,
const SDLoc &dl,
550 Ops.first, Ops.second);
553HexagonTargetLowering::VectorPair
554HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
556 TypePair Tys = typeSplit(ty(Vec));
559 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
563HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
569HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
575HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
580bool HexagonTargetLowering::allowsHvxMemoryAccess(
595bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
605void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
607 unsigned Opc =
MI.getOpcode();
613 auto At =
MI.getIterator();
616 case Hexagon::PS_vsplatib:
620 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
622 .
add(
MI.getOperand(1));
624 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
629 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
634 .
addImm(V << 24 | V << 16 | V << 8 | V);
640 case Hexagon::PS_vsplatrb:
644 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
645 .
add(
MI.getOperand(1));
647 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
649 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
652 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
657 case Hexagon::PS_vsplatih:
661 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
663 .
add(
MI.getOperand(1));
665 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
670 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
681 case Hexagon::PS_vsplatrh:
685 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
686 .
add(
MI.getOperand(1));
690 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
692 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
700 case Hexagon::PS_vsplatiw:
701 case Hexagon::PS_vsplatrw:
702 if (Opc == Hexagon::PS_vsplatiw) {
704 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
706 .
add(
MI.getOperand(1));
707 MI.getOperand(1).ChangeToRegister(SplatV,
false);
710 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
716HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
726 const SDLoc &dl(ElemIdx);
732HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
735 assert(ElemWidth >= 8 && ElemWidth <= 32);
748HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
765 for (
unsigned I = 0;
I != ElemSize; ++
I)
768 int NewM =
M*ElemSize;
769 for (
unsigned I = 0;
I != ElemSize; ++
I)
775 opCastElem(Op1,
MVT::i8, DAG), ByteMask);
782 unsigned VecLen = Values.
size();
788 unsigned ElemSize = ElemWidth / 8;
789 assert(ElemSize*VecLen == HwLen);
795 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
796 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
798 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
799 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
807 unsigned NumValues = Values.size();
810 for (
unsigned i = 0; i != NumValues; ++i) {
811 if (Values[i].isUndef())
814 if (!SplatV.getNode())
816 else if (SplatV != Values[i])
824 unsigned NumWords = Words.
size();
826 bool IsSplat =
isSplat(Words, SplatV);
827 if (IsSplat && isUndef(SplatV))
831 auto *IdxN = dyn_cast<ConstantSDNode>(SplatV.
getNode());
832 if (IdxN && IdxN->isZero())
833 return getZero(dl, VecTy, DAG);
842 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
847 Align Alignment(HwLen);
861 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
866 SrcIdx.push_back(-1);
879 int I =
C->getSExtValue();
880 assert(
I >= 0 &&
"Negative element index");
889 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
890 MVT ExtTy = ty(ExtVec);
892 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
899 for (
int M : ExtIdx) {
909 for (
unsigned I = 0;
I != ExtLen; ++
I) {
910 if (
Mask.size() == ExtLen)
918 return ExtLen == VecLen ? S : LoHalf(S, DAG);
929 for (
unsigned i = 0; i != NumWords; ++i) {
931 if (Words[i].isUndef())
933 for (
unsigned j = i;
j != NumWords; ++
j)
934 if (Words[i] == Words[j])
937 if (VecHist[i] > VecHist[n])
941 SDValue HalfV = getZero(dl, VecTy, DAG);
942 if (VecHist[n] > 1) {
957 for (
unsigned i = 0; i != NumWords/2; ++i) {
959 if (Words[i] != Words[n] || VecHist[n] <= 1) {
966 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
970 {HalfV1, Words[i+NumWords/2]});
993HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
994 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
995 MVT PredTy = ty(PredV);
1014 for (
unsigned i = 0; i != HwLen; ++i) {
1015 unsigned Num = i % Scale;
1016 unsigned Off = i / Scale;
1025 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1027 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1046 while (Bytes < BitBytes) {
1048 Words[IdxW].
clear();
1051 for (
const SDValue &W : Words[IdxW ^ 1]) {
1052 SDValue T = expandPredicate(W, dl, DAG);
1057 for (
const SDValue &W : Words[IdxW ^ 1]) {
1065 assert(Bytes == BitBytes);
1067 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1069 for (
const SDValue &W : Words[IdxW]) {
1083 unsigned VecLen = Values.
size();
1085 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1087 bool AllT =
true, AllF =
true;
1090 if (
const auto *
N = dyn_cast<ConstantSDNode>(
V.getNode()))
1091 return !
N->isZero();
1095 if (
const auto *
N = dyn_cast<ConstantSDNode>(
V.getNode()))
1100 if (VecLen <= HwLen) {
1104 assert(HwLen % VecLen == 0);
1105 unsigned BitBytes = HwLen / VecLen;
1112 for (
unsigned B = 0;
B != BitBytes; ++
B)
1119 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1122 for (;
B != 8; ++
B) {
1123 if (!Values[
I+
B].isUndef())
1136 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1146 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1151HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1156 assert(ElemWidth >= 8 && ElemWidth <= 32);
1159 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1168 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1171 return extractVector(ExVec, SubIdx, dl, ElemTy,
MVT::i32, DAG);
1175HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1188 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl,
MVT::i32, DAG);
1190 return getInstr(Hexagon::C2_cmpgtui, dl,
MVT::i1, {ExtB,
Zero}, DAG);
1194HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1199 assert(ElemWidth >= 8 && ElemWidth <= 32);
1204 MVT VecTy = ty(VecV);
1216 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1218 return InsertWord(VecV, ValV, ByteIdx);
1229 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1230 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1232 ValV, SubIdx, dl, ElemTy, DAG);
1235 return InsertWord(VecV, Ins, ByteIdx);
1239HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1250 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1255HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1257 MVT VecTy = ty(VecV);
1259 unsigned Idx = cast<ConstantSDNode>(IdxV.
getNode())->getZExtValue();
1266 if (isHvxPairTy(VecTy)) {
1267 if (
Idx * ElemWidth >= 8*HwLen)
1271 if (typeSplit(VecTy).first == ResTy)
1281 unsigned WordIdx = (
Idx*ElemWidth) / 32;
1295HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1297 MVT VecTy = ty(VecV);
1302 unsigned Idx = cast<ConstantSDNode>(IdxV.
getNode())->getZExtValue();
1317 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1318 for (
unsigned j = 0;
j != Rep; ++
j)
1335 unsigned Rep = 8 / ResLen;
1338 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1340 for (
unsigned i = 0; i != ResLen; ++i) {
1341 for (
unsigned j = 0;
j != Rep; ++
j)
1354 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1359HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1361 MVT VecTy = ty(VecV);
1362 MVT SubTy = ty(SubV);
1367 bool IsPair = isHvxPairTy(VecTy);
1375 V0 = LoHalf(VecV, DAG);
1376 V1 = HiHalf(VecV, DAG);
1381 if (isHvxSingleTy(SubTy)) {
1382 if (
const auto *CN = dyn_cast<const ConstantSDNode>(IdxV.
getNode())) {
1383 unsigned Idx = CN->getZExtValue();
1385 unsigned SubIdx = (
Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1407 auto *IdxN = dyn_cast<ConstantSDNode>(IdxV.
getNode());
1408 if (!IdxN || !IdxN->isZero()) {
1416 unsigned RolBase = HwLen;
1431 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1446HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1448 MVT VecTy = ty(VecV);
1449 MVT SubTy = ty(SubV);
1456 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1459 unsigned BitBytes = HwLen / VecLen;
1460 unsigned BlockLen = HwLen / Scale;
1464 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1467 auto *IdxN = dyn_cast<ConstantSDNode>(IdxV.
getNode());
1468 if (!IdxN || !IdxN->isZero()) {
1477 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1479 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1481 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1483 if (!IdxN || !IdxN->isZero()) {
1492HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1504 SDValue False = getZero(dl, ResTy, DAG);
1505 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1509HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1519 MVT PredTy = ty(VecQ);
1521 assert(HwLen % PredLen == 0);
1528 for (
unsigned i = 0; i != HwLen/8; ++i) {
1529 for (
unsigned j = 0;
j != 8; ++
j)
1533 Align Alignment(HwLen);
1542 getZero(dl, VecTy, DAG));
1548 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1550 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1558 for (
unsigned i = 0; i != HwLen; ++i)
1559 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1569 MVT InpTy = ty(VecV);
1584 if (InpWidth < ResWidth) {
1586 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1594HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1598 const SDLoc &dl(Vec);
1607 const SDLoc &dl(Op);
1610 unsigned Size =
Op.getNumOperands();
1612 for (
unsigned i = 0; i !=
Size; ++i)
1620 MVT SingleTy = typeSplit(VecTy).first;
1621 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size/2), dl, SingleTy, DAG);
1622 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size/2), dl, SingleTy, DAG);
1627 return buildHvxVectorPred(Ops, dl, VecTy, DAG);
1634 for (
unsigned i = 0; i !=
Size; i++)
1638 tyVector(VecTy,
MVT::i16), NewOps);
1642 return buildHvxVectorReg(Ops, dl, VecTy, DAG);
1648 const SDLoc &dl(Op);
1650 MVT ArgTy = ty(
Op.getOperand(0));
1670 const SDLoc &dl(Op);
1671 unsigned NumOp =
Op.getNumOperands();
1684 for (
unsigned i = 0, e = Elems.
size(); i != e; ++i) {
1688 MVT NTy = typeLegalize(Ty, DAG);
1692 V.getOperand(0),
V.getOperand(1)),
1697 switch (
V.getOpcode()) {
1705 Elems[i] =
V.getOperand(0);
1731 MVT HalfTy = typeSplit(VecTy).first;
1733 Ops.take_front(NumOp/2));
1735 Ops.take_back(NumOp/2));
1744 for (
SDValue V :
Op.getNode()->op_values()) {
1745 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1752 SDValue Res = getZero(dl, ByteTy, DAG);
1753 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1766 const SDLoc &dl(Op);
1769 return extractHvxElementPred(VecV, IdxV, dl, ty(Op), DAG);
1771 return extractHvxElementReg(VecV, IdxV, dl, ty(Op), DAG);
1777 const SDLoc &dl(Op);
1784 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1794 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1801 MVT SrcTy = ty(SrcV);
1804 unsigned Idx = cast<ConstantSDNode>(IdxV.
getNode())->getZExtValue();
1807 const SDLoc &dl(Op);
1811 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1813 return extractHvxSubvectorReg(Op, SrcV, IdxV, dl, DstTy, DAG);
1824 const SDLoc &dl(Op);
1825 MVT VecTy = ty(VecV);
1828 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1830 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1843 return LowerHvxSignExt(Op, DAG);
1853 return extendHvxVectorPred(InpV,
SDLoc(Op), ty(Op),
false, DAG);
1863 return extendHvxVectorPred(InpV,
SDLoc(Op), ty(Op),
true, DAG);
1871 const SDLoc &dl(Op);
1874 assert(ResTy == ty(InpV));
1899 const SDLoc &dl(Op);
1907 unsigned Opc =
Op.getOpcode();
1923 const SDLoc &dl(Op);
1924 unsigned Opc =
Op.getOpcode();
1929 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
1942 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1947 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
1948 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
1954 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1961 MVT ValTy = ty(Val);
1962 const SDLoc &dl(Op);
1967 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
1982 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
1989 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2014 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2018 for (
unsigned J = 0; J != 8; ++J) {
2026 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2050 const SDLoc &dl(Op);
2053 assert(HwLen % VecLen == 0);
2054 unsigned ElemSize = HwLen / VecLen;
2066 if (
SDValue S = getVectorShiftByInt(Op, DAG))
2072HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2074 unsigned Opc =
Op.getOpcode();
2086 const SDLoc &dl(Op);
2092 bool UseShifts = ElemTy !=
MVT::i8;
2096 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2120 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2123 return DAG.
getNode(MOpc, dl, ty(Op),
2129 const SDLoc &dl(Op);
2130 unsigned IntNo = cast<ConstantSDNode>(
Op.getOperand(0))->getZExtValue();
2138 case Intrinsic::hexagon_V6_pred_typecast:
2139 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2140 MVT ResTy = ty(Op), InpTy = ty(Ops[1]);
2141 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2148 case Intrinsic::hexagon_V6_vmpyss_parts:
2149 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2152 case Intrinsic::hexagon_V6_vmpyuu_parts:
2153 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2156 case Intrinsic::hexagon_V6_vmpyus_parts:
2157 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2168 const SDLoc &dl(Op);
2171 auto *MaskN = cast<MaskedLoadStoreSDNode>(
Op.getNode());
2173 SDValue Chain = MaskN->getChain();
2177 unsigned Opc =
Op->getOpcode();
2183 SDValue Thru = cast<MaskedLoadSDNode>(MaskN)->getPassThru();
2194 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2195 SDValue Value = cast<MaskedStoreSDNode>(MaskN)->getValue();
2198 if (MaskN->getAlign().value() % HwLen == 0) {
2207 SDValue Z = getZero(dl, ty(V), DAG);
2211 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2212 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2213 return std::make_pair(LoV, HiV);
2219 VectorPair Tmp = StoreAlign(MaskV,
Base);
2222 VectorPair ValueU = StoreAlign(
Value,
Base);
2227 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2230 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2232 DAG.
setNodeMemRefs(cast<MachineSDNode>(StoreHi.getNode()), {MemOp});
2245 MVT ArgTy = ty(
Op.getOperand(0));
2246 const SDLoc &dl(Op);
2256 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2258 MVT HalfTy = typeSplit(VecTy).first;
2259 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2261 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2263 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2266 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2294 return EqualizeFpIntConversion(Op, DAG);
2296 return ExpandHvxFpToInt(Op, DAG);
2321 return EqualizeFpIntConversion(Op, DAG);
2323 return ExpandHvxIntToFp(Op, DAG);
2326HexagonTargetLowering::TypePair
2327HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2338 unsigned MaxWidth = std::max(Width0, Width1);
2340 auto getScalarWithWidth = [](
MVT ScalarTy,
unsigned Width) {
2347 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2348 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2352 return {WideETy0, WideETy1};
2363HexagonTargetLowering::TypePair
2364HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2374 unsigned MaxLen = std::max(Len0, Len1);
2387HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2397HexagonTargetLowering::VectorPair
2428HexagonTargetLowering::VectorPair
2429HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2434 const SDLoc &dl(Val);
2435 MVT ValTy = ty(Val);
2449 MVT IntTy = tyVector(ValTy, ElemTy);
2461 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2506 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2508 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A, S16}, DAG);
2516 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2518 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2521 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2522 {HiHalf(P2, DAG), LoHalf(P1, DAG), S16}, DAG);
2523 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B, S16}, DAG);
2534HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2535 bool SignedB,
const SDLoc &dl,
2543 if (SignedA && !SignedB) {
2559 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2561 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2570 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2573 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG), S16}, DAG);
2577 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2578 {HiHalf(P2, DAG), T3, S16}, DAG);
2581 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2582 {LoHalf(P0, DAG), LoHalf(P2, DAG), S16}, DAG);
2586 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2593 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2594 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2595 }
else if (SignedB) {
2601 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2603 assert(!SignedA && !SignedB);
2610HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2618 if (SignedA && !SignedB) {
2625 SDValue P0 = getInstr(Hexagon::V6_vmpyewuh_64, dl,
PairTy, {
A,
B}, DAG);
2627 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {P0,
A,
B}, DAG);
2632 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2644 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2645 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2646 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2647 }
else if (!SignedA) {
2657 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2675 unsigned Opc =
Op.getOpcode();
2680 MVT InpTy = ty(Inp);
2686 const SDLoc &dl(Op);
2689 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2698 unsigned Opc =
Op.getOpcode();
2701 const SDLoc &dl(Op);
2703 MVT InpTy = ty(Op0);
2783 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
2784 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
2827 unsigned Opc =
Op.getOpcode();
2830 const SDLoc &dl(Op);
2832 MVT InpTy = ty(Op0);
2865 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
2875 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
2898 unsigned Opc =
Op.getOpcode();
2915 const SDLoc &dl(Op);
2916 return DAG.
getNode(TLOpc, dl, ty(Op),
Op.getOperand(0),
2925 unsigned Opc = cast<ConstantSDNode>(
Op.getOperand(2))->getZExtValue();
2929HexagonTargetLowering::VectorPair
2933 const SDLoc &dl(Op);
2935 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
2936 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
2938 return std::make_pair(TV, TV);
2945 switch (
Op.getOpcode()) {
2949 if (
const auto *
N = dyn_cast<const VTSDNode>(
A.getNode()))
2950 std::tie(
Lo,
Hi) = SplitVTNode(
N);
2958 MVT HalfTy = typeSplit(ResTy).first;
2966 auto *MemN = cast<MemSDNode>(
Op.getNode());
2968 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
2969 if (!isHvxPairTy(MemTy))
2972 const SDLoc &dl(Op);
2974 MVT SingleTy = typeSplit(MemTy).first;
2975 SDValue Chain = MemN->getChain();
2976 SDValue Base0 = MemN->getBasePtr();
2991 assert(cast<LoadSDNode>(Op)->isUnindexed());
3000 assert(cast<StoreSDNode>(Op)->isUnindexed());
3001 VectorPair Vals = opSplit(cast<StoreSDNode>(Op)->getValue(), dl, DAG);
3009 auto MaskN = cast<MaskedLoadStoreSDNode>(Op);
3010 assert(MaskN->isUnindexed());
3011 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3016 opSplit(cast<MaskedLoadSDNode>(Op)->getPassThru(), dl, DAG);
3031 VectorPair Vals = opSplit(cast<MaskedStoreSDNode>(Op)->getValue(), dl, DAG);
3033 Masks.first, SingleTy, MOp0,
3036 Masks.second, SingleTy, MOp1,
3041 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3047 const SDLoc &dl(Op);
3048 auto *LoadN = cast<LoadSDNode>(
Op.getNode());
3049 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3050 assert(LoadN->getMemoryVT().getVectorElementType() !=
MVT::i1 &&
3051 "Not widening loads of i1 yet");
3053 SDValue Chain = LoadN->getChain();
3060 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3063 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3079 const SDLoc &dl(Op);
3080 auto *StoreN = cast<StoreSDNode>(
Op.getNode());
3081 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3082 assert(StoreN->getMemoryVT().getVectorElementType() !=
MVT::i1 &&
3083 "Not widening stores of i1 yet");
3085 SDValue Chain = StoreN->getChain();
3095 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3099 assert(ty(
Value).getVectorNumElements() == HwLen);
3101 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3103 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3106 auto *
MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3113 const SDLoc &dl(Op);
3114 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3124 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3125 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3129 {WideOp0, WideOp1,
Op.getOperand(2)});
3131 EVT RetTy = typeLegalize(ty(Op), DAG);
3133 {SetCC, getZero(dl,
MVT::i32, DAG)});
3138 unsigned Opc =
Op.getOpcode();
3139 bool IsPairOp = isHvxPairTy(ty(Op)) ||
3141 return isHvxPairTy(ty(V));
3152 return SplitHvxMemOp(Op, DAG);
3158 return opJoin(SplitVectorOp(Op, DAG),
SDLoc(Op), DAG);
3188 return opJoin(SplitVectorOp(Op, DAG),
SDLoc(Op), DAG);
3194 return opJoin(SplitVectorOp(Op, DAG),
SDLoc(Op), DAG);
3213 case ISD::CTTZ:
return LowerHvxCttz(Op, DAG);
3217 case ISD::SRL:
return LowerHvxShift(Op, DAG);
3219 case ISD::FSHR:
return LowerHvxFunnelShift(Op, DAG);
3221 case ISD::MULHU:
return LowerHvxMulh(Op, DAG);
3229 case ISD::MSTORE:
return LowerHvxMaskedOp(Op, DAG);
3258 unsigned Opc =
Op.getOpcode();
3278 MVT InpTy = ty(Inp);
3283 assert(InpWidth != ResWidth);
3285 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3288 const SDLoc &dl(Op);
3292 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3300 return DAG.
getNode(Opc, dl, Ty, {
Arg,
Op.getOperand(1),
Op.getOperand(2)});
3307 if (InpWidth < ResWidth) {
3309 while (InpWidth * 2 <= ResWidth)
3310 S = repeatOp(InpWidth *= 2, S);
3314 while (InpWidth / 2 >= ResWidth)
3315 S = repeatOp(InpWidth /= 2, S);
3323 MVT InpTy = ty(Inp0);
3327 unsigned Opc =
Op.getOpcode();
3329 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3334 auto [WInpTy, WResTy] =
3335 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3336 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3337 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3345 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3346 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3347 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3348 return opJoin(SplitVectorOp(Op, DAG),
SDLoc(Op), DAG);
3351 return RemoveTLWrapper(Op, DAG);
3357HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3359 unsigned Opc =
N->getOpcode();
3362 if (
N->getNumOperands() > 0)
3363 Inp0 =
Op.getOperand(0);
3372 Results.push_back(CreateTLWrapper(Op, DAG));
3376 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3377 if (
SDValue T = WidenHvxSetCC(Op, DAG))
3382 if (shouldWidenToHvx(ty(cast<StoreSDNode>(
N)->getValue()), DAG)) {
3389 if (isHvxPairTy(ty(Op))) {
3390 SDValue S = SplitHvxMemOp(Op, DAG);
3397 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3398 SDValue S = SplitHvxMemOp(Op, DAG);
3406 if (ty(Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3407 SDValue T = EqualizeFpIntConversion(Op, DAG);
3415 Results.push_back(LegalizeHvxResize(Op, DAG));
3423HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3425 unsigned Opc =
N->getOpcode();
3428 if (
N->getNumOperands() > 0)
3429 Inp0 =
Op.getOperand(0);
3438 Results.push_back(CreateTLWrapper(Op, DAG));
3442 if (shouldWidenToHvx(ty(Op), DAG)) {
3443 if (
SDValue T = WidenHvxSetCC(Op, DAG))
3448 if (shouldWidenToHvx(ty(Op), DAG)) {
3457 if (isHvxBoolTy(ty(Inp0))) {
3458 SDValue C = LowerHvxBitcast(Op, DAG);
3464 if (ty(Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3465 SDValue T = EqualizeFpIntConversion(Op, DAG);
3473 Results.push_back(LegalizeHvxResize(Op, DAG));
3481HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3482 DAGCombinerInfo &DCI)
const {
3488 const SDLoc &dl(Op);
3495 EVT TruncTy =
Op.getValueType();
3497 EVT SrcTy = Src.getValueType();
3504 if (2 * CastLen != SrcLen)
3508 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3510 Mask[i + CastLen] = 2 * i + 1;
3514 return opSplit(Deal, dl, DAG).first;
3518HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3519 SDValue Op, DAGCombinerInfo &DCI)
const {
3524 if (
Op.getNumOperands() != 2)
3528 const SDLoc &dl(Op);
3543 if (Order.
size() > 2)
3554 auto *SV = cast<ShuffleVectorSDNode>(
Shuffle.getNode());
3558 for (
int M : Mask) {
3563 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3564 if (
static_cast<unsigned>(M) >= InpLen)
3567 int OutOffset = Order[0] == Src ? 0 : InpLen;
3584HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3589 unsigned Opc =
Op.getOpcode();
3594 return combineTruncateBeforeLegal(Op, DCI);
3596 return combineConcatVectorsBeforeLegal(Op, DCI);
3598 if (DCI.isBeforeLegalizeOps())
3614 if (
const auto *
C = dyn_cast<ConstantSDNode>(Ops[0].getOperand(0)))
3624 return getZero(dl, ty(Op), DAG);
3627 if (isUndef(Ops[1]))
3632 SDValue Vec = Ops[0].getOperand(0);
3633 SDValue Rot0 = Ops[1], Rot1 = Ops[0].getOperand(1);
3645HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3648 auto Action = getPreferredHvxVectorAction(Ty);
3655HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3658 auto Action = getPreferredHvxVectorAction(Ty);
3670 auto IsHvxTy = [
this](
EVT Ty) {
3671 return Ty.isSimple() && Subtarget.
isHVXVectorType(Ty.getSimpleVT(),
true);
3674 return Op.getValueType().isSimple() &&
3681 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3682 if (!
Op.getValueType().isSimple())
3685 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3688 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Function Alias Analysis Results
SmallVector< MachineOperand, 4 > Cond
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static cl::opt< unsigned > HvxWidenThreshold("hexagon-hvx-widen", cl::Hidden, cl::init(16), cl::desc("Lower threshold (in bytes) for widening to HVX vectors"))
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
This file provides utility analysis objects describing memory locations.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
const HexagonInstrInfo * getInstrInfo() const override
bool isHVXVectorType(EVT VecTy, bool IncludeBool=false) const
bool useHVXV62Ops() const
ArrayRef< MVT > getHVXElementTypes() const
bool useHVXFloatingPoint() const
bool useHVXQFloatOps() const
unsigned getVectorLength() const
bool useHVX128BOps() const
bool useHVXV68Ops() const
bool useHVXIEEEFPOps() const
bool useHVXV65Ops() const
bool useHVX64BOps() const
bool isHVXElementType(MVT Ty, bool IncludeBool=false) const
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
EVT getSetCCResultType(const DataLayout &, LLVMContext &C, EVT VT) const override
Return the ValueType of the result of SETCC operations.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
static MVT getFloatingPointVT(unsigned BitWidth)
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
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.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS)
Helper function to make it easier to build Select's if you just have operands and don't want to check...
SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provides VTs and return the low/high part.
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
SDValue getValueType(EVT)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVMContext * getContext() const
SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
const value_type & front() const
Return the first element of the SetVector.
const value_type & back() const
Return the last element of the SetVector.
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.
TargetInstrInfo - Interface to description of machine instruction set.
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...