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) {
183 if (Subtarget.useHVXV81Ops()) {
186 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
187 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
188 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
189 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
215 for (MVT
P : FloatW) {
239 if (Subtarget.useHVXQFloatOps()) {
242 }
else if (Subtarget.useHVXIEEEFPOps()) {
248 for (MVT
T : LegalV) {
275 if (
T.getScalarType() != MVT::i32) {
284 if (
T.getScalarType() != MVT::i32) {
312 if (Subtarget.useHVXFloatingPoint()) {
329 for (MVT
T : LegalW) {
384 if (
T.getScalarType() != MVT::i32) {
389 if (Subtarget.useHVXFloatingPoint()) {
436 for (MVT
T : LegalW) {
453 for (MVT
T : LegalV) {
468 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
471 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
476 unsigned HwLen = Subtarget.getVectorLength();
477 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
478 if (ElemTy == MVT::i1)
480 int ElemWidth = ElemTy.getFixedSizeInBits();
481 int MaxElems = (8*HwLen) / ElemWidth;
482 for (
int N = 2;
N < MaxElems;
N *= 2) {
493 if (Subtarget.useHVXFloatingPoint()) {
523 auto HvxType = [=](MVT ScalarT,
unsigned Factor = 1) {
532 typedef std::tuple<MVT, MVT, bool> ReductionSignature;
534 static const std::vector<ReductionSignature> NativeReductions = {
535 {MVT::i32, MVT::i8,
false},
538 for (
const auto &R : NativeReductions) {
540 MVT AccType = std::get<0>(R);
541 MVT InputType = std::get<1>(R);
542 unsigned Factor = std::get<2>(R) ? 2 : 1;
564 for (
unsigned ConcatFactor = 1; ConcatFactor <=
MaxExpandMLA;
566 for (
unsigned ReductionFactor = 1; ReductionFactor <=
MaxExpandMLA;
567 ReductionFactor <<= 1)
568 if (ConcatFactor * ReductionFactor != 1 &&
571 MLAOps, HvxType(AccType, Factor * ConcatFactor),
572 HvxType(InputType, Factor * ConcatFactor * ReductionFactor),
579HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
586 unsigned HwLen = Subtarget.getVectorLength();
589 if (ElemTy == MVT::i1 && VecLen > HwLen)
595 if (ElemTy == MVT::i1) {
610 unsigned HwWidth = 8*HwLen;
611 if (VecWidth > 2*HwWidth)
617 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
626HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
627 unsigned Opc =
Op.getOpcode();
629 case HexagonISD::SMUL_LOHI:
630 case HexagonISD::UMUL_LOHI:
631 case HexagonISD::USMUL_LOHI:
647HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
648 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
652 Tys.second.getVectorNumElements());
655HexagonTargetLowering::TypePair
656HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
659 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
661 return { HalfTy, HalfTy };
665HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
672HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
679HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
688HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
694HexagonTargetLowering::VectorPair
695HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
697 TypePair Tys = typeSplit(ty(Vec));
700 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
704HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
705 return Subtarget.isHVXVectorType(Ty) &&
710HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
711 return Subtarget.isHVXVectorType(Ty) &&
716HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
717 return Subtarget.isHVXVectorType(Ty,
true) &&
721bool HexagonTargetLowering::allowsHvxMemoryAccess(
729 if (!Subtarget.isHVXVectorType(VecTy,
false))
736bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
738 if (!Subtarget.isHVXVectorType(VecTy))
746void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
748 unsigned Opc =
MI.getOpcode();
749 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
750 MachineBasicBlock &MB = *
MI.getParent();
754 auto At =
MI.getIterator();
757 case Hexagon::PS_vsplatib:
758 if (Subtarget.useHVXV62Ops()) {
763 .
add(
MI.getOperand(1));
765 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
771 const MachineOperand &InpOp =
MI.getOperand(1);
773 uint32_t
V = InpOp.
getImm() & 0xFF;
775 .
addImm(V << 24 | V << 16 | V << 8 | V);
781 case Hexagon::PS_vsplatrb:
782 if (Subtarget.useHVXV62Ops()) {
785 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
786 .
add(
MI.getOperand(1));
789 const MachineOperand &InpOp =
MI.getOperand(1);
790 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
793 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
798 case Hexagon::PS_vsplatih:
799 if (Subtarget.useHVXV62Ops()) {
804 .
add(
MI.getOperand(1));
806 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
812 const MachineOperand &InpOp =
MI.getOperand(1);
814 uint32_t
V = InpOp.
getImm() & 0xFFFF;
822 case Hexagon::PS_vsplatrh:
823 if (Subtarget.useHVXV62Ops()) {
826 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
827 .
add(
MI.getOperand(1));
832 const MachineOperand &InpOp =
MI.getOperand(1);
833 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
841 case Hexagon::PS_vsplatiw:
842 case Hexagon::PS_vsplatrw:
843 if (
Opc == Hexagon::PS_vsplatiw) {
847 .
add(
MI.getOperand(1));
848 MI.getOperand(1).ChangeToRegister(SplatV,
false);
851 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
857HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
867 const SDLoc &dl(ElemIdx);
873HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
876 assert(ElemWidth >= 8 && ElemWidth <= 32);
880 if (ty(Idx) != MVT::i32)
882 const SDLoc &dl(Idx);
889HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
896 if (ElemTy == MVT::i8)
900 MVT ResTy = tyVector(OpTy, MVT::i8);
903 SmallVector<int,128> ByteMask;
906 for (
unsigned I = 0;
I != ElemSize; ++
I)
909 int NewM =
M*ElemSize;
910 for (
unsigned I = 0;
I != ElemSize; ++
I)
916 opCastElem(Op1, MVT::i8, DAG), ByteMask);
923 unsigned VecLen =
Values.size();
927 unsigned HwLen = Subtarget.getVectorLength();
929 unsigned ElemSize = ElemWidth / 8;
930 assert(ElemSize*VecLen == HwLen);
934 !(Subtarget.useHVXFloatingPoint() &&
936 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
937 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
939 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
940 SDValue W = buildVector32(
Values.slice(i, OpsPerWord), dl, PartVT, DAG);
948 unsigned NumValues =
Values.size();
951 for (
unsigned i = 0; i != NumValues; ++i) {
955 if (!SplatV.getNode())
957 else if (SplatV !=
Values[i])
965 unsigned NumWords = Words.
size();
967 bool IsSplat =
isSplat(Words, SplatV);
968 if (IsSplat && isUndef(SplatV))
973 return getZero(dl, VecTy, DAG);
982 bool AllConst = getBuildVectorConstInts(
Values, VecTy, DAG, Consts);
985 (Constant**)Consts.end());
987 Align Alignment(HwLen);
1003 SmallVectorImpl<int> &SrcIdx) {
1007 SrcIdx.push_back(-1);
1020 int I =
C->getSExtValue();
1021 assert(
I >= 0 &&
"Negative element index");
1022 SrcIdx.push_back(
I);
1028 SmallVector<int,128> ExtIdx;
1030 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
1031 MVT ExtTy = ty(ExtVec);
1033 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
1037 SmallVector<int,128>
Mask;
1038 BitVector
Used(ExtLen);
1040 for (
int M : ExtIdx) {
1050 for (
unsigned I = 0;
I != ExtLen; ++
I) {
1051 if (
Mask.size() == ExtLen)
1059 return ExtLen == VecLen ? S : LoHalf(S, DAG);
1067 assert(4*Words.
size() == Subtarget.getVectorLength());
1070 for (
unsigned i = 0; i != NumWords; ++i) {
1072 if (Words[i].isUndef())
1074 for (
unsigned j = i;
j != NumWords; ++
j)
1075 if (Words[i] == Words[j])
1078 if (VecHist[i] > VecHist[n])
1082 SDValue HalfV = getZero(dl, VecTy, DAG);
1083 if (VecHist[n] > 1) {
1091 HalfV = DAG.
getNode(HexagonISD::VALIGN, dl, VecTy,
1092 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1104 for (
unsigned i = 0; i != NumWords/2; ++i) {
1106 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1109 N = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1110 {HalfV0, Words[i]});
1113 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1116 M = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1117 {HalfV1, Words[i+NumWords/2]});
1140HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1141 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1142 MVT PredTy = ty(PredV);
1143 unsigned HwLen = Subtarget.getVectorLength();
1146 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1156 SmallVector<int,128>
Mask(HwLen);
1161 for (
unsigned i = 0; i != HwLen; ++i) {
1162 unsigned Num = i % Scale;
1163 unsigned Off = i / Scale;
1172 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1174 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1181 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1193 while (Bytes < BitBytes) {
1195 Words[IdxW].
clear();
1198 for (
const SDValue &W : Words[IdxW ^ 1]) {
1199 SDValue T = expandPredicate(W, dl, DAG);
1204 for (
const SDValue &W : Words[IdxW ^ 1]) {
1212 assert(Bytes == BitBytes);
1213 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1215 for (
const SDValue &W : Words[IdxW]) {
1217 Vec = DAG.
getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1229 unsigned VecLen =
Values.size();
1230 unsigned HwLen = Subtarget.getVectorLength();
1231 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1233 bool AllT =
true, AllF =
true;
1237 return !
N->isZero();
1246 if (VecLen <= HwLen) {
1250 assert(HwLen % VecLen == 0);
1251 unsigned BitBytes = HwLen / VecLen;
1258 for (
unsigned B = 0;
B != BitBytes; ++
B)
1265 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1268 for (;
B != 8; ++
B) {
1287 return DAG.
getNode(HexagonISD::QTRUE, dl, VecTy);
1289 return DAG.
getNode(HexagonISD::QFALSE, dl, VecTy);
1292 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1297HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1302 assert(ElemWidth >= 8 && ElemWidth <= 32);
1305 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1306 SDValue ExWord = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1308 if (ElemTy == MVT::i32)
1314 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1317 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1321HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1324 assert(ResTy == MVT::i1);
1326 unsigned HwLen = Subtarget.getVectorLength();
1330 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1334 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1336 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1340HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1345 assert(ElemWidth >= 8 && ElemWidth <= 32);
1350 MVT VecTy = ty(VecV);
1351 unsigned HwLen = Subtarget.getVectorLength();
1356 SDValue InsV = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1363 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1364 if (ElemTy == MVT::i32)
1365 return InsertWord(VecV, ValV, ByteIdx);
1371 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1376 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1377 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1379 ValV, SubIdx, dl, ElemTy, DAG);
1382 return InsertWord(VecV, Ins, ByteIdx);
1386HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1388 unsigned HwLen = Subtarget.getVectorLength();
1392 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1397 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1402HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1404 MVT VecTy = ty(VecV);
1405 unsigned HwLen = Subtarget.getVectorLength();
1413 if (isHvxPairTy(VecTy)) {
1414 unsigned SubIdx = Hexagon::vsub_lo;
1415 if (Idx * ElemWidth >= 8 * HwLen) {
1416 SubIdx = Hexagon::vsub_hi;
1420 VecTy = typeSplit(VecTy).first;
1430 MVT WordTy = tyVector(VecTy, MVT::i32);
1432 unsigned WordIdx = (Idx*ElemWidth) / 32;
1435 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1440 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1441 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1446HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1448 MVT VecTy = ty(VecV);
1449 unsigned HwLen = Subtarget.getVectorLength();
1457 unsigned Offset = Idx * BitBytes;
1459 SmallVector<int,128>
Mask;
1461 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1468 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1469 for (
unsigned j = 0;
j != Rep; ++
j)
1486 unsigned Rep = 8 / ResLen;
1489 for (
unsigned r = 0; r != HwLen / 8; ++r) {
1491 for (
unsigned i = 0; i != ResLen; ++i) {
1492 for (
unsigned j = 0;
j != Rep; ++
j)
1504 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1505 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1510HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1512 MVT VecTy = ty(VecV);
1513 MVT SubTy = ty(SubV);
1514 unsigned HwLen = Subtarget.getVectorLength();
1518 bool IsPair = isHvxPairTy(VecTy);
1526 V0 = LoHalf(VecV, DAG);
1527 V1 = HiHalf(VecV, DAG);
1532 if (isHvxSingleTy(SubTy)) {
1534 unsigned Idx = CN->getZExtValue();
1536 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1559 if (!IdxN || !IdxN->isZero()) {
1567 unsigned RolBase = HwLen;
1570 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1575 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1578 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1582 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1597HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1599 MVT VecTy = ty(VecV);
1600 MVT SubTy = ty(SubV);
1601 assert(Subtarget.isHVXVectorType(VecTy,
true));
1606 unsigned HwLen = Subtarget.getVectorLength();
1607 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1610 unsigned BitBytes = HwLen / VecLen;
1611 unsigned BlockLen = HwLen / Scale;
1615 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1619 if (!IdxN || !IdxN->isZero()) {
1628 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1630 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1632 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1634 if (!IdxN || !IdxN->isZero()) {
1643HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1648 assert(Subtarget.isHVXVectorType(ResTy));
1655 SDValue False = getZero(dl, ResTy, DAG);
1656 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1660HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1668 unsigned HwLen = Subtarget.getVectorLength();
1670 MVT PredTy = ty(VecQ);
1672 assert(HwLen % PredLen == 0);
1679 for (
unsigned i = 0; i != HwLen/8; ++i) {
1680 for (
unsigned j = 0;
j != 8; ++
j)
1681 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1684 Align Alignment(HwLen);
1694 getZero(dl, VecTy, DAG));
1700 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1702 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1709 SmallVector<int,128>
Mask;
1710 for (
unsigned i = 0; i != HwLen; ++i)
1711 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1721 MVT InpTy = ty(VecV);
1729 return InpWidth < ResWidth
1737 if (InpWidth < ResWidth) {
1739 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1741 unsigned NarOpc =
Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1747HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1751 const SDLoc &dl(Vec);
1760 const SDLoc &dl(
Op);
1765 for (
unsigned i = 0; i !=
Size; ++i)
1766 Ops.push_back(
Op.getOperand(i));
1769 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1777 for (
unsigned i = 0; i !=
Size; i++)
1788 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1790 MVT SingleTy = typeSplit(VecTy).first;
1791 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1792 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1796 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1802 const SDLoc &dl(
Op);
1804 MVT ArgTy = ty(
Op.getOperand(0));
1806 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1824 const SDLoc &dl(
Op);
1841 MVT NTy = typeLegalize(Ty, DAG);
1845 V.getOperand(0),
V.getOperand(1)),
1850 switch (
V.getOpcode()) {
1858 V =
V.getOperand(0);
1869 unsigned HwLen = Subtarget.getVectorLength();
1876 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1878 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, Op0,
Op.getOperand(1));
1884 MVT HalfTy = typeSplit(VecTy).first;
1886 Ops.take_front(NumOp/2));
1888 Ops.take_back(NumOp/2));
1889 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, V0,
V1);
1899 SDValue Combined = combineConcatOfScalarPreds(
Op, BitBytes, DAG);
1902 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1906 unsigned InpLen = ty(Combined.
getOperand(0)).getVectorNumElements();
1909 SDValue Res = getZero(dl, ByteTy, DAG);
1910 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1923 const SDLoc &dl(
Op);
1925 if (ElemTy == MVT::i1)
1926 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1928 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1934 const SDLoc &dl(
Op);
1940 if (ElemTy == MVT::i1)
1941 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1943 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1945 tyVector(VecTy, MVT::i16),
1946 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1948 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1951 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1958 MVT SrcTy = ty(SrcV);
1964 const SDLoc &dl(
Op);
1967 if (ElemTy == MVT::i1)
1968 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1970 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1981 const SDLoc &dl(
Op);
1982 MVT VecTy = ty(VecV);
1984 if (ElemTy == MVT::i1)
1985 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1987 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1999 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2000 return LowerHvxSignExt(
Op, DAG);
2009 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2010 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
2019 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2020 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
2028 const SDLoc &dl(
Op);
2031 assert(ResTy == ty(InpV));
2056 const SDLoc &dl(
Op);
2063 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2064 unsigned Opc =
Op.getOpcode();
2068 return DAG.
getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2070 return DAG.
getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2080 const SDLoc &dl(
Op);
2081 unsigned Opc =
Op.getOpcode();
2086 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2093 bool SignedVu =
Opc == HexagonISD::SMUL_LOHI;
2094 bool SignedVv =
Opc == HexagonISD::SMUL_LOHI ||
Opc == HexagonISD::USMUL_LOHI;
2098 if (Subtarget.useHVXV62Ops())
2099 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2101 if (
Opc == HexagonISD::SMUL_LOHI) {
2104 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2105 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2111 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2118 MVT ValTy = ty(Val);
2119 const SDLoc &dl(
Op);
2122 unsigned HwLen = Subtarget.getVectorLength();
2130 if (PredLen < HwLen) {
2133 if (HwLen > PredLen * 2) {
2134 assert(HwLen == PredLen * 4);
2136 Val = getInstr(Hexagon::V6_vdealh, dl, ByteTy, Val, DAG);
2138 if (HwLen > PredLen) {
2139 assert(HwLen == PredLen * 2);
2140 Val = getInstr(Hexagon::V6_vdealb, dl, ByteTy, Val, DAG);
2145 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2160 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2162 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2167 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2168 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2181 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2182 assert(Val32.getValueType().getSizeInBits() == 32 &&
2183 "Input must be 32 bits");
2187 for (
unsigned i = 0; i < 32; ++i)
2195 if (ResTy == MVT::v32i1 &&
2196 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2197 Subtarget.useHVX128BOps()) {
2199 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2201 return bitcastI32ToV32I1(Val32);
2204 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2222 unsigned HwLen = Subtarget.getVectorLength();
2234 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2238 for (
unsigned J = 0; J != 8; ++J) {
2246 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2258 const SDLoc &dl(
Op);
2261 MVT ValTy = ty(Val);
2264 if (!isHvxBoolTy(ValTy))
2271 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2275 unsigned HwLen = Subtarget.getVectorLength();
2279 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2283 for (
unsigned i = 0; i != NumBits / 32; ++i) {
2294 return DAG.
getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2297 if (NumBits == 64) {
2298 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2302 if (NumBits == 128) {
2303 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2304 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2320 const SDLoc &dl(
Op);
2325 if (!isHvxBoolTy(ResTy))
2331 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2339 if (NumBits == 32) {
2347 if (NumBits == 64) {
2355 if (NumBits == 128) {
2391 const SDLoc &dl(
Op);
2392 unsigned HwLen = Subtarget.getVectorLength();
2394 assert(HwLen % VecLen == 0);
2395 unsigned ElemSize = HwLen / VecLen;
2407 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2413HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2415 unsigned Opc =
Op.getOpcode();
2427 const SDLoc &dl(
Op);
2433 bool UseShifts = ElemTy != MVT::i8;
2434 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2437 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2445 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2451 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2453 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2461 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2463 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2470 const SDLoc &dl(
Op);
2471 unsigned IntNo =
Op.getConstantOperandVal(0);
2479 case Intrinsic::hexagon_V6_pred_typecast:
2480 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2481 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2482 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2489 case Intrinsic::hexagon_V6_vmpyss_parts:
2490 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2491 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2493 case Intrinsic::hexagon_V6_vmpyuu_parts:
2494 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2495 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2497 case Intrinsic::hexagon_V6_vmpyus_parts:
2498 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2499 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2509 const SDLoc &dl(
Op);
2510 unsigned HwLen = Subtarget.getVectorLength();
2514 SDValue Chain = MaskN->getChain();
2518 unsigned Opc =
Op->getOpcode();
2535 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2539 if (MaskN->getAlign().value() % HwLen == 0) {
2548 SDValue Z = getZero(dl, ty(V), DAG);
2552 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2553 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2554 return std::make_pair(LoV, HiV);
2560 VectorPair Tmp = StoreAlign(MaskV,
Base);
2563 VectorPair ValueU = StoreAlign(
Value,
Base);
2567 getInstr(StoreOpc, dl, MVT::Other,
2568 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2570 getInstr(StoreOpc, dl, MVT::Other,
2571 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2581 assert(Subtarget.useHVXQFloatOps());
2586 MVT ArgTy = ty(
Op.getOperand(0));
2587 const SDLoc &dl(
Op);
2589 if (ArgTy == MVT::v64bf16) {
2590 MVT HalfTy = typeSplit(VecTy).first;
2593 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2598 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2599 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2601 {VecPair.second, VecPair.first,
2607 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2616 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2618 MVT HalfTy = typeSplit(VecTy).first;
2619 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2621 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2623 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2626 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2639 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2642 if (Subtarget.useHVXIEEEFPOps()) {
2644 if (FpTy == MVT::f16) {
2646 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2648 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2654 return EqualizeFpIntConversion(
Op, DAG);
2656 return ExpandHvxFpToInt(
Op, DAG);
2672 MVT ResTy = ty(PredOp);
2673 const SDLoc &dl(PredOp);
2676 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2677 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2679 SDNode *PredTransfer =
2682 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2685 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2690 SDNode *IndexShift =
2696 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2721 MVT ResTy = ty(PredOp);
2722 const SDLoc &dl(PredOp);
2732 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2733 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2743 SDNode *PredTransfer =
2747 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2754 SDNode *IndexShift_hi =
2757 SDNode *IndexShift_lo =
2761 SDNode *MaskOff_hi =
2764 SDNode *MaskOff_lo =
2787 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2788 return LowerHvxPred32ToFp(
Op, DAG);
2789 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2790 return LowerHvxPred64ToFp(
Op, DAG);
2793 if (Subtarget.useHVXIEEEFPOps()) {
2795 if (FpTy == MVT::f16) {
2797 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2799 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2805 return EqualizeFpIntConversion(
Op, DAG);
2807 return ExpandHvxIntToFp(
Op, DAG);
2810HexagonTargetLowering::TypePair
2811HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2822 unsigned MaxWidth = std::max(Width0, Width1);
2824 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2831 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2832 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2836 return {WideETy0, WideETy1};
2847HexagonTargetLowering::TypePair
2848HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2858 unsigned MaxLen = std::max(Len0, Len1);
2871HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2872 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2881HexagonTargetLowering::VectorPair
2912HexagonTargetLowering::VectorPair
2913HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2918 const SDLoc &dl(Val);
2919 MVT ValTy = ty(Val);
2933 MVT IntTy = tyVector(ValTy, ElemTy);
2945 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2964 MVT
PairTy = typeJoin({VecTy, VecTy});
2990 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2992 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
3000 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
3005 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3006 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
3007 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
3018HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
3019 bool SignedB,
const SDLoc &dl,
3022 MVT
PairTy = typeJoin({VecTy, VecTy});
3027 if (SignedA && !SignedB) {
3043 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3044 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
3045 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
3054 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3057 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
3061 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3062 {HiHalf(P2, DAG), T3,
S16}, DAG);
3065 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3066 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
3070 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
3077 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
3078 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
3079 }
else if (SignedB) {
3085 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
3087 assert(!SignedA && !SignedB);
3094HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
3099 MVT
PairTy = typeJoin({VecTy, VecTy});
3102 if (SignedA && !SignedB) {
3111 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
3116 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
3128 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
3129 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
3130 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
3131 }
else if (!SignedA) {
3141 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
3159 unsigned Opc =
Op.getOpcode();
3164 MVT InpTy = ty(Inp);
3170 const SDLoc &dl(
Op);
3173 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3182 unsigned Opc =
Op.getOpcode();
3185 const SDLoc &dl(
Op);
3187 MVT InpTy = ty(Op0);
3200 if (InpTy == MVT::v64f16) {
3201 if (Subtarget.useHVXV81Ops()) {
3204 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3208 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3213 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3293 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3294 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3337 unsigned Opc =
Op.getOpcode();
3340 const SDLoc &dl(
Op);
3342 MVT InpTy = ty(Op0);
3375 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3385 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3408 unsigned Opc =
Op.getOpcode();
3425 const SDLoc &dl(
Op);
3426 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3435 unsigned Opc =
Op.getConstantOperandVal(2);
3439HexagonTargetLowering::VectorPair
3443 const SDLoc &dl(
Op);
3445 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3446 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3448 return std::make_pair(TV, TV);
3453 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3455 switch (
Op.getOpcode()) {
3456 case ISD::SIGN_EXTEND_INREG:
3457 case HexagonISD::SSAT:
3458 case HexagonISD::USAT:
3459 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3460 std::tie(Lo, Hi) = SplitVTNode(N);
3468 MVT HalfTy = typeSplit(ResTy).first;
3477 unsigned MemOpc = MemN->getOpcode();
3478 EVT MemTy = MemN->getMemoryVT();
3495 EVT LoMemVT, HiMemVT;
3496 bool HiIsEmpty =
false;
3497 std::tie(LoMemVT, HiMemVT) =
3503 const SDLoc &dl(
Op);
3504 SDValue Chain = MemN->getChain();
3505 SDValue Base0 = MemN->getBasePtr();
3509 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3510 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3512 auto MemSize = [=](uint64_t
Size) {
3546 assert(MaskN->isUnindexed());
3547 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3554 Masks.first, Thru.first, LoMemVT, MOp0,
3563 Masks.second, Thru.second, HiMemVT, MOp1,
3585 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3591 const SDLoc &dl(
Op);
3593 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3594 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3595 "Not widening loads of i1 yet");
3597 SDValue Chain = LoadN->getChain();
3602 unsigned HwLen = Subtarget.getVectorLength();
3604 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3607 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3615 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3623 const SDLoc &dl(
Op);
3625 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3626 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3627 "Not widening stores of i1 yet");
3629 SDValue Chain = StoreN->getChain();
3633 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3634 MVT ValueTy = ty(
Value);
3636 unsigned HwLen = Subtarget.getVectorLength();
3639 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3641 Len = ty(
Value).getVectorNumElements();
3643 assert(ty(
Value).getVectorNumElements() == HwLen);
3645 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3647 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3650 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3657 const SDLoc &dl(
Op);
3658 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3660 unsigned HwLen = Subtarget.getVectorLength();
3665 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3668 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3669 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3673 {WideOp0, WideOp1,
Op.getOperand(2)});
3675 EVT RetTy = typeLegalize(ty(
Op), DAG);
3677 {SetCC, getZero(dl, MVT::i32, DAG)});
3687 const SDLoc &dl(
Op);
3689 MVT InpTy = ty(Inp);
3693 "Expected boolean result type");
3696 unsigned HwLen = Subtarget.getVectorLength();
3701 if (!Subtarget.isHVXVectorType(WideInpTy,
false))
3705 SDValue WideInp = appendUndef(Inp, WideInpTy, DAG);
3712 EVT RetTy = typeLegalize(ResTy, DAG);
3714 {WideTrunc, getZero(dl, MVT::i32, DAG)});
3719 unsigned Opc =
Op.getOpcode();
3720 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3722 return isHvxPairTy(ty(V));
3733 return SplitHvxMemOp(
Op, DAG);
3738 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3739 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3771 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3776 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3777 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3801 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3803 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3824 case HexagonISD::SMUL_LOHI:
3825 case HexagonISD::UMUL_LOHI:
3826 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3831 return LowerHvxPartialReduceMLA(
Op, DAG);
3849 unsigned Opc =
Op.getOpcode();
3851 case HexagonISD::SSAT:
3852 case HexagonISD::USAT:
3869 MVT InpTy = ty(Inp);
3874 assert(InpWidth != ResWidth);
3876 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3879 const SDLoc &dl(
Op);
3883 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3886 case HexagonISD::SSAT:
3887 case HexagonISD::USAT:
3891 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3898 if (InpWidth < ResWidth) {
3900 while (InpWidth * 2 <= ResWidth)
3901 S = repeatOp(InpWidth *= 2, S);
3905 while (InpWidth / 2 >= ResWidth)
3906 S = repeatOp(InpWidth /= 2, S);
3914 MVT InpTy = ty(Inp0);
3918 unsigned Opc =
Op.getOpcode();
3920 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3925 auto [WInpTy, WResTy] =
3926 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3927 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3928 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3936 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3937 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3938 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3945 SDValue T = ExpandHvxResizeIntoSteps(
Op, DAG);
3948 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3951 return RemoveTLWrapper(
Op, DAG);
3957HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3959 unsigned Opc =
N->getOpcode();
3962 if (
N->getNumOperands() > 0)
3963 Inp0 =
Op.getOperand(0);
3969 if (Subtarget.isHVXElementType(ty(
Op)) &&
3970 Subtarget.isHVXElementType(ty(Inp0))) {
3971 Results.push_back(CreateTLWrapper(
Op, DAG));
3983 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
3984 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
3986 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
3987 Subtarget.isHVXElementType(ty(Inp0))) {
3988 Results.push_back(CreateTLWrapper(
Op, DAG));
3992 if (shouldWidenToHvx(ty(Inp0), DAG)) {
4005 if (isHvxPairTy(ty(
Op))) {
4013 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
4022 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4023 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4027 case HexagonISD::SSAT:
4028 case HexagonISD::USAT:
4031 Results.push_back(LegalizeHvxResize(
Op, DAG));
4039HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
4041 unsigned Opc =
N->getOpcode();
4044 if (
N->getNumOperands() > 0)
4045 Inp0 =
Op.getOperand(0);
4051 if (Subtarget.isHVXElementType(ty(
Op)) &&
4052 Subtarget.isHVXElementType(ty(Inp0))) {
4053 Results.push_back(CreateTLWrapper(
Op, DAG));
4060 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4061 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
4063 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4064 Subtarget.isHVXElementType(ty(Inp0))) {
4065 Results.push_back(CreateTLWrapper(
Op, DAG));
4069 if (shouldWidenToHvx(ty(
Op), DAG)) {
4075 if (shouldWidenToHvx(ty(
Op), DAG)) {
4084 if (isHvxBoolTy(ty(Inp0))) {
4091 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4092 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4096 case HexagonISD::SSAT:
4097 case HexagonISD::USAT:
4100 Results.push_back(LegalizeHvxResize(
Op, DAG));
4108HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
4109 DAGCombinerInfo &DCI)
const {
4114 SelectionDAG &DAG = DCI.DAG;
4115 const SDLoc &dl(
Op);
4122 EVT TruncTy =
Op.getValueType();
4124 EVT SrcTy = Src.getValueType();
4131 if (2 * CastLen != SrcLen)
4134 SmallVector<int, 128>
Mask(SrcLen);
4135 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
4137 Mask[i + CastLen] = 2 * i + 1;
4141 return opSplit(Deal, dl, DAG).first;
4145HexagonTargetLowering::combineConcatOfShuffles(
SDValue Op,
4154 const SDLoc &dl(
Op);
4163 SetVector<SDValue> Order;
4169 if (Order.
size() > 2)
4178 SmallVector<int, 128> LongMask;
4179 auto AppendToMask = [&](
SDValue Shuffle) {
4181 ArrayRef<int>
Mask = SV->getMask();
4184 for (
int M : Mask) {
4189 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
4190 if (
static_cast<unsigned>(M) >= InpLen)
4193 int OutOffset = Order[0] == Src ? 0 : InpLen;
4216HexagonTargetLowering::combineConcatOfScalarPreds(
SDValue Op,
unsigned BitBytes,
4218 const SDLoc &dl(
Op);
4221 MVT InpTy = ty(
Ops[0]);
4224 assert(InpLen <= 8 &&
"Too long for scalar predicate");
4225 assert(ResLen > 8 &&
"Too short for HVX vector predicate");
4227 unsigned Bytes = 8 / InpLen;
4230 if (Bytes <= BitBytes)
4234 unsigned SliceLen = Bytes / BitBytes;
4239 for (
unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4241 Inputs.slice(SliceLen * i, SliceLen));
4248SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4249 SDValue Op, DAGCombinerInfo &DCI)
const {
4253 if (ElemTy != MVT::i1) {
4254 return combineConcatOfShuffles(
Op, DCI.DAG);
4261SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4262 unsigned Opcode,
EVT AccEltType,
unsigned AccNumElements,
EVT InputType,
4265 const auto &Subtarget = DAG.
getSubtarget<HexagonSubtarget>();
4266 if (!Subtarget.useHVXOps())
4272 unsigned NativeRatio;
4273 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4285 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4286 if (RemainingReductionRatio == 1)
4291 InputNumElements / NativeRatio);
4294 return DAG.
getNode(Opcode,
DL, IntermediateType, Zero,
A,
B);
4300 EVT AccType =
Mul.getValueType();
4306 A =
Mul->getOperand(0);
4307 B =
Mul->getOperand(1);
4327 A =
A->getOperand(0);
4328 B =
B->getOperand(0);
4329 if (
A.getValueType() !=
B.getValueType())
4340 if (!Subtarget.useHVXOps())
4343 EVT ScalarType =
N->getValueType(0);
4350 unsigned RemainingReductionRatio;
4352 createExtendingPartialReduceMLA(Opcode, ScalarType, 1,
A.getValueType(),
4353 A,
B, RemainingReductionRatio,
DL, DAG);
4370HexagonTargetLowering::splitExtendingPartialReduceMLA(
SDNode *
N,
4372 if (!Subtarget.useHVXOps())
4378 if (
A.getValueType() !=
B.getValueType())
4384 EVT InputType =
A.getValueType();
4389 unsigned RemainingReductionRatio;
4390 SDValue Partial = createExtendingPartialReduceMLA(
4404 DL, AccType, Acc, Partial, One);
4408HexagonTargetLowering::LowerHvxPartialReduceMLA(
SDValue Op,
4410 const SDLoc &
DL(
Op);
4416 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4420 unsigned AccSubvectorNumElements =
4422 EVT AccSubvectorType =
4425 EVT InputType =
A.getValueType();
4428 unsigned InputSubvectorNumElements =
4431 InputSubvectorNumElements);
4436 for (
unsigned I = 0;
I != SubvectorNum; ++
I) {
4438 I * AccSubvectorNumElements);
4440 I * InputSubvectorNumElements);
4442 I * InputSubvectorNumElements);
4444 SubvectorAcc, SubvectorA, SubvectorB);
4452HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
4455 SelectionDAG &DAG = DCI.DAG;
4457 unsigned Opc =
Op.getOpcode();
4462 return combineTruncateBeforeLegal(
Op, DCI);
4464 return combineConcatVectorsBeforeLegal(
Op, DCI);
4466 if (DCI.isBeforeLegalizeOps())
4473 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
4474 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
4482 return getZero(dl, ty(
Op), DAG);
4484 case HexagonISD::VINSERTW0:
4485 if (isUndef(
Ops[1]))
4503HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4504 if (Subtarget.isHVXVectorType(Ty,
true))
4506 auto Action = getPreferredHvxVectorAction(Ty);
4508 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4513HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4514 if (Subtarget.isHVXVectorType(Ty,
true))
4516 auto Action = getPreferredHvxVectorAction(Ty);
4518 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4524 if (!Subtarget.useHVXOps())
4528 auto IsHvxTy = [
this](EVT Ty) {
4529 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4532 return Op.getValueType().isSimple() &&
4533 Subtarget.isHVXVectorType(ty(
Op),
true);
4539 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
4540 if (!
Op.getValueType().isSimple())
4543 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4546 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 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,...
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