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()) {
757 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
759 .
add(
MI.getOperand(1));
761 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
766 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
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));
784 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
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()) {
798 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
800 .
add(
MI.getOperand(1));
802 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
807 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
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));
827 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
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) {
841 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
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();
2114 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2129 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2131 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2136 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2137 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2150 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2151 assert(Val32.getValueType().getSizeInBits() == 32 &&
2152 "Input must be 32 bits");
2156 for (
unsigned i = 0; i < 32; ++i)
2164 if (ResTy == MVT::v32i1 &&
2165 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2166 Subtarget.useHVX128BOps()) {
2168 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2170 return bitcastI32ToV32I1(Val32);
2173 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2191 unsigned HwLen = Subtarget.getVectorLength();
2203 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2207 for (
unsigned J = 0; J != 8; ++J) {
2215 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2227 const SDLoc &dl(
Op);
2230 MVT ValTy = ty(Val);
2233 if (!isHvxBoolTy(ValTy))
2240 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2244 unsigned HwLen = Subtarget.getVectorLength();
2248 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2252 for (
unsigned i = 0; i != NumBits / 32; ++i) {
2263 return DAG.
getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2266 if (NumBits == 64) {
2267 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2271 if (NumBits == 128) {
2272 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2273 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2289 const SDLoc &dl(
Op);
2294 if (!isHvxBoolTy(ResTy))
2300 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2308 if (NumBits == 32) {
2316 if (NumBits == 64) {
2324 if (NumBits == 128) {
2360 const SDLoc &dl(
Op);
2361 unsigned HwLen = Subtarget.getVectorLength();
2363 assert(HwLen % VecLen == 0);
2364 unsigned ElemSize = HwLen / VecLen;
2376 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2382HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2384 unsigned Opc =
Op.getOpcode();
2396 const SDLoc &dl(
Op);
2402 bool UseShifts = ElemTy != MVT::i8;
2403 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2406 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2414 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2420 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2422 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2430 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2432 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2439 const SDLoc &dl(
Op);
2440 unsigned IntNo =
Op.getConstantOperandVal(0);
2448 case Intrinsic::hexagon_V6_pred_typecast:
2449 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2450 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2451 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2458 case Intrinsic::hexagon_V6_vmpyss_parts:
2459 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2460 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2462 case Intrinsic::hexagon_V6_vmpyuu_parts:
2463 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2464 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2466 case Intrinsic::hexagon_V6_vmpyus_parts:
2467 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2468 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2478 const SDLoc &dl(
Op);
2479 unsigned HwLen = Subtarget.getVectorLength();
2483 SDValue Chain = MaskN->getChain();
2487 unsigned Opc =
Op->getOpcode();
2504 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2508 if (MaskN->getAlign().value() % HwLen == 0) {
2517 SDValue Z = getZero(dl, ty(V), DAG);
2521 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2522 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2523 return std::make_pair(LoV, HiV);
2529 VectorPair Tmp = StoreAlign(MaskV,
Base);
2532 VectorPair ValueU = StoreAlign(
Value,
Base);
2536 getInstr(StoreOpc, dl, MVT::Other,
2537 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2539 getInstr(StoreOpc, dl, MVT::Other,
2540 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2550 assert(Subtarget.useHVXQFloatOps());
2555 MVT ArgTy = ty(
Op.getOperand(0));
2556 const SDLoc &dl(
Op);
2558 if (ArgTy == MVT::v64bf16) {
2559 MVT HalfTy = typeSplit(VecTy).first;
2562 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2567 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2568 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2570 {VecPair.second, VecPair.first,
2576 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2585 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2587 MVT HalfTy = typeSplit(VecTy).first;
2588 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2590 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2592 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2595 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2608 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2611 if (Subtarget.useHVXIEEEFPOps()) {
2613 if (FpTy == MVT::f16) {
2615 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2617 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2623 return EqualizeFpIntConversion(
Op, DAG);
2625 return ExpandHvxFpToInt(
Op, DAG);
2641 MVT ResTy = ty(PredOp);
2642 const SDLoc &dl(PredOp);
2645 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2646 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2648 SDNode *PredTransfer =
2651 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2654 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2659 SDNode *IndexShift =
2665 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2690 MVT ResTy = ty(PredOp);
2691 const SDLoc &dl(PredOp);
2701 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2702 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2712 SDNode *PredTransfer =
2716 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2723 SDNode *IndexShift_hi =
2726 SDNode *IndexShift_lo =
2730 SDNode *MaskOff_hi =
2733 SDNode *MaskOff_lo =
2756 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2757 return LowerHvxPred32ToFp(
Op, DAG);
2758 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2759 return LowerHvxPred64ToFp(
Op, DAG);
2762 if (Subtarget.useHVXIEEEFPOps()) {
2764 if (FpTy == MVT::f16) {
2766 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2768 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2774 return EqualizeFpIntConversion(
Op, DAG);
2776 return ExpandHvxIntToFp(
Op, DAG);
2779HexagonTargetLowering::TypePair
2780HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2791 unsigned MaxWidth = std::max(Width0, Width1);
2793 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2800 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2801 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2805 return {WideETy0, WideETy1};
2816HexagonTargetLowering::TypePair
2817HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2827 unsigned MaxLen = std::max(Len0, Len1);
2840HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2841 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2850HexagonTargetLowering::VectorPair
2881HexagonTargetLowering::VectorPair
2882HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2887 const SDLoc &dl(Val);
2888 MVT ValTy = ty(Val);
2902 MVT IntTy = tyVector(ValTy, ElemTy);
2914 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2933 MVT
PairTy = typeJoin({VecTy, VecTy});
2959 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2961 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2969 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2974 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2975 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2976 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2987HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2988 bool SignedB,
const SDLoc &dl,
2991 MVT
PairTy = typeJoin({VecTy, VecTy});
2996 if (SignedA && !SignedB) {
3012 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3013 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
3014 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
3023 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3026 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
3030 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3031 {HiHalf(P2, DAG), T3,
S16}, DAG);
3034 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3035 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
3039 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
3046 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
3047 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
3048 }
else if (SignedB) {
3054 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
3056 assert(!SignedA && !SignedB);
3063HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
3068 MVT
PairTy = typeJoin({VecTy, VecTy});
3071 if (SignedA && !SignedB) {
3080 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
3085 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
3097 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
3098 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
3099 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
3100 }
else if (!SignedA) {
3110 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
3128 unsigned Opc =
Op.getOpcode();
3133 MVT InpTy = ty(Inp);
3139 const SDLoc &dl(
Op);
3142 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3151 unsigned Opc =
Op.getOpcode();
3154 const SDLoc &dl(
Op);
3156 MVT InpTy = ty(Op0);
3169 if (InpTy == MVT::v64f16) {
3170 if (Subtarget.useHVXV81Ops()) {
3173 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3177 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3182 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3262 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3263 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3306 unsigned Opc =
Op.getOpcode();
3309 const SDLoc &dl(
Op);
3311 MVT InpTy = ty(Op0);
3344 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3354 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3377 unsigned Opc =
Op.getOpcode();
3394 const SDLoc &dl(
Op);
3395 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3404 unsigned Opc =
Op.getConstantOperandVal(2);
3408HexagonTargetLowering::VectorPair
3412 const SDLoc &dl(
Op);
3414 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3415 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3417 return std::make_pair(TV, TV);
3422 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3424 switch (
Op.getOpcode()) {
3425 case ISD::SIGN_EXTEND_INREG:
3426 case HexagonISD::SSAT:
3427 case HexagonISD::USAT:
3428 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3429 std::tie(Lo, Hi) = SplitVTNode(N);
3437 MVT HalfTy = typeSplit(ResTy).first;
3447 if (!MemN->getMemoryVT().isSimple())
3450 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3451 if (!isHvxPairTy(MemTy))
3454 const SDLoc &dl(
Op);
3455 unsigned HwLen = Subtarget.getVectorLength();
3456 MVT SingleTy = typeSplit(MemTy).first;
3457 SDValue Chain = MemN->getChain();
3458 SDValue Base0 = MemN->getBasePtr();
3463 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3464 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3493 assert(MaskN->isUnindexed());
3494 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3516 Masks.first, SingleTy, MOp0,
3519 Masks.second, SingleTy, MOp1,
3524 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3530 const SDLoc &dl(
Op);
3532 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3533 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3534 "Not widening loads of i1 yet");
3536 SDValue Chain = LoadN->getChain();
3541 unsigned HwLen = Subtarget.getVectorLength();
3543 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3546 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3554 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3562 const SDLoc &dl(
Op);
3564 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3565 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3566 "Not widening stores of i1 yet");
3568 SDValue Chain = StoreN->getChain();
3572 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3573 MVT ValueTy = ty(
Value);
3575 unsigned HwLen = Subtarget.getVectorLength();
3578 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3580 Len = ty(
Value).getVectorNumElements();
3582 assert(ty(
Value).getVectorNumElements() == HwLen);
3584 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3586 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3589 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3596 const SDLoc &dl(
Op);
3597 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3599 unsigned HwLen = Subtarget.getVectorLength();
3604 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3607 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3608 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3612 {WideOp0, WideOp1,
Op.getOperand(2)});
3614 EVT RetTy = typeLegalize(ty(
Op), DAG);
3616 {SetCC, getZero(dl, MVT::i32, DAG)});
3621 unsigned Opc =
Op.getOpcode();
3622 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3624 return isHvxPairTy(ty(V));
3635 return SplitHvxMemOp(
Op, DAG);
3640 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3641 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3671 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3676 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3677 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3701 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3703 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3724 case HexagonISD::SMUL_LOHI:
3725 case HexagonISD::UMUL_LOHI:
3726 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3731 return LowerHvxPartialReduceMLA(
Op, DAG);
3749 unsigned Opc =
Op.getOpcode();
3751 case HexagonISD::SSAT:
3752 case HexagonISD::USAT:
3769 MVT InpTy = ty(Inp);
3774 assert(InpWidth != ResWidth);
3776 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3779 const SDLoc &dl(
Op);
3783 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3786 case HexagonISD::SSAT:
3787 case HexagonISD::USAT:
3791 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3798 if (InpWidth < ResWidth) {
3800 while (InpWidth * 2 <= ResWidth)
3801 S = repeatOp(InpWidth *= 2, S);
3805 while (InpWidth / 2 >= ResWidth)
3806 S = repeatOp(InpWidth /= 2, S);
3814 MVT InpTy = ty(Inp0);
3818 unsigned Opc =
Op.getOpcode();
3820 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3825 auto [WInpTy, WResTy] =
3826 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3827 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3828 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3836 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3837 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3838 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3845 SDValue T = ExpandHvxResizeIntoSteps(
Op, DAG);
3848 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3851 return RemoveTLWrapper(
Op, DAG);
3857HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3859 unsigned Opc =
N->getOpcode();
3862 if (
N->getNumOperands() > 0)
3863 Inp0 =
Op.getOperand(0);
3870 if (Subtarget.isHVXElementType(ty(
Op)) &&
3871 Subtarget.isHVXElementType(ty(Inp0))) {
3872 Results.push_back(CreateTLWrapper(
Op, DAG));
3876 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3889 if (isHvxPairTy(ty(
Op))) {
3897 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3906 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3907 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3911 case HexagonISD::SSAT:
3912 case HexagonISD::USAT:
3915 Results.push_back(LegalizeHvxResize(
Op, DAG));
3923HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3925 unsigned Opc =
N->getOpcode();
3928 if (
N->getNumOperands() > 0)
3929 Inp0 =
Op.getOperand(0);
3936 if (Subtarget.isHVXElementType(ty(
Op)) &&
3937 Subtarget.isHVXElementType(ty(Inp0))) {
3938 Results.push_back(CreateTLWrapper(
Op, DAG));
3942 if (shouldWidenToHvx(ty(
Op), DAG)) {
3948 if (shouldWidenToHvx(ty(
Op), DAG)) {
3957 if (isHvxBoolTy(ty(Inp0))) {
3964 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3965 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3969 case HexagonISD::SSAT:
3970 case HexagonISD::USAT:
3973 Results.push_back(LegalizeHvxResize(
Op, DAG));
3981HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3982 DAGCombinerInfo &DCI)
const {
3987 SelectionDAG &DAG = DCI.DAG;
3988 const SDLoc &dl(
Op);
3995 EVT TruncTy =
Op.getValueType();
3997 EVT SrcTy = Src.getValueType();
4004 if (2 * CastLen != SrcLen)
4007 SmallVector<int, 128>
Mask(SrcLen);
4008 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
4010 Mask[i + CastLen] = 2 * i + 1;
4014 return opSplit(Deal, dl, DAG).first;
4018HexagonTargetLowering::combineConcatOfShuffles(
SDValue Op,
4027 const SDLoc &dl(
Op);
4036 SetVector<SDValue> Order;
4042 if (Order.
size() > 2)
4051 SmallVector<int, 128> LongMask;
4052 auto AppendToMask = [&](
SDValue Shuffle) {
4054 ArrayRef<int>
Mask = SV->getMask();
4057 for (
int M : Mask) {
4062 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
4063 if (
static_cast<unsigned>(M) >= InpLen)
4066 int OutOffset = Order[0] == Src ? 0 : InpLen;
4089HexagonTargetLowering::combineConcatOfScalarPreds(
SDValue Op,
unsigned BitBytes,
4091 const SDLoc &dl(
Op);
4094 MVT InpTy = ty(
Ops[0]);
4097 assert(InpLen <= 8 &&
"Too long for scalar predicate");
4098 assert(ResLen > 8 &&
"Too short for HVX vector predicate");
4100 unsigned Bytes = 8 / InpLen;
4103 if (Bytes <= BitBytes)
4107 unsigned SliceLen = Bytes / BitBytes;
4111 for (
unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4113 Inputs.slice(SliceLen * i, SliceLen));
4120SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4121 SDValue Op, DAGCombinerInfo &DCI)
const {
4125 if (ElemTy != MVT::i1) {
4126 return combineConcatOfShuffles(
Op, DCI.DAG);
4133SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4134 unsigned Opcode,
EVT AccEltType,
unsigned AccNumElements,
EVT InputType,
4137 const auto &Subtarget = DAG.
getSubtarget<HexagonSubtarget>();
4138 if (!Subtarget.useHVXOps())
4144 unsigned NativeRatio;
4145 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4157 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4158 if (RemainingReductionRatio == 1)
4163 InputNumElements / NativeRatio);
4166 return DAG.
getNode(Opcode,
DL, IntermediateType, Zero,
A,
B);
4172 EVT AccType =
Mul.getValueType();
4178 A =
Mul->getOperand(0);
4179 B =
Mul->getOperand(1);
4199 A =
A->getOperand(0);
4200 B =
B->getOperand(0);
4201 if (
A.getValueType() !=
B.getValueType())
4212 if (!Subtarget.useHVXOps())
4215 EVT ScalarType =
N->getValueType(0);
4222 unsigned RemainingReductionRatio;
4224 createExtendingPartialReduceMLA(Opcode, ScalarType, 1,
A.getValueType(),
4225 A,
B, RemainingReductionRatio,
DL, DAG);
4242HexagonTargetLowering::splitExtendingPartialReduceMLA(
SDNode *
N,
4244 if (!Subtarget.useHVXOps())
4250 if (
A.getValueType() !=
B.getValueType())
4256 EVT InputType =
A.getValueType();
4261 unsigned RemainingReductionRatio;
4262 SDValue Partial = createExtendingPartialReduceMLA(
4276 DL, AccType, Acc, Partial, One);
4280HexagonTargetLowering::LowerHvxPartialReduceMLA(
SDValue Op,
4282 const SDLoc &
DL(
Op);
4288 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4292 unsigned AccSubvectorNumElements =
4294 EVT AccSubvectorType =
4297 EVT InputType =
A.getValueType();
4300 unsigned InputSubvectorNumElements =
4303 InputSubvectorNumElements);
4308 for (
unsigned I = 0;
I != SubvectorNum; ++
I) {
4310 I * AccSubvectorNumElements);
4312 I * InputSubvectorNumElements);
4314 I * InputSubvectorNumElements);
4316 SubvectorAcc, SubvectorA, SubvectorB);
4324HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
4327 SelectionDAG &DAG = DCI.DAG;
4329 unsigned Opc =
Op.getOpcode();
4334 return combineTruncateBeforeLegal(
Op, DCI);
4336 return combineConcatVectorsBeforeLegal(
Op, DCI);
4338 if (DCI.isBeforeLegalizeOps())
4345 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
4346 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
4354 return getZero(dl, ty(
Op), DAG);
4356 case HexagonISD::VINSERTW0:
4357 if (isUndef(
Ops[1]))
4375HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4376 if (Subtarget.isHVXVectorType(Ty,
true))
4378 auto Action = getPreferredHvxVectorAction(Ty);
4380 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4385HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4386 if (Subtarget.isHVXVectorType(Ty,
true))
4388 auto Action = getPreferredHvxVectorAction(Ty);
4390 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4396 if (!Subtarget.useHVXOps())
4400 auto IsHvxTy = [
this](EVT Ty) {
4401 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4404 return Op.getValueType().isSimple() &&
4405 Subtarget.isHVXVectorType(ty(
Op),
true);
4411 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
4412 if (!
Op.getValueType().isSimple())
4415 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4418 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
unsigned const MachineRegisterInfo * MRI
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."))
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 TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
static 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.
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...
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 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.
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