21#include "llvm/IR/IntrinsicsHexagon.h"
32 cl::desc(
"Lower threshold (in bytes) for widening to HVX vectors"));
36 cl::desc(
"Enable FP fast conversion routine."));
38static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
39static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
40static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
41static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
48 switch (ElemTy.SimpleTy) {
50 return std::make_tuple(5, 15, 10);
52 return std::make_tuple(8, 127, 23);
54 return std::make_tuple(11, 1023, 52);
62HexagonTargetLowering::initializeHVXLowering() {
63 if (Subtarget.useHVX64BOps()) {
81 }
else if (Subtarget.useHVX128BOps()) {
91 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
97 if (Subtarget.useHVXV81Ops()) {
105 bool Use64b = Subtarget.useHVX64BOps();
108 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
109 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
110 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
112 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
130 if (Subtarget.useHVX128BOps()) {
140 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
141 Subtarget.useHVXFloatingPoint()) {
143 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
144 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
146 for (MVT
T : FloatV) {
189 if (!Subtarget.useHVXV81Ops())
193 if (Subtarget.useHVXV81Ops()) {
196 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
197 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
198 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
199 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
225 for (MVT
P : FloatW) {
249 if (Subtarget.useHVXQFloatOps()) {
252 }
else if (Subtarget.useHVXIEEEFPOps()) {
258 for (MVT
T : LegalV) {
285 if (
T.getScalarType() != MVT::i32) {
294 if (
T.getScalarType() != MVT::i32) {
322 if (Subtarget.useHVXFloatingPoint()) {
339 for (MVT
T : LegalW) {
394 if (
T.getScalarType() != MVT::i32) {
399 if (Subtarget.useHVXFloatingPoint()) {
446 for (MVT
T : LegalW) {
463 for (MVT
T : LegalV) {
478 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
481 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
486 unsigned HwLen = Subtarget.getVectorLength();
487 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
488 if (ElemTy == MVT::i1)
490 int ElemWidth = ElemTy.getFixedSizeInBits();
491 int MaxElems = (8*HwLen) / ElemWidth;
492 for (
int N = 2;
N < MaxElems;
N *= 2) {
503 if (Subtarget.useHVXFloatingPoint()) {
533 auto HvxType = [=](MVT ScalarT,
unsigned Factor = 1) {
542 typedef std::tuple<MVT, MVT, bool> ReductionSignature;
544 static const std::vector<ReductionSignature> NativeReductions = {
545 {MVT::i32, MVT::i8,
false},
548 for (
const auto &R : NativeReductions) {
550 MVT AccType = std::get<0>(R);
551 MVT InputType = std::get<1>(R);
552 unsigned Factor = std::get<2>(R) ? 2 : 1;
574 for (
unsigned ConcatFactor = 1; ConcatFactor <=
MaxExpandMLA;
576 for (
unsigned ReductionFactor = 1; ReductionFactor <=
MaxExpandMLA;
577 ReductionFactor <<= 1)
578 if (ConcatFactor * ReductionFactor != 1 &&
581 MLAOps, HvxType(AccType, Factor * ConcatFactor),
582 HvxType(InputType, Factor * ConcatFactor * ReductionFactor),
589HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
596 unsigned HwLen = Subtarget.getVectorLength();
599 if (ElemTy == MVT::i1 && VecLen > HwLen)
605 if (ElemTy == MVT::i1) {
620 unsigned HwWidth = 8*HwLen;
621 if (VecWidth > 2*HwWidth)
627 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
636HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
637 unsigned Opc =
Op.getOpcode();
639 case HexagonISD::SMUL_LOHI:
640 case HexagonISD::UMUL_LOHI:
641 case HexagonISD::USMUL_LOHI:
657HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
658 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
662 Tys.second.getVectorNumElements());
665HexagonTargetLowering::TypePair
666HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
669 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
671 return { HalfTy, HalfTy };
675HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
682HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
689HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
698HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
704HexagonTargetLowering::VectorPair
705HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
707 TypePair Tys = typeSplit(ty(Vec));
710 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
714HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
715 return Subtarget.isHVXVectorType(Ty) &&
720HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
721 return Subtarget.isHVXVectorType(Ty) &&
726HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
727 return Subtarget.isHVXVectorType(Ty,
true) &&
731bool HexagonTargetLowering::allowsHvxMemoryAccess(
739 if (!Subtarget.isHVXVectorType(VecTy,
false))
746bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
748 if (!Subtarget.isHVXVectorType(VecTy))
756void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
758 unsigned Opc =
MI.getOpcode();
759 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
760 MachineBasicBlock &MB = *
MI.getParent();
764 auto At =
MI.getIterator();
767 case Hexagon::PS_vsplatib:
768 if (Subtarget.useHVXV62Ops()) {
773 .
add(
MI.getOperand(1));
775 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
781 const MachineOperand &InpOp =
MI.getOperand(1);
783 uint32_t
V = InpOp.
getImm() & 0xFF;
785 .
addImm(V << 24 | V << 16 | V << 8 | V);
791 case Hexagon::PS_vsplatrb:
792 if (Subtarget.useHVXV62Ops()) {
795 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
796 .
add(
MI.getOperand(1));
799 const MachineOperand &InpOp =
MI.getOperand(1);
800 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
803 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
808 case Hexagon::PS_vsplatih:
809 if (Subtarget.useHVXV62Ops()) {
814 .
add(
MI.getOperand(1));
816 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
822 const MachineOperand &InpOp =
MI.getOperand(1);
824 uint32_t
V = InpOp.
getImm() & 0xFFFF;
832 case Hexagon::PS_vsplatrh:
833 if (Subtarget.useHVXV62Ops()) {
836 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
837 .
add(
MI.getOperand(1));
842 const MachineOperand &InpOp =
MI.getOperand(1);
843 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
851 case Hexagon::PS_vsplatiw:
852 case Hexagon::PS_vsplatrw:
853 if (
Opc == Hexagon::PS_vsplatiw) {
857 .
add(
MI.getOperand(1));
858 MI.getOperand(1).ChangeToRegister(SplatV,
false);
861 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
867HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
877 const SDLoc &dl(ElemIdx);
883HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
886 assert(ElemWidth >= 8 && ElemWidth <= 32);
890 if (ty(Idx) != MVT::i32)
892 const SDLoc &dl(Idx);
899HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
906 if (ElemTy == MVT::i8)
910 MVT ResTy = tyVector(OpTy, MVT::i8);
913 SmallVector<int,128> ByteMask;
916 for (
unsigned I = 0;
I != ElemSize; ++
I)
919 int NewM =
M*ElemSize;
920 for (
unsigned I = 0;
I != ElemSize; ++
I)
926 opCastElem(Op1, MVT::i8, DAG), ByteMask);
933 unsigned VecLen =
Values.size();
937 unsigned HwLen = Subtarget.getVectorLength();
939 unsigned ElemSize = ElemWidth / 8;
940 assert(ElemSize*VecLen == HwLen);
944 !(Subtarget.useHVXFloatingPoint() &&
946 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
947 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
949 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
950 SDValue W = buildVector32(
Values.slice(i, OpsPerWord), dl, PartVT, DAG);
958 unsigned NumValues =
Values.size();
961 for (
unsigned i = 0; i != NumValues; ++i) {
965 if (!SplatV.getNode())
967 else if (SplatV !=
Values[i])
975 unsigned NumWords = Words.
size();
977 bool IsSplat =
isSplat(Words, SplatV);
978 if (IsSplat && isUndef(SplatV))
983 return getZero(dl, VecTy, DAG);
992 bool AllConst = getBuildVectorConstInts(
Values, VecTy, DAG, Consts);
995 (Constant**)Consts.end());
997 Align Alignment(HwLen);
1013 SmallVectorImpl<int> &SrcIdx) {
1017 SrcIdx.push_back(-1);
1030 int I =
C->getSExtValue();
1031 assert(
I >= 0 &&
"Negative element index");
1032 SrcIdx.push_back(
I);
1038 SmallVector<int,128> ExtIdx;
1040 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
1041 MVT ExtTy = ty(ExtVec);
1043 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
1047 SmallVector<int,128>
Mask;
1048 BitVector
Used(ExtLen);
1050 for (
int M : ExtIdx) {
1060 for (
unsigned I = 0;
I != ExtLen; ++
I) {
1061 if (
Mask.size() == ExtLen)
1069 return ExtLen == VecLen ? S : LoHalf(S, DAG);
1077 assert(4*Words.
size() == Subtarget.getVectorLength());
1080 for (
unsigned i = 0; i != NumWords; ++i) {
1082 if (Words[i].isUndef())
1084 for (
unsigned j = i;
j != NumWords; ++
j)
1085 if (Words[i] == Words[j])
1088 if (VecHist[i] > VecHist[n])
1092 SDValue HalfV = getZero(dl, VecTy, DAG);
1093 if (VecHist[n] > 1) {
1101 HalfV = DAG.
getNode(HexagonISD::VALIGN, dl, VecTy,
1102 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1114 for (
unsigned i = 0; i != NumWords/2; ++i) {
1116 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1119 N = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1120 {HalfV0, Words[i]});
1123 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1126 M = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1127 {HalfV1, Words[i+NumWords/2]});
1150HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1151 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1152 MVT PredTy = ty(PredV);
1153 unsigned HwLen = Subtarget.getVectorLength();
1156 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1166 SmallVector<int,128>
Mask(HwLen);
1171 for (
unsigned i = 0; i != HwLen; ++i) {
1172 unsigned Num = i % Scale;
1173 unsigned Off = i / Scale;
1182 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1184 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1191 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1203 while (Bytes < BitBytes) {
1205 Words[IdxW].
clear();
1208 for (
const SDValue &W : Words[IdxW ^ 1]) {
1209 SDValue T = expandPredicate(W, dl, DAG);
1214 for (
const SDValue &W : Words[IdxW ^ 1]) {
1222 assert(Bytes == BitBytes);
1223 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1225 for (
const SDValue &W : Words[IdxW]) {
1227 Vec = DAG.
getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1239 unsigned VecLen =
Values.size();
1240 unsigned HwLen = Subtarget.getVectorLength();
1241 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1243 bool AllT =
true, AllF =
true;
1247 return !
N->isZero();
1256 if (VecLen <= HwLen) {
1260 assert(HwLen % VecLen == 0);
1261 unsigned BitBytes = HwLen / VecLen;
1268 for (
unsigned B = 0;
B != BitBytes; ++
B)
1275 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1278 for (;
B != 8; ++
B) {
1297 return DAG.
getNode(HexagonISD::QTRUE, dl, VecTy);
1299 return DAG.
getNode(HexagonISD::QFALSE, dl, VecTy);
1302 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1307HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1312 assert(ElemWidth >= 8 && ElemWidth <= 32);
1315 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1316 SDValue ExWord = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1318 if (ElemTy == MVT::i32)
1324 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1327 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1331HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1334 assert(ResTy == MVT::i1);
1336 unsigned HwLen = Subtarget.getVectorLength();
1340 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1344 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1346 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1350HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1355 assert(ElemWidth >= 8 && ElemWidth <= 32);
1360 MVT VecTy = ty(VecV);
1361 unsigned HwLen = Subtarget.getVectorLength();
1366 SDValue InsV = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1373 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1374 if (ElemTy == MVT::i32)
1375 return InsertWord(VecV, ValV, ByteIdx);
1381 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1386 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1387 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1389 ValV, SubIdx, dl, ElemTy, DAG);
1392 return InsertWord(VecV, Ins, ByteIdx);
1396HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1398 unsigned HwLen = Subtarget.getVectorLength();
1402 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1407 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1412HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1414 MVT VecTy = ty(VecV);
1415 unsigned HwLen = Subtarget.getVectorLength();
1423 if (isHvxPairTy(VecTy)) {
1424 unsigned SubIdx = Hexagon::vsub_lo;
1425 if (Idx * ElemWidth >= 8 * HwLen) {
1426 SubIdx = Hexagon::vsub_hi;
1430 VecTy = typeSplit(VecTy).first;
1440 MVT WordTy = tyVector(VecTy, MVT::i32);
1442 unsigned WordIdx = (Idx*ElemWidth) / 32;
1445 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1450 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1451 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1456HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1458 MVT VecTy = ty(VecV);
1459 unsigned HwLen = Subtarget.getVectorLength();
1467 unsigned Offset = Idx * BitBytes;
1469 SmallVector<int,128>
Mask;
1471 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1478 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1479 for (
unsigned j = 0;
j != Rep; ++
j)
1496 unsigned Rep = 8 / ResLen;
1499 for (
unsigned r = 0; r != HwLen / 8; ++r) {
1501 for (
unsigned i = 0; i != ResLen; ++i) {
1502 for (
unsigned j = 0;
j != Rep; ++
j)
1514 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1515 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1520HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1522 MVT VecTy = ty(VecV);
1523 MVT SubTy = ty(SubV);
1524 unsigned HwLen = Subtarget.getVectorLength();
1528 bool IsPair = isHvxPairTy(VecTy);
1536 V0 = LoHalf(VecV, DAG);
1537 V1 = HiHalf(VecV, DAG);
1542 if (isHvxSingleTy(SubTy)) {
1544 unsigned Idx = CN->getZExtValue();
1546 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1569 if (!IdxN || !IdxN->isZero()) {
1577 unsigned RolBase = HwLen;
1580 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1585 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1588 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1592 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1607HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1609 MVT VecTy = ty(VecV);
1610 MVT SubTy = ty(SubV);
1611 assert(Subtarget.isHVXVectorType(VecTy,
true));
1616 unsigned HwLen = Subtarget.getVectorLength();
1617 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1620 unsigned BitBytes = HwLen / VecLen;
1621 unsigned BlockLen = HwLen / Scale;
1625 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1629 if (!IdxN || !IdxN->isZero()) {
1638 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1640 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1642 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1644 if (!IdxN || !IdxN->isZero()) {
1653HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1658 assert(Subtarget.isHVXVectorType(ResTy));
1665 SDValue False = getZero(dl, ResTy, DAG);
1666 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1670HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1678 unsigned HwLen = Subtarget.getVectorLength();
1680 MVT PredTy = ty(VecQ);
1682 assert(HwLen % PredLen == 0);
1689 for (
unsigned i = 0; i != HwLen/8; ++i) {
1690 for (
unsigned j = 0;
j != 8; ++
j)
1691 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1694 Align Alignment(HwLen);
1704 getZero(dl, VecTy, DAG));
1710 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1712 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1719 SmallVector<int,128>
Mask;
1720 for (
unsigned i = 0; i != HwLen; ++i)
1721 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1731 MVT InpTy = ty(VecV);
1739 return InpWidth < ResWidth
1747 if (InpWidth < ResWidth) {
1749 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1751 unsigned NarOpc =
Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1757HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1761 const SDLoc &dl(Vec);
1770 const SDLoc &dl(
Op);
1775 for (
unsigned i = 0; i !=
Size; ++i)
1776 Ops.push_back(
Op.getOperand(i));
1779 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1787 for (
unsigned i = 0; i !=
Size; i++)
1798 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1800 MVT SingleTy = typeSplit(VecTy).first;
1801 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1802 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1806 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1812 const SDLoc &dl(
Op);
1814 MVT ArgTy = ty(
Op.getOperand(0));
1816 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1834 const SDLoc &dl(
Op);
1851 MVT NTy = typeLegalize(Ty, DAG);
1855 V.getOperand(0),
V.getOperand(1)),
1860 switch (
V.getOpcode()) {
1868 V =
V.getOperand(0);
1879 unsigned HwLen = Subtarget.getVectorLength();
1886 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1888 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, Op0,
Op.getOperand(1));
1894 MVT HalfTy = typeSplit(VecTy).first;
1896 Ops.take_front(NumOp/2));
1898 Ops.take_back(NumOp/2));
1899 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, V0,
V1);
1909 SDValue Combined = combineConcatOfScalarPreds(
Op, BitBytes, DAG);
1912 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1916 unsigned InpLen = ty(Combined.
getOperand(0)).getVectorNumElements();
1919 SDValue Res = getZero(dl, ByteTy, DAG);
1920 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1933 const SDLoc &dl(
Op);
1935 if (ElemTy == MVT::i1)
1936 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1938 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1944 const SDLoc &dl(
Op);
1950 if (ElemTy == MVT::i1)
1951 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1953 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1955 tyVector(VecTy, MVT::i16),
1956 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1958 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1961 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1968 MVT SrcTy = ty(SrcV);
1974 const SDLoc &dl(
Op);
1977 if (ElemTy == MVT::i1)
1978 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1980 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1991 const SDLoc &dl(
Op);
1992 MVT VecTy = ty(VecV);
1994 if (ElemTy == MVT::i1)
1995 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1997 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
2009 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2010 return LowerHvxSignExt(
Op, DAG);
2019 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2020 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
2029 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2030 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
2038 const SDLoc &dl(
Op);
2041 assert(ResTy == ty(InpV));
2066 const SDLoc &dl(
Op);
2073 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2074 unsigned Opc =
Op.getOpcode();
2078 return DAG.
getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2080 return DAG.
getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2090 const SDLoc &dl(
Op);
2091 unsigned Opc =
Op.getOpcode();
2096 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2103 bool SignedVu =
Opc == HexagonISD::SMUL_LOHI;
2104 bool SignedVv =
Opc == HexagonISD::SMUL_LOHI ||
Opc == HexagonISD::USMUL_LOHI;
2108 if (Subtarget.useHVXV62Ops())
2109 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2111 if (
Opc == HexagonISD::SMUL_LOHI) {
2114 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2115 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2121 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2128 MVT ValTy = ty(Val);
2129 const SDLoc &dl(
Op);
2132 unsigned HwLen = Subtarget.getVectorLength();
2140 if (PredLen < HwLen) {
2143 if (HwLen > PredLen * 2) {
2144 assert(HwLen == PredLen * 4);
2146 Val = getInstr(Hexagon::V6_vdealh, dl, ByteTy, Val, DAG);
2148 if (HwLen > PredLen) {
2149 assert(HwLen == PredLen * 2);
2150 Val = getInstr(Hexagon::V6_vdealb, dl, ByteTy, Val, DAG);
2155 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2170 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2172 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2177 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2178 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2191 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2192 assert(Val32.getValueType().getSizeInBits() == 32 &&
2193 "Input must be 32 bits");
2197 for (
unsigned i = 0; i < 32; ++i)
2205 if (ResTy == MVT::v32i1 &&
2206 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2207 Subtarget.useHVX128BOps()) {
2209 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2211 return bitcastI32ToV32I1(Val32);
2214 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2232 unsigned HwLen = Subtarget.getVectorLength();
2244 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2248 for (
unsigned J = 0; J != 8; ++J) {
2256 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2268 const SDLoc &dl(
Op);
2271 MVT ValTy = ty(Val);
2274 if (!isHvxBoolTy(ValTy))
2281 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2285 unsigned HwLen = Subtarget.getVectorLength();
2289 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2293 for (
unsigned i = 0; i != NumBits / 32; ++i) {
2304 return DAG.
getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2307 if (NumBits == 64) {
2308 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2312 if (NumBits == 128) {
2313 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2314 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2330 const SDLoc &dl(
Op);
2335 if (!isHvxBoolTy(ResTy))
2341 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2349 if (NumBits == 32) {
2357 if (NumBits == 64) {
2365 if (NumBits == 128) {
2401 const SDLoc &dl(
Op);
2402 unsigned HwLen = Subtarget.getVectorLength();
2404 assert(HwLen % VecLen == 0);
2405 unsigned ElemSize = HwLen / VecLen;
2417 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2423HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2425 unsigned Opc =
Op.getOpcode();
2437 const SDLoc &dl(
Op);
2443 bool UseShifts = ElemTy != MVT::i8;
2444 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2447 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2455 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2461 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2463 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2471 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2473 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2480 const SDLoc &dl(
Op);
2481 unsigned IntNo =
Op.getConstantOperandVal(0);
2489 case Intrinsic::hexagon_V6_pred_typecast:
2490 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2491 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2492 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2499 case Intrinsic::hexagon_V6_vmpyss_parts:
2500 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2501 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2503 case Intrinsic::hexagon_V6_vmpyuu_parts:
2504 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2505 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2507 case Intrinsic::hexagon_V6_vmpyus_parts:
2508 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2509 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2519 const SDLoc &dl(
Op);
2520 unsigned HwLen = Subtarget.getVectorLength();
2524 SDValue Chain = MaskN->getChain();
2528 unsigned Opc =
Op->getOpcode();
2545 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2549 if (MaskN->getAlign().value() % HwLen == 0) {
2558 SDValue Z = getZero(dl, ty(V), DAG);
2562 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2563 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2564 return std::make_pair(LoV, HiV);
2570 VectorPair Tmp = StoreAlign(MaskV,
Base);
2573 VectorPair ValueU = StoreAlign(
Value,
Base);
2577 getInstr(StoreOpc, dl, MVT::Other,
2578 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2589 uint64_t StoreMemSize = MaskN->getMemoryVT().getStoreSize().getFixedValue();
2590 if (StoreMemSize <= MaskN->
getAlign().value())
2594 getInstr(StoreOpc, dl, MVT::Other,
2595 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2604 assert(Subtarget.useHVXQFloatOps());
2609 MVT ArgTy = ty(
Op.getOperand(0));
2610 const SDLoc &dl(
Op);
2612 if (ArgTy == MVT::v64bf16) {
2613 MVT HalfTy = typeSplit(VecTy).first;
2616 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2621 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2622 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2624 {VecPair.second, VecPair.first,
2630 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2639 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2641 MVT HalfTy = typeSplit(VecTy).first;
2642 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2644 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2646 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2649 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2662 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2665 if (Subtarget.useHVXIEEEFPOps()) {
2667 if (FpTy == MVT::f16) {
2669 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2671 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2677 return EqualizeFpIntConversion(
Op, DAG);
2679 return ExpandHvxFpToInt(
Op, DAG);
2695 MVT ResTy = ty(PredOp);
2696 const SDLoc &dl(PredOp);
2699 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2700 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2702 SDNode *PredTransfer =
2705 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2708 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2713 SDNode *IndexShift =
2719 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2744 MVT ResTy = ty(PredOp);
2745 const SDLoc &dl(PredOp);
2755 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2756 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2766 SDNode *PredTransfer =
2770 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2777 SDNode *IndexShift_hi =
2780 SDNode *IndexShift_lo =
2784 SDNode *MaskOff_hi =
2787 SDNode *MaskOff_lo =
2810 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2811 return LowerHvxPred32ToFp(
Op, DAG);
2812 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2813 return LowerHvxPred64ToFp(
Op, DAG);
2816 if (Subtarget.useHVXIEEEFPOps()) {
2818 if (FpTy == MVT::f16) {
2820 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2822 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2828 return EqualizeFpIntConversion(
Op, DAG);
2830 return ExpandHvxIntToFp(
Op, DAG);
2833HexagonTargetLowering::TypePair
2834HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2845 unsigned MaxWidth = std::max(Width0, Width1);
2847 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2854 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2855 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2859 return {WideETy0, WideETy1};
2870HexagonTargetLowering::TypePair
2871HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2881 unsigned MaxLen = std::max(Len0, Len1);
2894HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2895 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2904HexagonTargetLowering::VectorPair
2935HexagonTargetLowering::VectorPair
2936HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2941 const SDLoc &dl(Val);
2942 MVT ValTy = ty(Val);
2956 MVT IntTy = tyVector(ValTy, ElemTy);
2968 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2987 MVT
PairTy = typeJoin({VecTy, VecTy});
3013 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
3015 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
3023 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
3028 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3029 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
3030 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
3041HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
3042 bool SignedB,
const SDLoc &dl,
3045 MVT
PairTy = typeJoin({VecTy, VecTy});
3050 if (SignedA && !SignedB) {
3066 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3067 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
3068 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
3077 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3080 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
3084 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3085 {HiHalf(P2, DAG), T3,
S16}, DAG);
3088 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3089 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
3093 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
3100 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
3101 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
3102 }
else if (SignedB) {
3108 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
3110 assert(!SignedA && !SignedB);
3117HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
3122 MVT
PairTy = typeJoin({VecTy, VecTy});
3125 if (SignedA && !SignedB) {
3134 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
3139 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
3151 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
3152 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
3153 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
3154 }
else if (!SignedA) {
3164 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
3182 unsigned Opc =
Op.getOpcode();
3187 MVT InpTy = ty(Inp);
3193 const SDLoc &dl(
Op);
3196 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3205 unsigned Opc =
Op.getOpcode();
3208 const SDLoc &dl(
Op);
3210 MVT InpTy = ty(Op0);
3223 if (InpTy == MVT::v64f16) {
3224 if (Subtarget.useHVXV81Ops()) {
3227 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3231 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3236 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3316 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3317 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3360 unsigned Opc =
Op.getOpcode();
3363 const SDLoc &dl(
Op);
3365 MVT InpTy = ty(Op0);
3398 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3408 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3431 unsigned Opc =
Op.getOpcode();
3448 const SDLoc &dl(
Op);
3449 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3458 unsigned Opc =
Op.getConstantOperandVal(2);
3462HexagonTargetLowering::VectorPair
3466 const SDLoc &dl(
Op);
3468 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3469 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3471 return std::make_pair(TV, TV);
3476 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3478 switch (
Op.getOpcode()) {
3479 case ISD::SIGN_EXTEND_INREG:
3480 case HexagonISD::SSAT:
3481 case HexagonISD::USAT:
3482 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3483 std::tie(Lo, Hi) = SplitVTNode(N);
3491 MVT HalfTy = typeSplit(ResTy).first;
3500 unsigned MemOpc = MemN->getOpcode();
3501 EVT MemTy = MemN->getMemoryVT();
3518 EVT LoMemVT, HiMemVT;
3519 bool HiIsEmpty =
false;
3520 std::tie(LoMemVT, HiMemVT) =
3526 const SDLoc &dl(
Op);
3527 SDValue Chain = MemN->getChain();
3528 SDValue Base0 = MemN->getBasePtr();
3532 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3533 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3535 auto MemSize = [=](uint64_t
Size) {
3569 assert(MaskN->isUnindexed());
3570 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3577 Masks.first, Thru.first, LoMemVT, MOp0,
3586 Masks.second, Thru.second, HiMemVT, MOp1,
3608 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3614 const SDLoc &dl(
Op);
3616 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3617 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3618 "Not widening loads of i1 yet");
3620 SDValue Chain = LoadN->getChain();
3625 unsigned HwLen = Subtarget.getVectorLength();
3627 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3630 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3638 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3646 const SDLoc &dl(
Op);
3648 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3649 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3650 "Not widening stores of i1 yet");
3652 SDValue Chain = StoreN->getChain();
3656 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3657 MVT ValueTy = ty(
Value);
3659 unsigned HwLen = Subtarget.getVectorLength();
3662 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3664 Len = ty(
Value).getVectorNumElements();
3666 assert(ty(
Value).getVectorNumElements() == HwLen);
3668 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3670 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3673 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3681 const SDLoc &dl(
Op);
3682 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3684 unsigned HwLen = Subtarget.getVectorLength();
3689 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3692 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3693 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3697 {WideOp0, WideOp1,
Op.getOperand(2)});
3699 EVT RetTy = typeLegalize(ty(
Op), DAG);
3701 {SetCC, getZero(dl, MVT::i32, DAG)});
3711 const SDLoc &dl(
Op);
3713 MVT InpTy = ty(Inp);
3717 "Expected boolean result type");
3720 unsigned HwLen = Subtarget.getVectorLength();
3725 if (!Subtarget.isHVXVectorType(WideInpTy,
false))
3729 SDValue WideInp = appendUndef(Inp, WideInpTy, DAG);
3736 EVT RetTy = typeLegalize(ResTy, DAG);
3738 {WideTrunc, getZero(dl, MVT::i32, DAG)});
3743 unsigned Opc =
Op.getOpcode();
3744 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3746 return isHvxPairTy(ty(V));
3757 return SplitHvxMemOp(
Op, DAG);
3762 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3763 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3795 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3800 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3801 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3825 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3827 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3836 ty(
Op.getOperand(0)).getScalarType().isFloatingPoint())
3837 return LowerHvxFpSetoeq(
Op, DAG);
3854 case HexagonISD::SMUL_LOHI:
3855 case HexagonISD::UMUL_LOHI:
3856 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3861 return LowerHvxPartialReduceMLA(
Op, DAG);
3879 unsigned Opc =
Op.getOpcode();
3881 case HexagonISD::SSAT:
3882 case HexagonISD::USAT:
3899 MVT InpTy = ty(Inp);
3904 assert(InpWidth != ResWidth);
3906 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3909 const SDLoc &dl(
Op);
3913 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3916 case HexagonISD::SSAT:
3917 case HexagonISD::USAT:
3921 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3928 if (InpWidth < ResWidth) {
3930 while (InpWidth * 2 <= ResWidth)
3931 S = repeatOp(InpWidth *= 2, S);
3935 while (InpWidth / 2 >= ResWidth)
3936 S = repeatOp(InpWidth /= 2, S);
3944 MVT InpTy = ty(Inp0);
3948 unsigned Opc =
Op.getOpcode();
3950 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3955 auto [WInpTy, WResTy] =
3956 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3957 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3958 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3966 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3967 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3968 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3975 SDValue T = ExpandHvxResizeIntoSteps(
Op, DAG);
3978 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3981 return RemoveTLWrapper(
Op, DAG);
3987HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3989 unsigned Opc =
N->getOpcode();
3992 if (
N->getNumOperands() > 0)
3993 Inp0 =
Op.getOperand(0);
3999 if (Subtarget.isHVXElementType(ty(
Op)) &&
4000 Subtarget.isHVXElementType(ty(Inp0))) {
4001 Results.push_back(CreateTLWrapper(
Op, DAG));
4013 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4014 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
4016 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4017 Subtarget.isHVXElementType(ty(Inp0))) {
4018 Results.push_back(CreateTLWrapper(
Op, DAG));
4022 if (shouldWidenToHvx(ty(Inp0), DAG)) {
4035 if (isHvxPairTy(ty(
Op))) {
4043 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
4052 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4053 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4057 case HexagonISD::SSAT:
4058 case HexagonISD::USAT:
4061 Results.push_back(LegalizeHvxResize(
Op, DAG));
4069HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
4071 unsigned Opc =
N->getOpcode();
4074 if (
N->getNumOperands() > 0)
4075 Inp0 =
Op.getOperand(0);
4081 if (Subtarget.isHVXElementType(ty(
Op)) &&
4082 Subtarget.isHVXElementType(ty(Inp0))) {
4083 Results.push_back(CreateTLWrapper(
Op, DAG));
4090 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4091 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
4093 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4094 Subtarget.isHVXElementType(ty(Inp0))) {
4095 Results.push_back(CreateTLWrapper(
Op, DAG));
4099 if (shouldWidenToHvx(ty(
Op), DAG)) {
4105 if (shouldWidenToHvx(ty(
Op), DAG)) {
4114 if (isHvxBoolTy(ty(Inp0))) {
4121 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4122 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4126 case HexagonISD::SSAT:
4127 case HexagonISD::USAT:
4130 Results.push_back(LegalizeHvxResize(
Op, DAG));
4138HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
4139 DAGCombinerInfo &DCI)
const {
4144 SelectionDAG &DAG = DCI.DAG;
4145 const SDLoc &dl(
Op);
4152 EVT TruncTy =
Op.getValueType();
4154 EVT SrcTy = Src.getValueType();
4161 if (2 * CastLen != SrcLen)
4164 SmallVector<int, 128>
Mask(SrcLen);
4165 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
4167 Mask[i + CastLen] = 2 * i + 1;
4171 return opSplit(Deal, dl, DAG).first;
4175HexagonTargetLowering::combineConcatOfShuffles(
SDValue Op,
4184 const SDLoc &dl(
Op);
4193 SetVector<SDValue> Order;
4199 if (Order.
size() > 2)
4208 SmallVector<int, 128> LongMask;
4209 auto AppendToMask = [&](
SDValue Shuffle) {
4211 ArrayRef<int>
Mask = SV->getMask();
4214 for (
int M : Mask) {
4219 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
4220 if (
static_cast<unsigned>(M) >= InpLen)
4223 int OutOffset = Order[0] == Src ? 0 : InpLen;
4246HexagonTargetLowering::combineConcatOfScalarPreds(
SDValue Op,
unsigned BitBytes,
4248 const SDLoc &dl(
Op);
4251 MVT InpTy = ty(
Ops[0]);
4254 assert(InpLen <= 8 &&
"Too long for scalar predicate");
4255 assert(ResLen > 8 &&
"Too short for HVX vector predicate");
4257 unsigned Bytes = 8 / InpLen;
4260 if (Bytes <= BitBytes)
4264 unsigned SliceLen = Bytes / BitBytes;
4269 for (
unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4271 Inputs.slice(SliceLen * i, SliceLen));
4278SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4279 SDValue Op, DAGCombinerInfo &DCI)
const {
4283 if (ElemTy != MVT::i1) {
4284 return combineConcatOfShuffles(
Op, DCI.DAG);
4291SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4292 unsigned Opcode,
EVT AccEltType,
unsigned AccNumElements,
EVT InputType,
4295 const auto &Subtarget = DAG.
getSubtarget<HexagonSubtarget>();
4296 if (!Subtarget.useHVXOps())
4302 unsigned NativeRatio;
4303 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4315 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4316 if (RemainingReductionRatio == 1)
4321 InputNumElements / NativeRatio);
4324 return DAG.
getNode(Opcode,
DL, IntermediateType, Zero,
A,
B);
4330 EVT AccType =
Mul.getValueType();
4336 A =
Mul->getOperand(0);
4337 B =
Mul->getOperand(1);
4357 A =
A->getOperand(0);
4358 B =
B->getOperand(0);
4359 if (
A.getValueType() !=
B.getValueType())
4370 if (!Subtarget.useHVXOps())
4373 EVT ScalarType =
N->getValueType(0);
4380 unsigned RemainingReductionRatio;
4382 createExtendingPartialReduceMLA(Opcode, ScalarType, 1,
A.getValueType(),
4383 A,
B, RemainingReductionRatio,
DL, DAG);
4400HexagonTargetLowering::splitExtendingPartialReduceMLA(
SDNode *
N,
4402 if (!Subtarget.useHVXOps())
4408 if (
A.getValueType() !=
B.getValueType())
4414 EVT InputType =
A.getValueType();
4419 unsigned RemainingReductionRatio;
4420 SDValue Partial = createExtendingPartialReduceMLA(
4434 DL, AccType, Acc, Partial, One);
4438HexagonTargetLowering::LowerHvxPartialReduceMLA(
SDValue Op,
4440 const SDLoc &
DL(
Op);
4446 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4450 unsigned AccSubvectorNumElements =
4452 EVT AccSubvectorType =
4455 EVT InputType =
A.getValueType();
4458 unsigned InputSubvectorNumElements =
4461 InputSubvectorNumElements);
4466 for (
unsigned I = 0;
I != SubvectorNum; ++
I) {
4468 I * AccSubvectorNumElements);
4470 I * InputSubvectorNumElements);
4472 I * InputSubvectorNumElements);
4474 SubvectorAcc, SubvectorA, SubvectorB);
4514 auto ResTy = ty(
Op);
4515 auto A =
Op.getOperand(0),
B =
Op->getOperand(1);
4516 MVT FloatTy = ty(
A);
4518 bool IsF32 = (ElemTy == MVT::f32);
4520 assert((ElemTy == MVT::f16));
4522 const SDLoc &
DL(
Op);
4523 MVT IntElemTy = IsF32 ? MVT::i32 : MVT::i16;
4524 MVT IntVecTy = tyVector(FloatTy, IntElemTy);
4528 bool NoNaN =
Op->getFlags().hasNoNaNs();
4546 uint64_t AbsMask = IsF32 ? 0x7FFFFFFFull : 0x7FFFull;
4547 uint64_t NaNThresh = IsF32 ? 0x7F800000ull : 0x7C00ull;
4569HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
4572 SelectionDAG &DAG = DCI.DAG;
4574 unsigned Opc =
Op.getOpcode();
4579 return combineTruncateBeforeLegal(
Op, DCI);
4581 return combineConcatVectorsBeforeLegal(
Op, DCI);
4583 if (DCI.isBeforeLegalizeOps())
4590 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
4591 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
4599 return getZero(dl, ty(
Op), DAG);
4601 case HexagonISD::VINSERTW0:
4602 if (isUndef(
Ops[1]))
4620HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4621 if (Subtarget.isHVXVectorType(Ty,
true))
4623 auto Action = getPreferredHvxVectorAction(Ty);
4625 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4630HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4631 if (Subtarget.isHVXVectorType(Ty,
true))
4633 auto Action = getPreferredHvxVectorAction(Ty);
4635 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4641 if (!Subtarget.useHVXOps())
4645 auto IsHvxTy = [
this](EVT Ty) {
4646 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4649 return Op.getValueType().isSimple() &&
4650 Subtarget.isHVXVectorType(ty(
Op),
true);
4656 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
4657 if (!
Op.getValueType().isSimple())
4660 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4663 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const unsigned MaxExpandMLA
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static bool DetectExtendingMultiply(const SDValue &N, EVT ScalarType, unsigned &Opcode, SDValue &A, SDValue &B)
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 cl::opt< bool > EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false), cl::desc("Enable FP fast conversion routine."))
static MaybeAlign getAlign(Value *Ptr)
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
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
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
uint64_t getNumOperands() 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.
const SDValue & getBasePtr() const
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.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, 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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
Flags
Flags values. These may be or'd together.
const MachinePointerInfo & getPointerInfo() const
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
unsigned getSubReg() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
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.
iterator_range< value_op_iterator > op_values() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
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...
const TargetSubtargetInfo & getSubtarget() const
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI 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.
LLVM_ABI SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI 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 getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
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.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
LLVM_ABI 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 provided VTs and return the low/high part.
LLVM_ABI 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.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI 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...
LLVM_ABI 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)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI 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.
LLVM_ABI 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
LLVM_ABI std::pair< EVT, EVT > GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT, bool *HiIsEmpty) const
Compute the VTs needed for the low/hi parts of a type, dependent on an enveloping VT that has been sp...
LLVM_ABI 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.
LLVM_ABI 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)
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
size_type size() const
Determine the number of elements in 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.
bool insert(const value_type &X)
Insert a new element into 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)
const SDValue & getBasePtr() const
const SDValue & getValue() const
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...
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
LegalizeAction getPartialReduceMLAAction(unsigned Opc, EVT AccVT, EVT InputVT) const
Return how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treated.
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ 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...
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ 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.
@ 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...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ 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 ...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ SIGN_EXTEND
Conversion operators.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ 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.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ 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.
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ 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.
@ 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...
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ 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...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
initializer< Ty > init(const Ty &Val)
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
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
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isVector() const
Return true if this is a vector value type.
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.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const