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) {
181 if (Subtarget.useHVXV81Ops()) {
184 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
185 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
186 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
187 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
213 for (MVT
P : FloatW) {
235 if (Subtarget.useHVXQFloatOps()) {
238 }
else if (Subtarget.useHVXIEEEFPOps()) {
244 for (MVT
T : LegalV) {
271 if (
T.getScalarType() != MVT::i32) {
280 if (
T.getScalarType() != MVT::i32) {
308 if (Subtarget.useHVXFloatingPoint()) {
325 for (MVT
T : LegalW) {
380 if (
T.getScalarType() != MVT::i32) {
385 if (Subtarget.useHVXFloatingPoint()) {
432 for (MVT
T : LegalW) {
449 for (MVT
T : LegalV) {
464 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
467 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
472 unsigned HwLen = Subtarget.getVectorLength();
473 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
474 if (ElemTy == MVT::i1)
476 int ElemWidth = ElemTy.getFixedSizeInBits();
477 int MaxElems = (8*HwLen) / ElemWidth;
478 for (
int N = 2;
N < MaxElems;
N *= 2) {
489 if (Subtarget.useHVXFloatingPoint()) {
519 auto HvxType = [=](MVT ScalarT,
unsigned Factor = 1) {
528 typedef std::tuple<MVT, MVT, bool> ReductionSignature;
530 static const std::vector<ReductionSignature> NativeReductions = {
531 {MVT::i32, MVT::i8,
false},
534 for (
const auto &R : NativeReductions) {
536 MVT AccType = std::get<0>(R);
537 MVT InputType = std::get<1>(R);
538 unsigned Factor = std::get<2>(R) ? 2 : 1;
560 for (
unsigned ConcatFactor = 1; ConcatFactor <=
MaxExpandMLA;
562 for (
unsigned ReductionFactor = 1; ReductionFactor <=
MaxExpandMLA;
563 ReductionFactor <<= 1)
564 if (ConcatFactor * ReductionFactor != 1 &&
567 MLAOps, HvxType(AccType, Factor * ConcatFactor),
568 HvxType(InputType, Factor * ConcatFactor * ReductionFactor),
575HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
582 unsigned HwLen = Subtarget.getVectorLength();
585 if (ElemTy == MVT::i1 && VecLen > HwLen)
591 if (ElemTy == MVT::i1) {
606 unsigned HwWidth = 8*HwLen;
607 if (VecWidth > 2*HwWidth)
613 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
622HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
623 unsigned Opc =
Op.getOpcode();
625 case HexagonISD::SMUL_LOHI:
626 case HexagonISD::UMUL_LOHI:
627 case HexagonISD::USMUL_LOHI:
643HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
644 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
648 Tys.second.getVectorNumElements());
651HexagonTargetLowering::TypePair
652HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
655 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
657 return { HalfTy, HalfTy };
661HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
668HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
675HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
684HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
690HexagonTargetLowering::VectorPair
691HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
693 TypePair Tys = typeSplit(ty(Vec));
696 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
700HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
701 return Subtarget.isHVXVectorType(Ty) &&
706HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
707 return Subtarget.isHVXVectorType(Ty) &&
712HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
713 return Subtarget.isHVXVectorType(Ty,
true) &&
717bool HexagonTargetLowering::allowsHvxMemoryAccess(
725 if (!Subtarget.isHVXVectorType(VecTy,
false))
732bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
734 if (!Subtarget.isHVXVectorType(VecTy))
742void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
744 unsigned Opc =
MI.getOpcode();
745 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
746 MachineBasicBlock &MB = *
MI.getParent();
750 auto At =
MI.getIterator();
753 case Hexagon::PS_vsplatib:
754 if (Subtarget.useHVXV62Ops()) {
759 .
add(
MI.getOperand(1));
761 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
767 const MachineOperand &InpOp =
MI.getOperand(1);
769 uint32_t
V = InpOp.
getImm() & 0xFF;
771 .
addImm(V << 24 | V << 16 | V << 8 | V);
777 case Hexagon::PS_vsplatrb:
778 if (Subtarget.useHVXV62Ops()) {
781 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
782 .
add(
MI.getOperand(1));
785 const MachineOperand &InpOp =
MI.getOperand(1);
786 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
789 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
794 case Hexagon::PS_vsplatih:
795 if (Subtarget.useHVXV62Ops()) {
800 .
add(
MI.getOperand(1));
802 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
808 const MachineOperand &InpOp =
MI.getOperand(1);
810 uint32_t
V = InpOp.
getImm() & 0xFFFF;
818 case Hexagon::PS_vsplatrh:
819 if (Subtarget.useHVXV62Ops()) {
822 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
823 .
add(
MI.getOperand(1));
828 const MachineOperand &InpOp =
MI.getOperand(1);
829 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
837 case Hexagon::PS_vsplatiw:
838 case Hexagon::PS_vsplatrw:
839 if (
Opc == Hexagon::PS_vsplatiw) {
843 .
add(
MI.getOperand(1));
844 MI.getOperand(1).ChangeToRegister(SplatV,
false);
847 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
853HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
863 const SDLoc &dl(ElemIdx);
869HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
872 assert(ElemWidth >= 8 && ElemWidth <= 32);
876 if (ty(Idx) != MVT::i32)
878 const SDLoc &dl(Idx);
885HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
892 if (ElemTy == MVT::i8)
896 MVT ResTy = tyVector(OpTy, MVT::i8);
899 SmallVector<int,128> ByteMask;
902 for (
unsigned I = 0;
I != ElemSize; ++
I)
905 int NewM =
M*ElemSize;
906 for (
unsigned I = 0;
I != ElemSize; ++
I)
912 opCastElem(Op1, MVT::i8, DAG), ByteMask);
919 unsigned VecLen = Values.
size();
923 unsigned HwLen = Subtarget.getVectorLength();
925 unsigned ElemSize = ElemWidth / 8;
926 assert(ElemSize*VecLen == HwLen);
930 !(Subtarget.useHVXFloatingPoint() &&
932 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
933 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
935 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
936 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
944 unsigned NumValues = Values.size();
947 for (
unsigned i = 0; i != NumValues; ++i) {
948 if (Values[i].isUndef())
951 if (!SplatV.getNode())
953 else if (SplatV != Values[i])
961 unsigned NumWords = Words.
size();
963 bool IsSplat =
isSplat(Words, SplatV);
964 if (IsSplat && isUndef(SplatV))
969 return getZero(dl, VecTy, DAG);
978 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
981 (Constant**)Consts.end());
983 Align Alignment(HwLen);
998 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
999 SmallVectorImpl<int> &SrcIdx) {
1003 SrcIdx.push_back(-1);
1016 int I =
C->getSExtValue();
1017 assert(
I >= 0 &&
"Negative element index");
1018 SrcIdx.push_back(
I);
1024 SmallVector<int,128> ExtIdx;
1026 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
1027 MVT ExtTy = ty(ExtVec);
1029 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
1033 SmallVector<int,128>
Mask;
1034 BitVector
Used(ExtLen);
1036 for (
int M : ExtIdx) {
1046 for (
unsigned I = 0;
I != ExtLen; ++
I) {
1047 if (
Mask.size() == ExtLen)
1055 return ExtLen == VecLen ? S : LoHalf(S, DAG);
1063 assert(4*Words.
size() == Subtarget.getVectorLength());
1066 for (
unsigned i = 0; i != NumWords; ++i) {
1068 if (Words[i].isUndef())
1070 for (
unsigned j = i;
j != NumWords; ++
j)
1071 if (Words[i] == Words[j])
1074 if (VecHist[i] > VecHist[n])
1078 SDValue HalfV = getZero(dl, VecTy, DAG);
1079 if (VecHist[n] > 1) {
1081 HalfV = DAG.
getNode(HexagonISD::VALIGN, dl, VecTy,
1082 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1094 for (
unsigned i = 0; i != NumWords/2; ++i) {
1096 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1099 N = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1100 {HalfV0, Words[i]});
1103 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1106 M = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1107 {HalfV1, Words[i+NumWords/2]});
1130HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1131 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1132 MVT PredTy = ty(PredV);
1133 unsigned HwLen = Subtarget.getVectorLength();
1136 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1146 SmallVector<int,128>
Mask(HwLen);
1151 for (
unsigned i = 0; i != HwLen; ++i) {
1152 unsigned Num = i % Scale;
1153 unsigned Off = i / Scale;
1162 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1164 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1171 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1183 while (Bytes < BitBytes) {
1185 Words[IdxW].
clear();
1188 for (
const SDValue &W : Words[IdxW ^ 1]) {
1189 SDValue T = expandPredicate(W, dl, DAG);
1194 for (
const SDValue &W : Words[IdxW ^ 1]) {
1202 assert(Bytes == BitBytes);
1203 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1205 for (
const SDValue &W : Words[IdxW]) {
1207 Vec = DAG.
getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1219 unsigned VecLen = Values.
size();
1220 unsigned HwLen = Subtarget.getVectorLength();
1221 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1223 bool AllT =
true, AllF =
true;
1227 return !
N->isZero();
1236 if (VecLen <= HwLen) {
1240 assert(HwLen % VecLen == 0);
1241 unsigned BitBytes = HwLen / VecLen;
1248 for (
unsigned B = 0;
B != BitBytes; ++
B)
1255 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1258 for (;
B != 8; ++
B) {
1259 if (!Values[
I+
B].isUndef())
1272 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1277 return DAG.
getNode(HexagonISD::QTRUE, dl, VecTy);
1279 return DAG.
getNode(HexagonISD::QFALSE, dl, VecTy);
1282 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1287HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1292 assert(ElemWidth >= 8 && ElemWidth <= 32);
1295 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1296 SDValue ExWord = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1298 if (ElemTy == MVT::i32)
1304 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1307 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1311HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1314 assert(ResTy == MVT::i1);
1316 unsigned HwLen = Subtarget.getVectorLength();
1320 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1324 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1326 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1330HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1335 assert(ElemWidth >= 8 && ElemWidth <= 32);
1340 MVT VecTy = ty(VecV);
1341 unsigned HwLen = Subtarget.getVectorLength();
1346 SDValue InsV = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1353 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1354 if (ElemTy == MVT::i32)
1355 return InsertWord(VecV, ValV, ByteIdx);
1361 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1366 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1367 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1369 ValV, SubIdx, dl, ElemTy, DAG);
1372 return InsertWord(VecV, Ins, ByteIdx);
1376HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1378 unsigned HwLen = Subtarget.getVectorLength();
1382 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1387 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1392HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1394 MVT VecTy = ty(VecV);
1395 unsigned HwLen = Subtarget.getVectorLength();
1403 if (isHvxPairTy(VecTy)) {
1404 unsigned SubIdx = Hexagon::vsub_lo;
1405 if (Idx * ElemWidth >= 8 * HwLen) {
1406 SubIdx = Hexagon::vsub_hi;
1410 VecTy = typeSplit(VecTy).first;
1420 MVT WordTy = tyVector(VecTy, MVT::i32);
1422 unsigned WordIdx = (Idx*ElemWidth) / 32;
1425 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1430 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1431 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1436HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1438 MVT VecTy = ty(VecV);
1439 unsigned HwLen = Subtarget.getVectorLength();
1447 unsigned Offset = Idx * BitBytes;
1449 SmallVector<int,128>
Mask;
1451 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1458 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1459 for (
unsigned j = 0;
j != Rep; ++
j)
1476 unsigned Rep = 8 / ResLen;
1479 for (
unsigned r = 0; r != HwLen / 8; ++r) {
1481 for (
unsigned i = 0; i != ResLen; ++i) {
1482 for (
unsigned j = 0;
j != Rep; ++
j)
1494 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1495 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1500HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1502 MVT VecTy = ty(VecV);
1503 MVT SubTy = ty(SubV);
1504 unsigned HwLen = Subtarget.getVectorLength();
1508 bool IsPair = isHvxPairTy(VecTy);
1516 V0 = LoHalf(VecV, DAG);
1517 V1 = HiHalf(VecV, DAG);
1522 if (isHvxSingleTy(SubTy)) {
1524 unsigned Idx = CN->getZExtValue();
1526 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1549 if (!IdxN || !IdxN->isZero()) {
1557 unsigned RolBase = HwLen;
1560 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1565 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1568 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1572 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1587HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1589 MVT VecTy = ty(VecV);
1590 MVT SubTy = ty(SubV);
1591 assert(Subtarget.isHVXVectorType(VecTy,
true));
1596 unsigned HwLen = Subtarget.getVectorLength();
1597 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1600 unsigned BitBytes = HwLen / VecLen;
1601 unsigned BlockLen = HwLen / Scale;
1605 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1609 if (!IdxN || !IdxN->isZero()) {
1618 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1620 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1622 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1624 if (!IdxN || !IdxN->isZero()) {
1633HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1638 assert(Subtarget.isHVXVectorType(ResTy));
1645 SDValue False = getZero(dl, ResTy, DAG);
1646 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1650HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1658 unsigned HwLen = Subtarget.getVectorLength();
1660 MVT PredTy = ty(VecQ);
1662 assert(HwLen % PredLen == 0);
1669 for (
unsigned i = 0; i != HwLen/8; ++i) {
1670 for (
unsigned j = 0;
j != 8; ++
j)
1671 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1674 Align Alignment(HwLen);
1684 getZero(dl, VecTy, DAG));
1690 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1692 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1699 SmallVector<int,128>
Mask;
1700 for (
unsigned i = 0; i != HwLen; ++i)
1701 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1711 MVT InpTy = ty(VecV);
1719 return InpWidth < ResWidth
1727 if (InpWidth < ResWidth) {
1729 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1731 unsigned NarOpc =
Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1737HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1741 const SDLoc &dl(Vec);
1750 const SDLoc &dl(
Op);
1755 for (
unsigned i = 0; i !=
Size; ++i)
1756 Ops.push_back(
Op.getOperand(i));
1759 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1767 for (
unsigned i = 0; i !=
Size; i++)
1778 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1780 MVT SingleTy = typeSplit(VecTy).first;
1781 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1782 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1786 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1792 const SDLoc &dl(
Op);
1794 MVT ArgTy = ty(
Op.getOperand(0));
1796 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1814 const SDLoc &dl(
Op);
1831 MVT NTy = typeLegalize(Ty, DAG);
1835 V.getOperand(0),
V.getOperand(1)),
1840 switch (
V.getOpcode()) {
1848 V =
V.getOperand(0);
1859 unsigned HwLen = Subtarget.getVectorLength();
1866 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1868 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, Op0,
Op.getOperand(1));
1874 MVT HalfTy = typeSplit(VecTy).first;
1876 Ops.take_front(NumOp/2));
1878 Ops.take_back(NumOp/2));
1879 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, V0, V1);
1889 SDValue Combined = combineConcatOfScalarPreds(
Op, BitBytes, DAG);
1892 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1896 unsigned InpLen = ty(Combined.
getOperand(0)).getVectorNumElements();
1899 SDValue Res = getZero(dl, ByteTy, DAG);
1900 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1913 const SDLoc &dl(
Op);
1915 if (ElemTy == MVT::i1)
1916 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1918 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1924 const SDLoc &dl(
Op);
1930 if (ElemTy == MVT::i1)
1931 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1933 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1935 tyVector(VecTy, MVT::i16),
1936 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1938 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1941 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1948 MVT SrcTy = ty(SrcV);
1954 const SDLoc &dl(
Op);
1957 if (ElemTy == MVT::i1)
1958 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1960 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1971 const SDLoc &dl(
Op);
1972 MVT VecTy = ty(VecV);
1974 if (ElemTy == MVT::i1)
1975 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1977 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1989 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1990 return LowerHvxSignExt(
Op, DAG);
1999 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2000 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
2009 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2010 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
2018 const SDLoc &dl(
Op);
2021 assert(ResTy == ty(InpV));
2046 const SDLoc &dl(
Op);
2053 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2054 unsigned Opc =
Op.getOpcode();
2058 return DAG.
getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2060 return DAG.
getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2070 const SDLoc &dl(
Op);
2071 unsigned Opc =
Op.getOpcode();
2076 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2083 bool SignedVu =
Opc == HexagonISD::SMUL_LOHI;
2084 bool SignedVv =
Opc == HexagonISD::SMUL_LOHI ||
Opc == HexagonISD::USMUL_LOHI;
2088 if (Subtarget.useHVXV62Ops())
2089 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2091 if (
Opc == HexagonISD::SMUL_LOHI) {
2094 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2095 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2101 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2108 MVT ValTy = ty(Val);
2109 const SDLoc &dl(
Op);
2112 unsigned HwLen = Subtarget.getVectorLength();
2120 if (PredLen < HwLen) {
2123 if (HwLen > PredLen * 2) {
2124 assert(HwLen == PredLen * 4);
2126 Val = getInstr(Hexagon::V6_vdealh, dl, ByteTy, Val, DAG);
2128 if (HwLen > PredLen) {
2129 assert(HwLen == PredLen * 2);
2130 Val = getInstr(Hexagon::V6_vdealb, dl, ByteTy, Val, DAG);
2135 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2150 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2152 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2157 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2158 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2171 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2172 assert(Val32.getValueType().getSizeInBits() == 32 &&
2173 "Input must be 32 bits");
2177 for (
unsigned i = 0; i < 32; ++i)
2185 if (ResTy == MVT::v32i1 &&
2186 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2187 Subtarget.useHVX128BOps()) {
2189 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2191 return bitcastI32ToV32I1(Val32);
2194 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2212 unsigned HwLen = Subtarget.getVectorLength();
2224 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2228 for (
unsigned J = 0; J != 8; ++J) {
2236 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2248 const SDLoc &dl(
Op);
2251 MVT ValTy = ty(Val);
2254 if (!isHvxBoolTy(ValTy))
2261 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2265 unsigned HwLen = Subtarget.getVectorLength();
2269 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2273 for (
unsigned i = 0; i != NumBits / 32; ++i) {
2284 return DAG.
getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2287 if (NumBits == 64) {
2288 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2292 if (NumBits == 128) {
2293 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2294 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2310 const SDLoc &dl(
Op);
2315 if (!isHvxBoolTy(ResTy))
2321 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2329 if (NumBits == 32) {
2337 if (NumBits == 64) {
2345 if (NumBits == 128) {
2381 const SDLoc &dl(
Op);
2382 unsigned HwLen = Subtarget.getVectorLength();
2384 assert(HwLen % VecLen == 0);
2385 unsigned ElemSize = HwLen / VecLen;
2397 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2403HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2405 unsigned Opc =
Op.getOpcode();
2417 const SDLoc &dl(
Op);
2423 bool UseShifts = ElemTy != MVT::i8;
2424 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2427 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2435 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2441 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2443 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2451 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2453 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2460 const SDLoc &dl(
Op);
2461 unsigned IntNo =
Op.getConstantOperandVal(0);
2469 case Intrinsic::hexagon_V6_pred_typecast:
2470 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2471 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2472 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2479 case Intrinsic::hexagon_V6_vmpyss_parts:
2480 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2481 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2483 case Intrinsic::hexagon_V6_vmpyuu_parts:
2484 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2485 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2487 case Intrinsic::hexagon_V6_vmpyus_parts:
2488 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2489 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2499 const SDLoc &dl(
Op);
2500 unsigned HwLen = Subtarget.getVectorLength();
2504 SDValue Chain = MaskN->getChain();
2508 unsigned Opc =
Op->getOpcode();
2525 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2529 if (MaskN->getAlign().value() % HwLen == 0) {
2538 SDValue Z = getZero(dl, ty(V), DAG);
2542 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2543 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2544 return std::make_pair(LoV, HiV);
2550 VectorPair Tmp = StoreAlign(MaskV,
Base);
2553 VectorPair ValueU = StoreAlign(
Value,
Base);
2557 getInstr(StoreOpc, dl, MVT::Other,
2558 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2560 getInstr(StoreOpc, dl, MVT::Other,
2561 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2571 assert(Subtarget.useHVXQFloatOps());
2576 MVT ArgTy = ty(
Op.getOperand(0));
2577 const SDLoc &dl(
Op);
2579 if (ArgTy == MVT::v64bf16) {
2580 MVT HalfTy = typeSplit(VecTy).first;
2583 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2588 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2589 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2591 {VecPair.second, VecPair.first,
2597 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2606 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2608 MVT HalfTy = typeSplit(VecTy).first;
2609 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2611 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2613 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2616 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2629 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2632 if (Subtarget.useHVXIEEEFPOps()) {
2634 if (FpTy == MVT::f16) {
2636 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2638 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2644 return EqualizeFpIntConversion(
Op, DAG);
2646 return ExpandHvxFpToInt(
Op, DAG);
2662 MVT ResTy = ty(PredOp);
2663 const SDLoc &dl(PredOp);
2666 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2667 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2669 SDNode *PredTransfer =
2672 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2675 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2680 SDNode *IndexShift =
2686 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2711 MVT ResTy = ty(PredOp);
2712 const SDLoc &dl(PredOp);
2722 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2723 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2733 SDNode *PredTransfer =
2737 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2744 SDNode *IndexShift_hi =
2747 SDNode *IndexShift_lo =
2751 SDNode *MaskOff_hi =
2754 SDNode *MaskOff_lo =
2777 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2778 return LowerHvxPred32ToFp(
Op, DAG);
2779 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2780 return LowerHvxPred64ToFp(
Op, DAG);
2783 if (Subtarget.useHVXIEEEFPOps()) {
2785 if (FpTy == MVT::f16) {
2787 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2789 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2795 return EqualizeFpIntConversion(
Op, DAG);
2797 return ExpandHvxIntToFp(
Op, DAG);
2800HexagonTargetLowering::TypePair
2801HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2812 unsigned MaxWidth = std::max(Width0, Width1);
2814 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2821 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2822 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2826 return {WideETy0, WideETy1};
2837HexagonTargetLowering::TypePair
2838HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2848 unsigned MaxLen = std::max(Len0, Len1);
2861HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2862 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2871HexagonTargetLowering::VectorPair
2902HexagonTargetLowering::VectorPair
2903HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2908 const SDLoc &dl(Val);
2909 MVT ValTy = ty(Val);
2923 MVT IntTy = tyVector(ValTy, ElemTy);
2935 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2954 MVT
PairTy = typeJoin({VecTy, VecTy});
2980 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2982 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2990 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2995 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2996 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2997 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
3008HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
3009 bool SignedB,
const SDLoc &dl,
3012 MVT
PairTy = typeJoin({VecTy, VecTy});
3017 if (SignedA && !SignedB) {
3033 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3034 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
3035 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
3044 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3047 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
3051 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3052 {HiHalf(P2, DAG), T3,
S16}, DAG);
3055 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3056 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
3060 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
3067 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
3068 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
3069 }
else if (SignedB) {
3075 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
3077 assert(!SignedA && !SignedB);
3084HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
3089 MVT
PairTy = typeJoin({VecTy, VecTy});
3092 if (SignedA && !SignedB) {
3101 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
3106 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
3118 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
3119 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
3120 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
3121 }
else if (!SignedA) {
3131 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
3149 unsigned Opc =
Op.getOpcode();
3154 MVT InpTy = ty(Inp);
3160 const SDLoc &dl(
Op);
3163 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3172 unsigned Opc =
Op.getOpcode();
3175 const SDLoc &dl(
Op);
3177 MVT InpTy = ty(Op0);
3190 if (InpTy == MVT::v64f16) {
3191 if (Subtarget.useHVXV81Ops()) {
3194 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3198 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3203 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3283 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3284 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3327 unsigned Opc =
Op.getOpcode();
3330 const SDLoc &dl(
Op);
3332 MVT InpTy = ty(Op0);
3365 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3375 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3398 unsigned Opc =
Op.getOpcode();
3415 const SDLoc &dl(
Op);
3416 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3425 unsigned Opc =
Op.getConstantOperandVal(2);
3429HexagonTargetLowering::VectorPair
3433 const SDLoc &dl(
Op);
3435 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3436 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3438 return std::make_pair(TV, TV);
3443 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3445 switch (
Op.getOpcode()) {
3446 case ISD::SIGN_EXTEND_INREG:
3447 case HexagonISD::SSAT:
3448 case HexagonISD::USAT:
3449 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3450 std::tie(Lo, Hi) = SplitVTNode(N);
3458 MVT HalfTy = typeSplit(ResTy).first;
3467 unsigned MemOpc = MemN->getOpcode();
3468 EVT MemTy = MemN->getMemoryVT();
3485 EVT LoMemVT, HiMemVT;
3486 bool HiIsEmpty =
false;
3487 std::tie(LoMemVT, HiMemVT) =
3493 const SDLoc &dl(
Op);
3494 SDValue Chain = MemN->getChain();
3495 SDValue Base0 = MemN->getBasePtr();
3499 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3500 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3502 auto MemSize = [=](uint64_t
Size) {
3536 assert(MaskN->isUnindexed());
3537 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3544 Masks.first, Thru.first, LoMemVT, MOp0,
3553 Masks.second, Thru.second, HiMemVT, MOp1,
3575 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3581 const SDLoc &dl(
Op);
3583 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3584 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3585 "Not widening loads of i1 yet");
3587 SDValue Chain = LoadN->getChain();
3592 unsigned HwLen = Subtarget.getVectorLength();
3594 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3597 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3605 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3613 const SDLoc &dl(
Op);
3615 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3616 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3617 "Not widening stores of i1 yet");
3619 SDValue Chain = StoreN->getChain();
3623 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3624 MVT ValueTy = ty(
Value);
3626 unsigned HwLen = Subtarget.getVectorLength();
3629 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3631 Len = ty(
Value).getVectorNumElements();
3633 assert(ty(
Value).getVectorNumElements() == HwLen);
3635 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3637 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3640 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3647 const SDLoc &dl(
Op);
3648 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3650 unsigned HwLen = Subtarget.getVectorLength();
3655 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3658 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3659 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3663 {WideOp0, WideOp1,
Op.getOperand(2)});
3665 EVT RetTy = typeLegalize(ty(
Op), DAG);
3667 {SetCC, getZero(dl, MVT::i32, DAG)});
3677 const SDLoc &dl(
Op);
3679 MVT InpTy = ty(Inp);
3683 "Expected boolean result type");
3686 unsigned HwLen = Subtarget.getVectorLength();
3691 if (!Subtarget.isHVXVectorType(WideInpTy,
false))
3695 SDValue WideInp = appendUndef(Inp, WideInpTy, DAG);
3702 EVT RetTy = typeLegalize(ResTy, DAG);
3704 {WideTrunc, getZero(dl, MVT::i32, DAG)});
3709 unsigned Opc =
Op.getOpcode();
3710 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3712 return isHvxPairTy(ty(V));
3723 return SplitHvxMemOp(
Op, DAG);
3728 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3729 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3759 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3764 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3765 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3789 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3791 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3812 case HexagonISD::SMUL_LOHI:
3813 case HexagonISD::UMUL_LOHI:
3814 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3819 return LowerHvxPartialReduceMLA(
Op, DAG);
3837 unsigned Opc =
Op.getOpcode();
3839 case HexagonISD::SSAT:
3840 case HexagonISD::USAT:
3857 MVT InpTy = ty(Inp);
3862 assert(InpWidth != ResWidth);
3864 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3867 const SDLoc &dl(
Op);
3871 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3874 case HexagonISD::SSAT:
3875 case HexagonISD::USAT:
3879 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3886 if (InpWidth < ResWidth) {
3888 while (InpWidth * 2 <= ResWidth)
3889 S = repeatOp(InpWidth *= 2, S);
3893 while (InpWidth / 2 >= ResWidth)
3894 S = repeatOp(InpWidth /= 2, S);
3902 MVT InpTy = ty(Inp0);
3906 unsigned Opc =
Op.getOpcode();
3908 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3913 auto [WInpTy, WResTy] =
3914 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3915 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3916 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3924 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3925 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3926 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3933 SDValue T = ExpandHvxResizeIntoSteps(
Op, DAG);
3936 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3939 return RemoveTLWrapper(
Op, DAG);
3945HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3947 unsigned Opc =
N->getOpcode();
3950 if (
N->getNumOperands() > 0)
3951 Inp0 =
Op.getOperand(0);
3957 if (Subtarget.isHVXElementType(ty(
Op)) &&
3958 Subtarget.isHVXElementType(ty(Inp0))) {
3959 Results.push_back(CreateTLWrapper(
Op, DAG));
3971 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
3972 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
3974 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
3975 Subtarget.isHVXElementType(ty(Inp0))) {
3976 Results.push_back(CreateTLWrapper(
Op, DAG));
3980 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3993 if (isHvxPairTy(ty(
Op))) {
4001 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
4010 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4011 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4015 case HexagonISD::SSAT:
4016 case HexagonISD::USAT:
4019 Results.push_back(LegalizeHvxResize(
Op, DAG));
4027HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
4029 unsigned Opc =
N->getOpcode();
4032 if (
N->getNumOperands() > 0)
4033 Inp0 =
Op.getOperand(0);
4039 if (Subtarget.isHVXElementType(ty(
Op)) &&
4040 Subtarget.isHVXElementType(ty(Inp0))) {
4041 Results.push_back(CreateTLWrapper(
Op, DAG));
4048 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4049 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
4051 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4052 Subtarget.isHVXElementType(ty(Inp0))) {
4053 Results.push_back(CreateTLWrapper(
Op, DAG));
4057 if (shouldWidenToHvx(ty(
Op), DAG)) {
4063 if (shouldWidenToHvx(ty(
Op), DAG)) {
4072 if (isHvxBoolTy(ty(Inp0))) {
4079 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4080 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4084 case HexagonISD::SSAT:
4085 case HexagonISD::USAT:
4088 Results.push_back(LegalizeHvxResize(
Op, DAG));
4096HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
4097 DAGCombinerInfo &DCI)
const {
4102 SelectionDAG &DAG = DCI.DAG;
4103 const SDLoc &dl(
Op);
4110 EVT TruncTy =
Op.getValueType();
4112 EVT SrcTy = Src.getValueType();
4119 if (2 * CastLen != SrcLen)
4122 SmallVector<int, 128>
Mask(SrcLen);
4123 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
4125 Mask[i + CastLen] = 2 * i + 1;
4129 return opSplit(Deal, dl, DAG).first;
4133HexagonTargetLowering::combineConcatOfShuffles(
SDValue Op,
4142 const SDLoc &dl(
Op);
4151 SetVector<SDValue> Order;
4157 if (Order.
size() > 2)
4166 SmallVector<int, 128> LongMask;
4167 auto AppendToMask = [&](
SDValue Shuffle) {
4169 ArrayRef<int>
Mask = SV->getMask();
4172 for (
int M : Mask) {
4177 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
4178 if (
static_cast<unsigned>(M) >= InpLen)
4181 int OutOffset = Order[0] == Src ? 0 : InpLen;
4204HexagonTargetLowering::combineConcatOfScalarPreds(
SDValue Op,
unsigned BitBytes,
4206 const SDLoc &dl(
Op);
4209 MVT InpTy = ty(
Ops[0]);
4212 assert(InpLen <= 8 &&
"Too long for scalar predicate");
4213 assert(ResLen > 8 &&
"Too short for HVX vector predicate");
4215 unsigned Bytes = 8 / InpLen;
4218 if (Bytes <= BitBytes)
4222 unsigned SliceLen = Bytes / BitBytes;
4227 for (
unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4229 Inputs.slice(SliceLen * i, SliceLen));
4236SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4237 SDValue Op, DAGCombinerInfo &DCI)
const {
4241 if (ElemTy != MVT::i1) {
4242 return combineConcatOfShuffles(
Op, DCI.DAG);
4249SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4250 unsigned Opcode,
EVT AccEltType,
unsigned AccNumElements,
EVT InputType,
4253 const auto &Subtarget = DAG.
getSubtarget<HexagonSubtarget>();
4254 if (!Subtarget.useHVXOps())
4260 unsigned NativeRatio;
4261 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4273 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4274 if (RemainingReductionRatio == 1)
4279 InputNumElements / NativeRatio);
4282 return DAG.
getNode(Opcode,
DL, IntermediateType, Zero,
A,
B);
4288 EVT AccType =
Mul.getValueType();
4294 A =
Mul->getOperand(0);
4295 B =
Mul->getOperand(1);
4315 A =
A->getOperand(0);
4316 B =
B->getOperand(0);
4317 if (
A.getValueType() !=
B.getValueType())
4328 if (!Subtarget.useHVXOps())
4331 EVT ScalarType =
N->getValueType(0);
4338 unsigned RemainingReductionRatio;
4340 createExtendingPartialReduceMLA(Opcode, ScalarType, 1,
A.getValueType(),
4341 A,
B, RemainingReductionRatio,
DL, DAG);
4358HexagonTargetLowering::splitExtendingPartialReduceMLA(
SDNode *
N,
4360 if (!Subtarget.useHVXOps())
4366 if (
A.getValueType() !=
B.getValueType())
4372 EVT InputType =
A.getValueType();
4377 unsigned RemainingReductionRatio;
4378 SDValue Partial = createExtendingPartialReduceMLA(
4392 DL, AccType, Acc, Partial, One);
4396HexagonTargetLowering::LowerHvxPartialReduceMLA(
SDValue Op,
4398 const SDLoc &
DL(
Op);
4404 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4408 unsigned AccSubvectorNumElements =
4410 EVT AccSubvectorType =
4413 EVT InputType =
A.getValueType();
4416 unsigned InputSubvectorNumElements =
4419 InputSubvectorNumElements);
4424 for (
unsigned I = 0;
I != SubvectorNum; ++
I) {
4426 I * AccSubvectorNumElements);
4428 I * InputSubvectorNumElements);
4430 I * InputSubvectorNumElements);
4432 SubvectorAcc, SubvectorA, SubvectorB);
4440HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
4443 SelectionDAG &DAG = DCI.DAG;
4445 unsigned Opc =
Op.getOpcode();
4450 return combineTruncateBeforeLegal(
Op, DCI);
4452 return combineConcatVectorsBeforeLegal(
Op, DCI);
4454 if (DCI.isBeforeLegalizeOps())
4461 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
4462 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
4470 return getZero(dl, ty(
Op), DAG);
4472 case HexagonISD::VINSERTW0:
4473 if (isUndef(
Ops[1]))
4491HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4492 if (Subtarget.isHVXVectorType(Ty,
true))
4494 auto Action = getPreferredHvxVectorAction(Ty);
4496 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4501HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4502 if (Subtarget.isHVXVectorType(Ty,
true))
4504 auto Action = getPreferredHvxVectorAction(Ty);
4506 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4512 if (!Subtarget.useHVXOps())
4516 auto IsHvxTy = [
this](EVT Ty) {
4517 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4520 return Op.getValueType().isSimple() &&
4521 Subtarget.isHVXVectorType(ty(
Op),
true);
4527 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
4528 if (!
Op.getValueType().isSimple())
4531 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4534 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)
static Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
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),...
size_t size() const
Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
static 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)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
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.
@ 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.
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.
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