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 };
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) {
194 if (!Subtarget.useHVXV81Ops())
198 if (Subtarget.useHVXV81Ops()) {
201 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
202 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
203 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
204 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
229 for (MVT
P : FloatW) {
259 if (Subtarget.useHVXQFloatOps()) {
262 }
else if (Subtarget.useHVXIEEEFPOps()) {
268 for (MVT
T : LegalV) {
295 if (
T.getScalarType() != MVT::i32) {
304 if (
T.getScalarType() != MVT::i32) {
332 if (Subtarget.useHVXFloatingPoint()) {
349 for (MVT
T : LegalW) {
404 if (
T.getScalarType() != MVT::i32) {
409 if (Subtarget.useHVXFloatingPoint()) {
456 for (MVT
T : LegalW) {
473 for (MVT
T : LegalV) {
488 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
491 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
496 unsigned HwLen = Subtarget.getVectorLength();
497 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
498 if (ElemTy == MVT::i1)
500 int ElemWidth = ElemTy.getFixedSizeInBits();
501 int MaxElems = (8*HwLen) / ElemWidth;
502 for (
int N = 2;
N < MaxElems;
N *= 2) {
513 if (Subtarget.useHVXFloatingPoint()) {
543 auto HvxType = [=](MVT ScalarT,
unsigned Factor = 1) {
552 typedef std::tuple<MVT, MVT, bool> ReductionSignature;
554 static const std::vector<ReductionSignature> NativeReductions = {
555 {MVT::i32, MVT::i8,
false},
558 for (
const auto &R : NativeReductions) {
560 MVT AccType = std::get<0>(R);
561 MVT InputType = std::get<1>(R);
562 unsigned Factor = std::get<2>(R) ? 2 : 1;
584 for (
unsigned ConcatFactor = 1; ConcatFactor <=
MaxExpandMLA;
586 for (
unsigned ReductionFactor = 1; ReductionFactor <=
MaxExpandMLA;
587 ReductionFactor <<= 1)
588 if (ConcatFactor * ReductionFactor != 1 &&
591 MLAOps, HvxType(AccType, Factor * ConcatFactor),
592 HvxType(InputType, Factor * ConcatFactor * ReductionFactor),
599HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
606 unsigned HwLen = Subtarget.getVectorLength();
609 if (ElemTy == MVT::i1 && VecLen > HwLen)
615 if (ElemTy == MVT::i1) {
630 unsigned HwWidth = 8*HwLen;
631 if (VecWidth > 2*HwWidth)
637 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
646HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
647 unsigned Opc =
Op.getOpcode();
649 case HexagonISD::SMUL_LOHI:
650 case HexagonISD::UMUL_LOHI:
651 case HexagonISD::USMUL_LOHI:
667HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
668 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
672 Tys.second.getVectorNumElements());
675HexagonTargetLowering::TypePair
676HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
679 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
681 return { HalfTy, HalfTy };
685HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
692HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
699HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
708HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
714HexagonTargetLowering::VectorPair
715HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
717 TypePair Tys = typeSplit(ty(Vec));
720 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
724HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
725 return Subtarget.isHVXVectorType(Ty) &&
730HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
731 return Subtarget.isHVXVectorType(Ty) &&
736HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
737 return Subtarget.isHVXVectorType(Ty,
true) &&
741bool HexagonTargetLowering::allowsHvxMemoryAccess(
749 if (!Subtarget.isHVXVectorType(VecTy,
false))
756bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
758 if (!Subtarget.isHVXVectorType(VecTy))
766void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
768 unsigned Opc =
MI.getOpcode();
769 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
770 MachineBasicBlock &MB = *
MI.getParent();
777 case Hexagon::PS_vsplatib:
778 if (Subtarget.useHVXV62Ops()) {
783 .
add(
MI.getOperand(1));
785 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
791 const MachineOperand &InpOp =
MI.getOperand(1);
793 uint32_t
V = InpOp.
getImm() & 0xFF;
795 .
addImm(V << 24 | V << 16 | V << 8 | V);
801 case Hexagon::PS_vsplatrb:
802 if (Subtarget.useHVXV62Ops()) {
805 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
806 .
add(
MI.getOperand(1));
809 const MachineOperand &InpOp =
MI.getOperand(1);
810 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
813 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
818 case Hexagon::PS_vsplatih:
819 if (Subtarget.useHVXV62Ops()) {
824 .
add(
MI.getOperand(1));
826 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
832 const MachineOperand &InpOp =
MI.getOperand(1);
834 uint32_t
V = InpOp.
getImm() & 0xFFFF;
842 case Hexagon::PS_vsplatrh:
843 if (Subtarget.useHVXV62Ops()) {
846 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
847 .
add(
MI.getOperand(1));
852 const MachineOperand &InpOp =
MI.getOperand(1);
853 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
861 case Hexagon::PS_vsplatiw:
862 case Hexagon::PS_vsplatrw:
863 if (
Opc == Hexagon::PS_vsplatiw) {
867 .
add(
MI.getOperand(1));
868 MI.getOperand(1).ChangeToRegister(SplatV,
false);
871 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
877HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
887 const SDLoc &dl(ElemIdx);
893HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
896 assert(ElemWidth >= 8 && ElemWidth <= 32);
900 if (ty(Idx) != MVT::i32)
902 const SDLoc &dl(Idx);
909HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
916 if (ElemTy == MVT::i8)
920 MVT ResTy = tyVector(OpTy, MVT::i8);
923 SmallVector<int,128> ByteMask;
926 for (
unsigned I = 0;
I != ElemSize; ++
I)
929 int NewM =
M*ElemSize;
930 for (
unsigned I = 0;
I != ElemSize; ++
I)
936 opCastElem(Op1, MVT::i8, DAG), ByteMask);
943 unsigned VecLen =
Values.size();
947 unsigned HwLen = Subtarget.getVectorLength();
949 unsigned ElemSize = ElemWidth / 8;
950 assert(ElemSize*VecLen == HwLen);
954 !(Subtarget.useHVXFloatingPoint() &&
956 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
957 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
959 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
960 SDValue
W = buildVector32(
Values.slice(i, OpsPerWord), dl, PartVT, DAG);
968 unsigned NumValues =
Values.size();
971 for (
unsigned i = 0; i != NumValues; ++i) {
975 if (!SplatV.getNode())
977 else if (SplatV !=
Values[i])
985 unsigned NumWords = Words.
size();
987 bool IsSplat =
isSplat(Words, SplatV);
988 if (IsSplat && isUndef(SplatV))
993 return getZero(dl, VecTy, DAG);
1002 bool AllConst = getBuildVectorConstInts(
Values, VecTy, DAG, Consts);
1005 (Constant**)Consts.end());
1022 auto IsBuildFromExtracts = [
this,&
Values] (SDValue &SrcVec,
1023 SmallVectorImpl<int> &SrcIdx) {
1025 for (SDValue V :
Values) {
1027 SrcIdx.push_back(-1);
1033 SDValue
T =
V.getOperand(0);
1040 int I =
C->getSExtValue();
1041 assert(
I >= 0 &&
"Negative element index");
1042 SrcIdx.push_back(
I);
1048 SmallVector<int,128> ExtIdx;
1050 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
1051 MVT ExtTy = ty(ExtVec);
1053 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
1057 SmallVector<int,128>
Mask;
1058 BitVector
Used(ExtLen);
1060 for (
int M : ExtIdx) {
1070 for (
unsigned I = 0;
I != ExtLen; ++
I) {
1071 if (
Mask.size() == ExtLen)
1079 return ExtLen == VecLen ? S : LoHalf(S, DAG);
1087 assert(4*Words.
size() == Subtarget.getVectorLength());
1090 for (
unsigned i = 0; i != NumWords; ++i) {
1092 if (Words[i].isUndef())
1094 for (
unsigned j = i;
j != NumWords; ++
j)
1095 if (Words[i] == Words[j])
1098 if (VecHist[i] > VecHist[n])
1102 SDValue HalfV = getZero(dl, VecTy, DAG);
1103 if (VecHist[n] > 1) {
1110 SDValue SplatV = DAG.
getBitcast(VecTy, WordSplat);
1111 HalfV = DAG.
getNode(HexagonISD::VALIGN, dl, VecTy,
1112 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1114 SDValue HalfV0 = HalfV;
1115 SDValue HalfV1 = HalfV;
1124 for (
unsigned i = 0; i != NumWords/2; ++i) {
1126 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1129 N = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1130 {HalfV0, Words[i]});
1133 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1136 M = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1137 {HalfV1, Words[i+NumWords/2]});
1149 SDValue T0 = DAG.
getBitcast(tyVector(VecTy, MVT::i32), HalfV0);
1150 SDValue
T1 = DAG.
getBitcast(tyVector(VecTy, MVT::i32), HalfV1);
1160HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1161 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1162 MVT PredTy = ty(PredV);
1163 unsigned HwLen = Subtarget.getVectorLength();
1166 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1176 SmallVector<int,128>
Mask(HwLen);
1181 for (
unsigned i = 0; i != HwLen; ++i) {
1182 unsigned Num = i % Scale;
1183 unsigned Off = i / Scale;
1192 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1194 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1201 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1207 SDValue W0 = isUndef(PredV)
1213 while (Bytes < BitBytes) {
1215 Words[IdxW].
clear();
1218 for (
const SDValue &W : Words[IdxW ^ 1]) {
1219 SDValue
T = expandPredicate(W, dl, DAG);
1224 for (
const SDValue &W : Words[IdxW ^ 1]) {
1232 assert(Bytes == BitBytes);
1233 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1234 SDValue S4 = DAG.
getConstant(HwLen-4, dl, MVT::i32);
1235 for (
const SDValue &W : Words[IdxW]) {
1237 Vec = DAG.
getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1249 unsigned VecLen =
Values.size();
1250 unsigned HwLen = Subtarget.getVectorLength();
1251 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1253 bool AllT =
true, AllF =
true;
1255 auto IsTrue = [] (SDValue
V) {
1257 return !
N->isZero();
1260 auto IsFalse = [] (SDValue
V) {
1266 if (VecLen <= HwLen) {
1270 assert(HwLen % VecLen == 0);
1271 unsigned BitBytes = HwLen / VecLen;
1272 for (SDValue V :
Values) {
1278 for (
unsigned B = 0;
B != BitBytes; ++
B)
1285 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1288 for (;
B != 8; ++
B) {
1307 return DAG.
getNode(HexagonISD::QTRUE, dl, VecTy);
1309 return DAG.
getNode(HexagonISD::QFALSE, dl, VecTy);
1312 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1317HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1322 assert(ElemWidth >= 8 && ElemWidth <= 32);
1325 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1326 SDValue ExWord = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1328 if (ElemTy == MVT::i32)
1334 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1336 SDValue ExVec = DAG.
getBitcast(tyVector(ty(ExWord), ElemTy), ExWord);
1337 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1341HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1344 assert(ResTy == MVT::i1);
1346 unsigned HwLen = Subtarget.getVectorLength();
1350 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1351 SDValue ScV = DAG.
getConstant(Scale, dl, MVT::i32);
1354 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1356 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1360HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1365 assert(ElemWidth >= 8 && ElemWidth <= 32);
1368 auto InsertWord = [&DAG,&dl,
this] (SDValue VecV, SDValue ValV,
1370 MVT VecTy = ty(VecV);
1371 unsigned HwLen = Subtarget.getVectorLength();
1376 SDValue InsV = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1383 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1384 if (ElemTy == MVT::i32)
1385 return InsertWord(VecV, ValV, ByteIdx);
1391 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1396 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1397 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1398 SDValue Ins = insertVector(DAG.
getBitcast(SubVecTy, Ext),
1399 ValV, SubIdx, dl, ElemTy, DAG);
1402 return InsertWord(VecV, Ins, ByteIdx);
1406HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1408 unsigned HwLen = Subtarget.getVectorLength();
1412 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1413 SDValue ScV = DAG.
getConstant(Scale, dl, MVT::i32);
1417 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1422HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1424 MVT VecTy = ty(VecV);
1425 unsigned HwLen = Subtarget.getVectorLength();
1433 if (isHvxPairTy(VecTy)) {
1434 unsigned SubIdx = Hexagon::vsub_lo;
1435 if (Idx * ElemWidth >= 8 * HwLen) {
1436 SubIdx = Hexagon::vsub_hi;
1440 VecTy = typeSplit(VecTy).first;
1450 MVT WordTy = tyVector(VecTy, MVT::i32);
1451 SDValue WordVec = DAG.
getBitcast(WordTy, VecV);
1452 unsigned WordIdx = (Idx*ElemWidth) / 32;
1454 SDValue W0Idx = DAG.
getConstant(WordIdx, dl, MVT::i32);
1455 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1459 SDValue W1Idx = DAG.
getConstant(WordIdx+1, dl, MVT::i32);
1460 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1461 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1466HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1468 MVT VecTy = ty(VecV);
1469 unsigned HwLen = Subtarget.getVectorLength();
1477 unsigned Offset = Idx * BitBytes;
1479 SmallVector<int,128>
Mask;
1481 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1488 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1489 for (
unsigned j = 0;
j != Rep; ++
j)
1506 unsigned Rep = 8 / ResLen;
1509 for (
unsigned r = 0; r != HwLen / 8; ++r) {
1511 for (
unsigned i = 0; i != ResLen; ++i) {
1512 for (
unsigned j = 0;
j != Rep; ++
j)
1517 SDValue
Zero = getZero(dl, MVT::i32, DAG);
1521 SDValue W0 = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32, {ShuffV,
Zero});
1522 SDValue W1 = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1524 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1525 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1530HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1532 MVT VecTy = ty(VecV);
1533 MVT SubTy = ty(SubV);
1534 unsigned HwLen = Subtarget.getVectorLength();
1538 bool IsPair = isHvxPairTy(VecTy);
1542 SDValue SingleV = VecV;
1546 V0 = LoHalf(VecV, DAG);
1547 V1 = HiHalf(VecV, DAG);
1552 if (isHvxSingleTy(SubTy)) {
1554 unsigned Idx = CN->getZExtValue();
1556 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1579 if (!IdxN || !IdxN->isZero()) {
1587 unsigned RolBase = HwLen;
1590 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1593 SDValue R0 = LoHalf(V, DAG);
1594 SDValue R1 = HiHalf(V, DAG);
1595 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1598 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1602 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1617HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1619 MVT VecTy = ty(VecV);
1620 MVT SubTy = ty(SubV);
1621 assert(Subtarget.isHVXVectorType(VecTy,
true));
1626 unsigned HwLen = Subtarget.getVectorLength();
1627 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1630 unsigned BitBytes = HwLen / VecLen;
1631 unsigned BlockLen = HwLen / Scale;
1635 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1639 if (!IdxN || !IdxN->isZero()) {
1648 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1650 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1652 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1654 if (!IdxN || !IdxN->isZero()) {
1655 SDValue HwLenV = DAG.
getConstant(HwLen, dl, MVT::i32);
1656 SDValue ByteXdi = DAG.
getNode(
ISD::SUB, dl, MVT::i32, HwLenV, ByteIdx);
1663HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1668 assert(Subtarget.isHVXVectorType(ResTy));
1675 SDValue False = getZero(dl, ResTy, DAG);
1676 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1680HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1688 unsigned HwLen = Subtarget.getVectorLength();
1690 MVT PredTy = ty(VecQ);
1692 assert(HwLen % PredLen == 0);
1699 for (
unsigned i = 0; i != HwLen/8; ++i) {
1700 for (
unsigned j = 0;
j != 8; ++
j)
1701 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1714 getZero(dl, VecTy, DAG));
1720 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1722 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1729 SmallVector<int,128>
Mask;
1730 for (
unsigned i = 0; i != HwLen; ++i)
1731 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1741 MVT InpTy = ty(VecV);
1749 return InpWidth < ResWidth
1757 if (InpWidth < ResWidth) {
1759 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1761 unsigned NarOpc =
Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1767HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1771 const SDLoc &dl(Vec);
1780 const SDLoc &dl(
Op);
1785 for (
unsigned i = 0; i !=
Size; ++i)
1786 Ops.push_back(
Op.getOperand(i));
1789 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1797 for (
unsigned i = 0; i !=
Size; i++)
1808 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1810 MVT SingleTy = typeSplit(VecTy).first;
1811 SDValue
V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1812 SDValue
V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1816 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1822 const SDLoc &dl(
Op);
1824 MVT ArgTy = ty(
Op.getOperand(0));
1826 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1828 SDValue ToInt16 = DAG.
getBitcast(MVT::i16,
Op.getOperand(0));
1844 const SDLoc &dl(
Op);
1851 for (SDValue V :
Op.getNode()->ops())
1858 for (SDValue &V : Elems) {
1861 MVT NTy = typeLegalize(Ty, DAG);
1865 V.getOperand(0),
V.getOperand(1)),
1870 switch (
V.getOpcode()) {
1878 V =
V.getOperand(0);
1889 unsigned HwLen = Subtarget.getVectorLength();
1892 SDValue Op0 =
Op.getOperand(0);
1896 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1898 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, Op0,
Op.getOperand(1));
1904 MVT HalfTy = typeSplit(VecTy).first;
1906 Ops.take_front(NumOp/2));
1908 Ops.take_back(NumOp/2));
1909 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, V0,
V1);
1919 SDValue Combined = combineConcatOfScalarPreds(
Op, BitBytes, DAG);
1922 SDValue
P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1926 unsigned InpLen = ty(Combined.
getOperand(0)).getVectorNumElements();
1928 SDValue S = DAG.
getConstant(HwLen - InpLen*BitBytes, dl, MVT::i32);
1929 SDValue Res = getZero(dl, ByteTy, DAG);
1930 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1941 SDValue VecV =
Op.getOperand(0);
1943 const SDLoc &dl(
Op);
1944 SDValue IdxV =
Op.getOperand(1);
1945 if (ElemTy == MVT::i1)
1946 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1948 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1954 const SDLoc &dl(
Op);
1955 SDValue VecV =
Op.getOperand(0);
1956 SDValue ValV =
Op.getOperand(1);
1957 SDValue IdxV =
Op.getOperand(2);
1959 if (ElemTy == MVT::i1)
1960 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1962 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1968 SDValue SrcV =
Op.getOperand(0);
1969 MVT SrcTy = ty(SrcV);
1971 SDValue IdxV =
Op.getOperand(1);
1975 const SDLoc &dl(
Op);
1978 if (ElemTy == MVT::i1)
1979 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1981 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1988 SDValue VecV =
Op.getOperand(0);
1989 SDValue ValV =
Op.getOperand(1);
1990 SDValue IdxV =
Op.getOperand(2);
1992 const SDLoc &dl(
Op);
1993 MVT VecTy = ty(VecV);
1995 if (ElemTy == MVT::i1)
1996 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1998 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
2008 SDValue InpV =
Op.getOperand(0);
2010 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2011 return LowerHvxSignExt(
Op, DAG);
2018 SDValue InpV =
Op.getOperand(0);
2020 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2021 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
2028 SDValue InpV =
Op.getOperand(0);
2030 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2031 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
2039 const SDLoc &dl(
Op);
2041 SDValue InpV =
Op.getOperand(0);
2042 assert(ResTy == ty(InpV));
2067 const SDLoc &dl(
Op);
2071 SDValue Vs =
Op.getOperand(0);
2072 SDValue Vt =
Op.getOperand(1);
2074 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2075 unsigned Opc =
Op.getOpcode();
2079 return DAG.
getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2081 return DAG.
getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2091 const SDLoc &dl(
Op);
2092 unsigned Opc =
Op.getOpcode();
2093 SDValue Vu =
Op.getOperand(0);
2094 SDValue Vv =
Op.getOperand(1);
2097 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2104 bool SignedVu =
Opc == HexagonISD::SMUL_LOHI;
2105 bool SignedVv =
Opc == HexagonISD::SMUL_LOHI ||
Opc == HexagonISD::USMUL_LOHI;
2109 if (Subtarget.useHVXV62Ops())
2110 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2112 if (
Opc == HexagonISD::SMUL_LOHI) {
2115 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2116 SDValue
Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2122 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2127 SDValue Val =
Op.getOperand(0);
2129 MVT ValTy = ty(Val);
2130 const SDLoc &dl(
Op);
2133 unsigned HwLen = Subtarget.getVectorLength();
2141 if (PredLen < HwLen) {
2144 if (HwLen > PredLen * 2) {
2145 assert(HwLen == PredLen * 4);
2147 Val = getInstr(Hexagon::V6_vdealh, dl, ByteTy, Val, DAG);
2149 if (HwLen > PredLen) {
2150 assert(HwLen == PredLen * 2);
2151 Val = getInstr(Hexagon::V6_vdealb, dl, ByteTy, Val, DAG);
2156 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2160 SDValue W0 = extractHvxElementReg(VQ, DAG.
getConstant(0, dl, MVT::i32),
2171 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2172 SDValue
W = extractHvxElementReg(
2173 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2178 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2179 SDValue
C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2192 auto bitcastI32ToV32I1 = [&](SDValue Val32) {
2193 assert(Val32.getValueType().getSizeInBits() == 32 &&
2194 "Input must be 32 bits");
2198 for (
unsigned i = 0; i < 32; ++i)
2206 if (ResTy == MVT::v32i1 &&
2207 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2208 Subtarget.useHVX128BOps()) {
2209 SDValue Val32 = Val;
2210 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2212 return bitcastI32ToV32I1(Val32);
2215 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2223 SDValue LoRes = bitcastI32ToV32I1(
Lo);
2224 SDValue HiRes = bitcastI32ToV32I1(
Hi);
2233 unsigned HwLen = Subtarget.getVectorLength();
2237 SDValue ValAsVec = DAG.
getBitcast(ValAsVecTy, Val);
2245 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2249 for (
unsigned J = 0; J != 8; ++J) {
2256 SDValue ConstantVec = DAG.
getBuildVector(ConstantVecTy, dl, Tmp);
2257 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2269 const SDLoc &dl(
Op);
2272 MVT ValTy = ty(Val);
2275 if (!isHvxBoolTy(ValTy))
2282 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2286 unsigned HwLen = Subtarget.getVectorLength();
2290 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2294 for (
unsigned i = 0; i != NumBits / 32; ++i) {
2295 SDValue
W = extractHvxElementReg(VQ, DAG.
getConstant(i, dl, MVT::i32), dl,
2305 return DAG.
getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2308 if (NumBits == 64) {
2309 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2313 if (NumBits == 128) {
2314 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2315 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2320 SDValue Offset8 = DAG.
getConstant(8, dl, MVT::i32);
2331 const SDLoc &dl(
Op);
2336 if (!isHvxBoolTy(ResTy))
2342 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2350 if (NumBits == 32) {
2358 if (NumBits == 64) {
2366 if (NumBits == 128) {
2371 SDValue Offset8 = DAG.
getConstant(8, dl, MVT::i32);
2373 SDValue Hi64 = DAG.
getLoad(MVT::i64, dl, Chain, Ptr8,
2402 const SDLoc &dl(
Op);
2403 unsigned HwLen = Subtarget.getVectorLength();
2405 assert(HwLen % VecLen == 0);
2406 unsigned ElemSize = HwLen / VecLen;
2418 if (SDValue S = getVectorShiftByInt(
Op, DAG))
2424HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2426 unsigned Opc =
Op.getOpcode();
2431 SDValue
A =
Op.getOperand(0);
2432 SDValue
B =
Op.getOperand(1);
2433 SDValue S =
Op.getOperand(2);
2438 const SDLoc &dl(
Op);
2444 bool UseShifts = ElemTy != MVT::i8;
2445 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2448 if (SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2456 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2462 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2464 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2472 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2474 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2481 const SDLoc &dl(
Op);
2482 unsigned IntNo =
Op.getConstantOperandVal(0);
2485 auto Swap = [&](SDValue
P) {
2490 case Intrinsic::hexagon_V6_pred_typecast:
2491 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2492 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2493 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2500 case Intrinsic::hexagon_V6_vmpyss_parts:
2501 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2502 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2504 case Intrinsic::hexagon_V6_vmpyuu_parts:
2505 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2506 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2508 case Intrinsic::hexagon_V6_vmpyus_parts:
2509 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2510 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2520 const SDLoc &dl(
Op);
2521 unsigned HwLen = Subtarget.getVectorLength();
2524 SDValue
Mask = MaskN->getMask();
2525 SDValue Chain = MaskN->getChain();
2526 SDValue
Base = MaskN->getBasePtr();
2529 unsigned Opc =
Op->getOpcode();
2546 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2550 if (MaskN->getAlign().value() % HwLen == 0) {
2551 SDValue
Store = getInstr(StoreOpc, dl, MVT::Other,
2558 auto StoreAlign = [&](SDValue
V, SDValue
A) {
2559 SDValue
Z = getZero(dl, ty(V), DAG);
2563 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2564 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2565 return std::make_pair(LoV, HiV);
2571 VectorPair Tmp = StoreAlign(MaskV,
Base);
2574 VectorPair ValueU = StoreAlign(
Value,
Base);
2578 getInstr(StoreOpc, dl, MVT::Other,
2579 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2590 uint64_t StoreMemSize = MaskN->getMemoryVT().getStoreSize().getFixedValue();
2591 if (StoreMemSize <= MaskN->
getAlign().value())
2595 getInstr(StoreOpc, dl, MVT::Other,
2596 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2605 assert(Subtarget.useHVXQFloatOps());
2610 MVT ArgTy = ty(
Op.getOperand(0));
2611 const SDLoc &dl(
Op);
2613 if (ArgTy == MVT::v64bf16) {
2614 MVT HalfTy = typeSplit(VecTy).first;
2615 SDValue BF16Vec =
Op.getOperand(0);
2617 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2622 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2623 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2624 SDValue
Result = getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2625 {VecPair.second, VecPair.first,
2631 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2633 SDValue F16Vec =
Op.getOperand(0);
2640 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2642 MVT HalfTy = typeSplit(VecTy).first;
2643 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2645 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2647 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2650 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2663 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2666 if (Subtarget.useHVXIEEEFPOps()) {
2668 if (FpTy == MVT::f16) {
2670 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2672 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2678 return EqualizeFpIntConversion(
Op, DAG);
2680 return ExpandHvxFpToInt(
Op, DAG);
2696 MVT ResTy = ty(PredOp);
2697 const SDLoc &dl(PredOp);
2700 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2701 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2702 SDValue(RegConst, 0));
2703 SDNode *PredTransfer =
2705 SDValue(SplatConst, 0), SDValue(RegConst, 0));
2706 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2707 SDValue(PredTransfer, 0));
2709 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2713 SDValue(PrefixSum, 0), SDValue(SplatConst, 0));
2714 SDNode *IndexShift =
2716 SDValue(SplatParam, 0), SDValue(Vsub, 0));
2719 SDValue(IndexShift, 0), SDValue(SplatConst, 0));
2720 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2721 SDValue(MaskOff, 0));
2722 return SDValue(Convert, 0);
2745 MVT ResTy = ty(PredOp);
2746 const SDLoc &dl(PredOp);
2756 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2757 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2758 SDValue(RegConst, 0));
2767 SDNode *PredTransfer =
2769 SDValue(SplatConst, 0), SDValue(RegConst, 0));
2771 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2772 SDValue(PredTransfer, 0));
2776 SDValue(PrefixSum, 0), SDValue(SplatConst, 0));
2778 SDNode *IndexShift_hi =
2780 SDValue(SplatHi, 0), SDValue(Vsub, 0));
2781 SDNode *IndexShift_lo =
2783 SDValue(SplatLo, 0), SDValue(Vsub, 0));
2785 SDNode *MaskOff_hi =
2787 SDValue(IndexShift_hi, 0), SDValue(SplatConst, 0));
2788 SDNode *MaskOff_lo =
2790 SDValue(IndexShift_lo, 0), SDValue(SplatConst, 0));
2794 SDValue(MaskOff_hi, 0), SDValue(MaskOff_lo, 0));
2796 DAG.
getMachineNode(Hexagon::V6_vconv_hf_h, dl, ResTy, SDValue(Pack, 0));
2797 return SDValue(Convert, 0);
2811 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2812 return LowerHvxPred32ToFp(
Op, DAG);
2813 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2814 return LowerHvxPred64ToFp(
Op, DAG);
2817 if (Subtarget.useHVXIEEEFPOps()) {
2819 if (FpTy == MVT::f16) {
2821 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2823 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2829 return EqualizeFpIntConversion(
Op, DAG);
2831 return ExpandHvxIntToFp(
Op, DAG);
2834HexagonTargetLowering::TypePair
2835HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2846 unsigned MaxWidth = std::max(Width0, Width1);
2848 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2855 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2856 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2860 return {WideETy0, WideETy1};
2871HexagonTargetLowering::TypePair
2872HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2882 unsigned MaxLen = std::max(Len0, Len1);
2895HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2896 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2905HexagonTargetLowering::VectorPair
2936HexagonTargetLowering::VectorPair
2937HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2942 const SDLoc &dl(Val);
2943 MVT ValTy = ty(Val);
2957 MVT IntTy = tyVector(ValTy, ElemTy);
2962 SDValue LowBits = DAG.
getConstant((1ull << (Amt - 1)) - 1, dl, IntTy);
2964 SDValue AmtP1 = DAG.
getConstant(1ull << Amt, dl, IntTy);
2966 SDValue
Zero = getZero(dl, IntTy, DAG);
2969 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2971 SDValue AmtM1 = DAG.
getConstant(Amt - 1, dl, IntTy);
2972 SDValue Tmp1 = DAG.
getNode(ShRight, dl, IntTy, Inp, AmtM1);
2973 SDValue Tmp2 = DAG.
getNode(ShRight, dl, IntTy, Tmp0, AmtM1);
2978 SDValue Tmp4 = DAG.
getNode(ShRight, dl, IntTy, {Tmp2, One});
2979 SDValue Tmp5 = DAG.
getNode(ShRight, dl, IntTy, {Tmp3, One});
2988 MVT
PairTy = typeJoin({VecTy, VecTy});
3014 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
3016 SDValue
T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
3018 SDValue
P0 = getInstr(Hexagon::V6_vmpyhus, dl,
PairTy, {
T1,
B}, DAG);
3020 SDValue T2 = LoHalf(P0, DAG);
3024 SDValue
P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
3026 SDValue
P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
3029 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3030 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
3031 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
3034 SDValue
P3 = getInstr(Hexagon::V6_vmpyhv, dl,
PairTy, {
T1, T4}, DAG);
3035 SDValue T5 = LoHalf(P3, DAG);
3042HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
3043 bool SignedB,
const SDLoc &dl,
3046 MVT
PairTy = typeJoin({VecTy, VecTy});
3051 if (SignedA && !SignedB) {
3064 SDValue
P0 = getInstr(Hexagon::V6_vmpyuhv, dl,
PairTy, {
A,
B}, DAG);
3067 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3068 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
3069 SDValue
T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
3073 SDValue
P1 = getInstr(Hexagon::V6_vmpyuhv, dl,
PairTy, {
A,
T1}, DAG);
3077 SDValue
P2 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy,
3078 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3081 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
3085 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3086 {HiHalf(P2, DAG), T3,
S16}, DAG);
3089 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3090 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
3094 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
3097 SDValue
Zero = getZero(dl, VecTy, DAG);
3101 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
3102 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
3103 }
else if (SignedB) {
3107 SDValue
Zero = getZero(dl, VecTy, DAG);
3109 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
3111 assert(!SignedA && !SignedB);
3118HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
3123 MVT
PairTy = typeJoin({VecTy, VecTy});
3126 if (SignedA && !SignedB) {
3133 SDValue
P0 = getInstr(Hexagon::V6_vmpyewuh_64, dl,
PairTy, {
A,
B}, DAG);
3135 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
3136 SDValue
Lo = LoHalf(P1, DAG);
3137 SDValue
Hi = HiHalf(P1, DAG);
3140 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
3141 SDValue
Zero = getZero(dl, VecTy, DAG);
3152 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
3153 SDValue
T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
3154 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
3155 }
else if (!SignedA) {
3156 SDValue
Zero = getZero(dl, VecTy, DAG);
3165 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
3183 unsigned Opc =
Op.getOpcode();
3187 SDValue Inp =
Op.getOperand(0);
3188 MVT InpTy = ty(Inp);
3194 const SDLoc &dl(
Op);
3197 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3198 SDValue WInp = resizeToWidth(Inp, WInpTy,
Signed, dl, DAG);
3199 SDValue Conv = DAG.
getNode(
Opc, dl, WResTy, WInp);
3200 SDValue Res = resizeToWidth(Conv, ResTy,
Signed, dl, DAG);
3206 unsigned Opc =
Op.getOpcode();
3209 const SDLoc &dl(
Op);
3210 SDValue Op0 =
Op.getOperand(0);
3211 MVT InpTy = ty(Op0);
3224 if (InpTy == MVT::v64f16) {
3225 if (Subtarget.useHVXV81Ops()) {
3228 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3232 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3237 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3317 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3318 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3321 SDValue
Zero = getZero(dl, ResTy, DAG);
3323 SDValue M80 = DAG.
getConstant(1ull << (ElemWidth - 1), dl, ResTy);
3324 SDValue M7F = DAG.
getConstant((1ull << (ElemWidth - 1)) - 1, dl, ResTy);
3328 SDValue MNE = DAG.
getConstant(ElemWidth - ExpWidth, dl, ResTy);
3331 SDValue ExpW = DAG.
getConstant(ExpWidth, dl, ResTy);
3335 SDValue MN2 = DAG.
getConstant(ElemWidth - 2, dl, ResTy);
3337 SDValue MW = DAG.
getConstant(ElemWidth, dl, ResTy);
3361 unsigned Opc =
Op.getOpcode();
3364 const SDLoc &dl(
Op);
3365 SDValue Op0 =
Op.getOperand(0);
3366 MVT InpTy = ty(Op0);
3399 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3401 SDValue
Zero = getZero(dl, InpTy, DAG);
3409 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3412 SDValue M80 = DAG.
getConstant(1ull << (ElemWidth - 1), dl, InpTy);
3418 SDValue Exp0 = DAG.
getConstant(ElemWidth + ExpBias, dl, InpTy);
3432 unsigned Opc =
Op.getOpcode();
3449 const SDLoc &dl(
Op);
3450 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3459 unsigned Opc =
Op.getConstantOperandVal(2);
3463HexagonTargetLowering::VectorPair
3467 const SDLoc &dl(
Op);
3469 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3470 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3472 return std::make_pair(TV, TV);
3475 for (SDValue
A :
Op.getNode()->ops()) {
3477 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3479 switch (
Op.getOpcode()) {
3480 case ISD::SIGN_EXTEND_INREG:
3481 case HexagonISD::SSAT:
3482 case HexagonISD::USAT:
3483 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3484 std::tie(Lo, Hi) = SplitVTNode(N);
3492 MVT HalfTy = typeSplit(ResTy).first;
3493 SDValue
L = DAG.
getNode(
Op.getOpcode(), dl, HalfTy, OpsL);
3494 SDValue
H = DAG.
getNode(
Op.getOpcode(), dl, HalfTy, OpsH);
3501 unsigned MemOpc = MemN->getOpcode();
3502 EVT MemTy = MemN->getMemoryVT();
3519 EVT LoMemVT, HiMemVT;
3520 bool HiIsEmpty =
false;
3521 std::tie(LoMemVT, HiMemVT) =
3527 const SDLoc &dl(
Op);
3528 SDValue Chain = MemN->getChain();
3529 SDValue Base0 = MemN->getBasePtr();
3533 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3534 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3550 SDValue Load0 = DAG.
getLoad(LoVT, dl, Chain, Base0, MOp0);
3551 SDValue Load1 = DAG.
getLoad(HiVT, dl, Chain, Base1, MOp1);
3562 SDValue Store0 = DAG.
getStore(Chain, dl, Vals.first, Base0, MOp0);
3563 SDValue Store1 = DAG.
getStore(Chain, dl, Vals.second, Base1, MOp1);
3570 assert(MaskN->isUnindexed());
3571 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3578 Masks.first, Thru.first, LoMemVT, MOp0,
3587 Masks.second, Thru.second, HiMemVT, MOp1,
3609 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3615 const SDLoc &dl(
Op);
3617 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3618 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3619 "Not widening loads of i1 yet");
3621 SDValue Chain = LoadN->getChain();
3622 SDValue
Base = LoadN->getBasePtr();
3626 unsigned HwLen = Subtarget.getVectorLength();
3628 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3631 SDValue
Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3639 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3647 const SDLoc &dl(
Op);
3649 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3650 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3651 "Not widening stores of i1 yet");
3653 SDValue Chain = StoreN->getChain();
3654 SDValue
Base = StoreN->getBasePtr();
3657 SDValue
Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3658 MVT ValueTy = ty(
Value);
3660 unsigned HwLen = Subtarget.getVectorLength();
3663 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3665 Len = ty(
Value).getVectorNumElements();
3667 assert(ty(
Value).getVectorNumElements() == HwLen);
3669 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3671 SDValue
Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3674 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3682 const SDLoc &dl(
Op);
3683 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3685 unsigned HwLen = Subtarget.getVectorLength();
3690 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3693 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3694 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3698 {WideOp0, WideOp1,
Op.getOperand(2)});
3700 EVT RetTy = typeLegalize(ty(
Op), DAG);
3702 {SetCC, getZero(dl, MVT::i32, DAG)});
3712 const SDLoc &dl(
Op);
3713 SDValue Inp =
Op.getOperand(0);
3714 MVT InpTy = ty(Inp);
3718 "Expected boolean result type");
3721 unsigned HwLen = Subtarget.getVectorLength();
3726 if (!Subtarget.isHVXVectorType(WideInpTy,
false))
3730 SDValue WideInp = appendUndef(Inp, WideInpTy, DAG);
3737 EVT RetTy = typeLegalize(ResTy, DAG);
3739 {WideTrunc, getZero(dl, MVT::i32, DAG)});
3744 unsigned Opc =
Op.getOpcode();
3745 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3747 return isHvxPairTy(ty(V));
3758 return SplitHvxMemOp(
Op, DAG);
3763 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3764 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3798 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3803 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3804 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3828 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3830 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3839 ty(
Op.getOperand(0)).getScalarType().isFloatingPoint())
3840 return LowerHvxFpSetoeq(
Op, DAG);
3857 case HexagonISD::SMUL_LOHI:
3858 case HexagonISD::UMUL_LOHI:
3859 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3864 return LowerHvxPartialReduceMLA(
Op, DAG);
3866 return LowerHvxVecReduceFMin(
Op, DAG);
3868 return LowerHvxVecReduceFMax(
Op, DAG);
3870 return LowerHvxVecReduceFMinimum(
Op, DAG);
3872 return LowerHvxVecReduceFMaximum(
Op, DAG);
3874 return LowerHvxFMinNum(
Op, DAG);
3876 return LowerHvxFMaxNum(
Op, DAG);
3894 unsigned Opc =
Op.getOpcode();
3896 case HexagonISD::SSAT:
3897 case HexagonISD::USAT:
3913 SDValue Inp =
Op.getOperand(0);
3914 MVT InpTy = ty(Inp);
3919 assert(InpWidth != ResWidth);
3921 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3924 const SDLoc &dl(
Op);
3928 auto repeatOp = [&](
unsigned NewWidth, SDValue Arg) {
3931 case HexagonISD::SSAT:
3932 case HexagonISD::USAT:
3936 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3943 if (InpWidth < ResWidth) {
3945 while (InpWidth * 2 <= ResWidth)
3946 S = repeatOp(InpWidth *= 2, S);
3950 while (InpWidth / 2 >= ResWidth)
3951 S = repeatOp(InpWidth /= 2, S);
3958 SDValue Inp0 =
Op.getOperand(0);
3959 MVT InpTy = ty(Inp0);
3963 unsigned Opc =
Op.getOpcode();
3965 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3970 auto [WInpTy, WResTy] =
3971 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3972 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3973 SDValue
W = appendUndef(Inp0, WInpTy, DAG);
3981 SDValue
T = ExpandHvxResizeIntoSteps(S, DAG);
3982 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3983 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3990 SDValue
T = ExpandHvxResizeIntoSteps(
Op, DAG);
3993 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3996 return RemoveTLWrapper(
Op, DAG);
4002HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
4004 unsigned Opc =
N->getOpcode();
4007 if (
N->getNumOperands() > 0)
4008 Inp0 =
Op.getOperand(0);
4014 if (Subtarget.isHVXElementType(ty(
Op)) &&
4015 Subtarget.isHVXElementType(ty(Inp0))) {
4016 Results.push_back(CreateTLWrapper(
Op, DAG));
4028 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4029 if (SDValue
T = WidenHvxTruncateToBool(
Op, DAG))
4031 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4032 Subtarget.isHVXElementType(ty(Inp0))) {
4033 Results.push_back(CreateTLWrapper(
Op, DAG));
4037 if (shouldWidenToHvx(ty(Inp0), DAG)) {
4038 if (SDValue
T = WidenHvxSetCC(
Op, DAG))
4044 SDValue
Store = WidenHvxStore(
Op, DAG);
4050 if (isHvxPairTy(ty(
Op))) {
4051 SDValue S = SplitHvxMemOp(
Op, DAG);
4058 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
4059 SDValue S = SplitHvxMemOp(
Op, DAG);
4067 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4068 SDValue
T = EqualizeFpIntConversion(
Op, DAG);
4072 case HexagonISD::SSAT:
4073 case HexagonISD::USAT:
4076 Results.push_back(LegalizeHvxResize(
Op, DAG));
4084HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
4086 unsigned Opc =
N->getOpcode();
4089 if (
N->getNumOperands() > 0)
4090 Inp0 =
Op.getOperand(0);
4096 if (Subtarget.isHVXElementType(ty(
Op)) &&
4097 Subtarget.isHVXElementType(ty(Inp0))) {
4098 Results.push_back(CreateTLWrapper(
Op, DAG));
4105 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4106 if (SDValue
T = WidenHvxTruncateToBool(
Op, DAG))
4108 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4109 Subtarget.isHVXElementType(ty(Inp0))) {
4110 Results.push_back(CreateTLWrapper(
Op, DAG));
4114 if (shouldWidenToHvx(ty(
Op), DAG)) {
4115 if (SDValue
T = WidenHvxSetCC(
Op, DAG))
4120 if (shouldWidenToHvx(ty(
Op), DAG)) {
4121 SDValue
Load = WidenHvxLoad(
Op, DAG);
4129 if (isHvxBoolTy(ty(Inp0))) {
4130 SDValue
C = LowerHvxBitcast(
Op, DAG);
4136 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4137 SDValue
T = EqualizeFpIntConversion(
Op, DAG);
4141 case HexagonISD::SSAT:
4142 case HexagonISD::USAT:
4145 Results.push_back(LegalizeHvxResize(
Op, DAG));
4153HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
4154 DAGCombinerInfo &DCI)
const {
4159 SelectionDAG &DAG = DCI.DAG;
4160 const SDLoc &dl(
Op);
4164 SDValue Cast =
Op.getOperand(0);
4167 EVT TruncTy =
Op.getValueType();
4169 EVT SrcTy = Src.getValueType();
4176 if (2 * CastLen != SrcLen)
4179 SmallVector<int, 128>
Mask(SrcLen);
4180 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
4182 Mask[i + CastLen] = 2 * i + 1;
4186 return opSplit(Deal, dl, DAG).first;
4190HexagonTargetLowering::combineConcatOfShuffles(
SDValue Op,
4199 const SDLoc &dl(
Op);
4200 SDValue
V0 =
Op.getOperand(0);
4201 SDValue
V1 =
Op.getOperand(1);
4208 SetVector<SDValue> Order;
4214 if (Order.
size() > 2)
4219 EVT InpTy =
V0.getValueType();
4223 SmallVector<int, 128> LongMask;
4224 auto AppendToMask = [&](SDValue Shuffle) {
4226 ArrayRef<int>
Mask =
SV->getMask();
4227 SDValue
X = Shuffle.getOperand(0);
4228 SDValue
Y = Shuffle.getOperand(1);
4229 for (
int M : Mask) {
4234 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
4235 if (
static_cast<unsigned>(M) >= InpLen)
4238 int OutOffset = Order[0] == Src ? 0 : InpLen;
4246 SDValue C0 = Order.
front();
4247 SDValue C1 = Order.
back();
4261HexagonTargetLowering::combineConcatOfScalarPreds(
SDValue Op,
unsigned BitBytes,
4263 const SDLoc &dl(
Op);
4266 MVT InpTy = ty(
Ops[0]);
4269 assert(InpLen <= 8 &&
"Too long for scalar predicate");
4270 assert(ResLen > 8 &&
"Too short for HVX vector predicate");
4272 unsigned Bytes = 8 / InpLen;
4275 if (Bytes <= BitBytes)
4279 unsigned SliceLen = Bytes / BitBytes;
4284 for (
unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4286 Inputs.slice(SliceLen * i, SliceLen));
4293SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4294 SDValue Op, DAGCombinerInfo &DCI)
const {
4298 if (ElemTy != MVT::i1) {
4299 return combineConcatOfShuffles(
Op, DCI.DAG);
4306SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4307 unsigned Opcode,
EVT AccEltType,
unsigned AccNumElements,
EVT InputType,
4310 const auto &Subtarget = DAG.
getSubtarget<HexagonSubtarget>();
4311 if (!Subtarget.useHVXOps())
4317 unsigned NativeRatio;
4318 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4330 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4331 if (RemainingReductionRatio == 1)
4336 InputNumElements / NativeRatio);
4339 return DAG.
getNode(Opcode,
DL, IntermediateType, Zero,
A,
B);
4345 EVT AccType =
Mul.getValueType();
4351 A =
Mul->getOperand(0);
4352 B =
Mul->getOperand(1);
4372 A =
A->getOperand(0);
4373 B =
B->getOperand(0);
4374 if (
A.getValueType() !=
B.getValueType())
4385 if (!Subtarget.useHVXOps())
4388 EVT ScalarType =
N->getValueType(0);
4395 unsigned RemainingReductionRatio;
4397 createExtendingPartialReduceMLA(Opcode, ScalarType, 1,
A.getValueType(),
4398 A,
B, RemainingReductionRatio,
DL, DAG);
4414SDValue HexagonTargetLowering::LowerHvxVecReduceFMinMax(
4417 SDValue Vec =
Op.getOperand(0);
4418 MVT VecTy = ty(Vec);
4419 SDNodeFlags
Flags =
Op->getFlags();
4420 bool ShouldStripNaN = IgnoreNaN && !
Flags.hasNoNaNs();
4423 SDValue OrigVec = Vec;
4424 MVT OrigVecTy = VecTy;
4428 auto ReplaceNaN = [&](SDValue
V, MVT Ty) -> SDValue {
4439 if (isHvxPairTy(VecTy)) {
4440 auto [
Lo,
Hi] = opSplit(Vec,
DL, DAG);
4441 MVT SingleTy = ty(
Lo);
4442 if (ShouldStripNaN) {
4443 Lo = ReplaceNaN(
Lo, SingleTy);
4444 Hi = ReplaceNaN(
Hi, SingleTy);
4446 Vec = DAG.
getNode(PairwiseOpc,
DL, SingleTy,
Lo,
Hi, Flags);
4448 }
else if (ShouldStripNaN) {
4449 Vec = ReplaceNaN(Vec, VecTy);
4456 unsigned HwLen = Subtarget.getVectorLength();
4457 unsigned NumElems = HwLen / ElemBytes;
4460 for (
unsigned Width = NumElems / 2; Width >= 1; Width /= 2) {
4461 SDValue RotAmt = DAG.
getConstant(Width * ElemBytes,
DL, MVT::i32);
4463 Curr = DAG.
getNode(PairwiseOpc,
DL, VecTy, Curr, Rotated, Flags);
4467 MVT ScalarTy =
Op.getSimpleValueType();
4475 if (ShouldStripNaN) {
4484 SDValue IsOrdInt = DAG.
getBitcast(IntTy, IsOrd);
4485 SDValue AnyNonNaN = DAG.
getSetCC(
DL, MVT::i1, IsOrdInt,
4506HexagonTargetLowering::LowerHvxVecReduceFMinimum(
SDValue Op,
4512HexagonTargetLowering::LowerHvxVecReduceFMaximum(
SDValue Op,
4524 auto A =
Op.getOperand(0),
B =
Op.getOperand(1);
4528 if (!
Flags.hasNoNaNs()) {
4551 auto A =
Op.getOperand(0),
B =
Op.getOperand(1);
4555 if (!
Flags.hasNoNaNs()) {
4581HexagonTargetLowering::splitExtendingPartialReduceMLA(
SDNode *
N,
4583 if (!Subtarget.useHVXOps())
4586 SDValue Acc =
N->getOperand(0);
4587 SDValue
A =
N->getOperand(1);
4588 SDValue
B =
N->getOperand(2);
4589 if (
A.getValueType() !=
B.getValueType())
4595 EVT InputType =
A.getValueType();
4600 unsigned RemainingReductionRatio;
4601 SDValue Partial = createExtendingPartialReduceMLA(
4615 DL, AccType, Acc, Partial, One);
4619HexagonTargetLowering::LowerHvxPartialReduceMLA(
SDValue Op,
4621 const SDLoc &
DL(
Op);
4622 SDValue Acc =
Op.getOperand(0);
4623 SDValue
A =
Op.getOperand(1);
4624 SDValue
B =
Op.getOperand(2);
4627 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4631 unsigned AccSubvectorNumElements =
4633 EVT AccSubvectorType =
4636 EVT InputType =
A.getValueType();
4639 unsigned InputSubvectorNumElements =
4642 InputSubvectorNumElements);
4647 for (
unsigned I = 0;
I != SubvectorNum; ++
I) {
4649 I * AccSubvectorNumElements);
4651 I * InputSubvectorNumElements);
4653 I * InputSubvectorNumElements);
4654 SDValue SubvectorMLA = DAG.
getNode(
Op.getOpcode(),
DL, AccSubvectorType,
4655 SubvectorAcc, SubvectorA, SubvectorB);
4695 auto ResTy = ty(
Op);
4696 auto A =
Op.getOperand(0),
B =
Op->getOperand(1);
4697 MVT FloatTy = ty(
A);
4699 bool IsF32 = (ElemTy == MVT::f32);
4701 assert((ElemTy == MVT::f16));
4703 const SDLoc &
DL(
Op);
4704 MVT IntElemTy = IsF32 ? MVT::i32 : MVT::i16;
4705 MVT IntVecTy = tyVector(FloatTy, IntElemTy);
4709 bool NoNaN =
Op->getFlags().hasNoNaNs();
4727 uint64_t AbsMask = IsF32 ? 0x7FFFFFFFull : 0x7FFFull;
4728 uint64_t NaNThresh = IsF32 ? 0x7F800000ull : 0x7C00ull;
4733 SDValue ThreshVec = DAG.
getConstant(NaNThresh,
DL, IntVecTy);
4750HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
4753 SelectionDAG &DAG = DCI.DAG;
4755 unsigned Opc =
Op.getOpcode();
4760 return combineTruncateBeforeLegal(
Op, DCI);
4762 return combineConcatVectorsBeforeLegal(
Op, DCI);
4764 if (DCI.isBeforeLegalizeOps())
4771 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
4772 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
4780 return getZero(dl, ty(
Op), DAG);
4782 case HexagonISD::VINSERTW0:
4783 if (isUndef(
Ops[1]))
4801HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4802 if (Subtarget.isHVXVectorType(Ty,
true))
4804 auto Action = getPreferredHvxVectorAction(Ty);
4806 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4811HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4812 if (Subtarget.isHVXVectorType(Ty,
true))
4814 auto Action = getPreferredHvxVectorAction(Ty);
4816 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4822 if (!Subtarget.useHVXOps())
4826 auto IsHvxTy = [
this](EVT Ty) {
4827 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4829 auto IsHvxOp = [
this](SDValue
Op) {
4830 return Op.getValueType().isSimple() &&
4831 Subtarget.isHVXVectorType(ty(
Op),
true);
4837 auto IsWidenedToHvx = [
this, &DAG](SDValue
Op) {
4838 if (!
Op.getValueType().isSimple())
4841 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4844 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
4845 if (IsWidenedToHvx(SDValue(
N, i)))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const unsigned MaxExpandMLA
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static bool DetectExtendingMultiply(const SDValue &N, EVT ScalarType, unsigned &Opcode, SDValue &A, SDValue &B)
static cl::opt< unsigned > HvxWidenThreshold("hexagon-hvx-widen", cl::Hidden, cl::init(16), cl::desc("Lower threshold (in bytes) for widening to HVX vectors"))
static cl::opt< bool > EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false), cl::desc("Enable FP fast conversion routine."))
static MaybeAlign getAlign(Value *Ptr)
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
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)
uint64_t getScalarSizeInBits() const
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.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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.
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 getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
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 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 getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
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 getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
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
self_iterator getIterator()
#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.
@ 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 ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ 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...
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
initializer< Ty > init(const Ty &Val)
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
@ Fast
Assign the register banks as fast as possible (default).
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