21#include "llvm/IR/IntrinsicsHexagon.h"
33 cl::desc(
"Lower threshold (in bytes) for widening to HVX vectors"));
37 cl::desc(
"Enable FP fast conversion routine."));
41 cl::desc(
"Enable XQF fast conversion routine."));
43static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
44static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
45static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
46static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
55 return std::make_tuple(5, 15, 10);
57 return std::make_tuple(8, 127, 23);
59 return std::make_tuple(11, 1023, 52);
67HexagonTargetLowering::initializeHVXLowering() {
68 if (Subtarget.useHVX64BOps()) {
86 }
else if (Subtarget.useHVX128BOps()) {
96 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
102 if (Subtarget.useHVXV81Ops()) {
110 bool Use64b = Subtarget.useHVX64BOps();
113 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
114 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
115 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
117 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
135 if (Subtarget.useHVX128BOps()) {
145 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
146 Subtarget.useHVXFloatingPoint()) {
148 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
149 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
151 for (MVT
T : FloatV) {
199 if (!Subtarget.useHVXV81Ops())
203 if (Subtarget.useHVXV81Ops()) {
206 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
207 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
208 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
209 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
234 for (MVT
P : FloatW) {
264 if (Subtarget.useHVXQFloatOps()) {
267 }
else if (Subtarget.useHVXIEEEFPOps()) {
273 for (MVT
T : LegalV) {
300 if (
T.getScalarType() != MVT::i32) {
309 if (
T.getScalarType() != MVT::i32) {
337 if (Subtarget.useHVXFloatingPoint()) {
354 for (MVT
T : LegalW) {
409 if (
T.getScalarType() != MVT::i32) {
414 if (Subtarget.useHVXFloatingPoint()) {
461 for (MVT
T : LegalW) {
478 for (MVT
T : LegalV) {
493 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
496 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
501 unsigned HwLen = Subtarget.getVectorLength();
502 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
503 if (ElemTy == MVT::i1)
505 int ElemWidth = ElemTy.getFixedSizeInBits();
506 int MaxElems = (8*HwLen) / ElemWidth;
507 for (
int N = 2;
N < MaxElems;
N *= 2) {
518 if (Subtarget.useHVXFloatingPoint()) {
548 auto HvxType = [=](MVT ScalarT,
unsigned Factor = 1) {
557 typedef std::tuple<MVT, MVT, bool> ReductionSignature;
559 static const std::vector<ReductionSignature> NativeReductions = {
560 {MVT::i32, MVT::i8,
false},
563 for (
const auto &R : NativeReductions) {
565 MVT AccType = std::get<0>(R);
566 MVT InputType = std::get<1>(R);
567 unsigned Factor = std::get<2>(R) ? 2 : 1;
589 for (
unsigned ConcatFactor = 1; ConcatFactor <=
MaxExpandMLA;
591 for (
unsigned ReductionFactor = 1; ReductionFactor <=
MaxExpandMLA;
592 ReductionFactor <<= 1)
593 if (ConcatFactor * ReductionFactor != 1 &&
596 MLAOps, HvxType(AccType, Factor * ConcatFactor),
597 HvxType(InputType, Factor * ConcatFactor * ReductionFactor),
604HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
611 unsigned HwLen = Subtarget.getVectorLength();
614 if (ElemTy == MVT::i1 && VecLen > HwLen)
620 if (ElemTy == MVT::i1) {
635 unsigned HwWidth = 8*HwLen;
636 if (VecWidth > 2*HwWidth)
642 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
651HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
652 unsigned Opc =
Op.getOpcode();
654 case HexagonISD::SMUL_LOHI:
655 case HexagonISD::UMUL_LOHI:
656 case HexagonISD::USMUL_LOHI:
672HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
673 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
677 Tys.second.getVectorNumElements());
680HexagonTargetLowering::TypePair
681HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
684 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
686 return { HalfTy, HalfTy };
690HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
697HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
704HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
713HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
719HexagonTargetLowering::VectorPair
720HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
722 TypePair Tys = typeSplit(ty(Vec));
725 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
729HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
730 return Subtarget.isHVXVectorType(Ty) &&
735HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
736 return Subtarget.isHVXVectorType(Ty) &&
741HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
742 return Subtarget.isHVXVectorType(Ty,
true) &&
746bool HexagonTargetLowering::allowsHvxMemoryAccess(
754 if (!Subtarget.isHVXVectorType(VecTy,
false))
761bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
763 if (!Subtarget.isHVXVectorType(VecTy))
771void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
773 unsigned Opc =
MI.getOpcode();
774 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
775 MachineBasicBlock &MB = *
MI.getParent();
782 case Hexagon::PS_vsplatib:
783 if (Subtarget.useHVXV62Ops()) {
788 .
add(
MI.getOperand(1));
790 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
796 const MachineOperand &InpOp =
MI.getOperand(1);
798 uint32_t
V = InpOp.
getImm() & 0xFF;
800 .
addImm(V << 24 | V << 16 | V << 8 | V);
806 case Hexagon::PS_vsplatrb:
807 if (Subtarget.useHVXV62Ops()) {
810 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
811 .
add(
MI.getOperand(1));
814 const MachineOperand &InpOp =
MI.getOperand(1);
815 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
818 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
823 case Hexagon::PS_vsplatih:
824 if (Subtarget.useHVXV62Ops()) {
829 .
add(
MI.getOperand(1));
831 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
837 const MachineOperand &InpOp =
MI.getOperand(1);
839 uint32_t
V = InpOp.
getImm() & 0xFFFF;
847 case Hexagon::PS_vsplatrh:
848 if (Subtarget.useHVXV62Ops()) {
851 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
852 .
add(
MI.getOperand(1));
857 const MachineOperand &InpOp =
MI.getOperand(1);
858 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
866 case Hexagon::PS_vsplatiw:
867 case Hexagon::PS_vsplatrw:
868 if (
Opc == Hexagon::PS_vsplatiw) {
872 .
add(
MI.getOperand(1));
873 MI.getOperand(1).ChangeToRegister(SplatV,
false);
876 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
882HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
892 const SDLoc &dl(ElemIdx);
898HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
901 assert(ElemWidth >= 8 && ElemWidth <= 32);
905 if (ty(Idx) != MVT::i32)
907 const SDLoc &dl(Idx);
914HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
921 if (ElemTy == MVT::i8)
925 MVT ResTy = tyVector(OpTy, MVT::i8);
928 SmallVector<int,128> ByteMask;
931 for (
unsigned I = 0;
I != ElemSize; ++
I)
934 int NewM =
M*ElemSize;
935 for (
unsigned I = 0;
I != ElemSize; ++
I)
941 opCastElem(Op1, MVT::i8, DAG), ByteMask);
948 unsigned VecLen =
Values.size();
952 unsigned HwLen = Subtarget.getVectorLength();
954 unsigned ElemSize = ElemWidth / 8;
955 assert(ElemSize*VecLen == HwLen);
959 !(Subtarget.useHVXFloatingPoint() &&
961 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
962 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
964 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
965 SDValue
W = buildVector32(
Values.slice(i, OpsPerWord), dl, PartVT, DAG);
973 unsigned NumValues =
Values.size();
976 for (
unsigned i = 0; i != NumValues; ++i) {
980 if (!SplatV.getNode())
982 else if (SplatV !=
Values[i])
990 unsigned NumWords = Words.
size();
992 bool IsSplat =
isSplat(Words, SplatV);
993 if (IsSplat && isUndef(SplatV))
998 return getZero(dl, VecTy, DAG);
1007 bool AllConst = getBuildVectorConstInts(
Values, VecTy, DAG, Consts);
1010 (Constant**)Consts.end());
1027 auto IsBuildFromExtracts = [
this,&
Values] (SDValue &SrcVec,
1028 SmallVectorImpl<int> &SrcIdx) {
1030 for (SDValue V :
Values) {
1032 SrcIdx.push_back(-1);
1038 SDValue
T =
V.getOperand(0);
1045 int I =
C->getSExtValue();
1046 assert(
I >= 0 &&
"Negative element index");
1047 SrcIdx.push_back(
I);
1053 SmallVector<int,128> ExtIdx;
1055 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
1056 MVT ExtTy = ty(ExtVec);
1058 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
1062 SmallVector<int,128>
Mask;
1063 BitVector
Used(ExtLen);
1065 for (
int M : ExtIdx) {
1075 for (
unsigned I = 0;
I != ExtLen; ++
I) {
1076 if (
Mask.size() == ExtLen)
1084 return ExtLen == VecLen ? S : LoHalf(S, DAG);
1092 assert(4*Words.
size() == Subtarget.getVectorLength());
1095 for (
unsigned i = 0; i != NumWords; ++i) {
1097 if (Words[i].isUndef())
1099 for (
unsigned j = i;
j != NumWords; ++
j)
1100 if (Words[i] == Words[j])
1103 if (VecHist[i] > VecHist[n])
1107 SDValue HalfV = getZero(dl, VecTy, DAG);
1108 if (VecHist[n] > 1) {
1115 SDValue SplatV = DAG.
getBitcast(VecTy, WordSplat);
1116 HalfV = DAG.
getNode(HexagonISD::VALIGN, dl, VecTy,
1117 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1119 SDValue HalfV0 = HalfV;
1120 SDValue HalfV1 = HalfV;
1129 for (
unsigned i = 0; i != NumWords/2; ++i) {
1131 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1134 N = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1135 {HalfV0, Words[i]});
1138 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1141 M = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1142 {HalfV1, Words[i+NumWords/2]});
1154 SDValue T0 = DAG.
getBitcast(tyVector(VecTy, MVT::i32), HalfV0);
1155 SDValue
T1 = DAG.
getBitcast(tyVector(VecTy, MVT::i32), HalfV1);
1165HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1166 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1167 MVT PredTy = ty(PredV);
1168 unsigned HwLen = Subtarget.getVectorLength();
1171 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1181 SmallVector<int,128>
Mask(HwLen);
1186 for (
unsigned i = 0; i != HwLen; ++i) {
1187 unsigned Num = i % Scale;
1188 unsigned Off = i / Scale;
1197 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1199 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1206 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1212 SDValue W0 = isUndef(PredV)
1218 while (Bytes < BitBytes) {
1220 Words[IdxW].
clear();
1223 for (
const SDValue &W : Words[IdxW ^ 1]) {
1224 SDValue
T = expandPredicate(W, dl, DAG);
1229 for (
const SDValue &W : Words[IdxW ^ 1]) {
1237 assert(Bytes == BitBytes);
1238 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1239 SDValue S4 = DAG.
getConstant(HwLen-4, dl, MVT::i32);
1240 for (
const SDValue &W : Words[IdxW]) {
1242 Vec = DAG.
getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1254 unsigned VecLen =
Values.size();
1255 unsigned HwLen = Subtarget.getVectorLength();
1256 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1258 bool AllT =
true, AllF =
true;
1260 auto IsTrue = [] (SDValue
V) {
1262 return !
N->isZero();
1265 auto IsFalse = [] (SDValue
V) {
1271 if (VecLen <= HwLen) {
1275 assert(HwLen % VecLen == 0);
1276 unsigned BitBytes = HwLen / VecLen;
1277 for (SDValue V :
Values) {
1283 for (
unsigned B = 0;
B != BitBytes; ++
B)
1290 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1293 for (;
B != 8; ++
B) {
1312 return DAG.
getNode(HexagonISD::QTRUE, dl, VecTy);
1314 return DAG.
getNode(HexagonISD::QFALSE, dl, VecTy);
1317 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1322HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1327 assert(ElemWidth >= 8 && ElemWidth <= 32);
1330 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1331 SDValue ExWord = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1333 if (ElemTy == MVT::i32)
1339 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1341 SDValue ExVec = DAG.
getBitcast(tyVector(ty(ExWord), ElemTy), ExWord);
1342 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1346HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1349 assert(ResTy == MVT::i1);
1351 unsigned HwLen = Subtarget.getVectorLength();
1355 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1356 SDValue ScV = DAG.
getConstant(Scale, dl, MVT::i32);
1359 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1361 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1365HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1370 assert(ElemWidth >= 8 && ElemWidth <= 32);
1373 auto InsertWord = [&DAG,&dl,
this] (SDValue VecV, SDValue ValV,
1375 MVT VecTy = ty(VecV);
1376 unsigned HwLen = Subtarget.getVectorLength();
1381 SDValue InsV = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1388 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1389 if (ElemTy == MVT::i32)
1390 return InsertWord(VecV, ValV, ByteIdx);
1396 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1401 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1402 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1403 SDValue Ins = insertVector(DAG.
getBitcast(SubVecTy, Ext),
1404 ValV, SubIdx, dl, ElemTy, DAG);
1407 return InsertWord(VecV, Ins, ByteIdx);
1411HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1413 unsigned HwLen = Subtarget.getVectorLength();
1417 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1418 SDValue ScV = DAG.
getConstant(Scale, dl, MVT::i32);
1422 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1427HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1429 MVT VecTy = ty(VecV);
1430 unsigned HwLen = Subtarget.getVectorLength();
1438 if (isHvxPairTy(VecTy)) {
1439 unsigned SubIdx = Hexagon::vsub_lo;
1440 if (Idx * ElemWidth >= 8 * HwLen) {
1441 SubIdx = Hexagon::vsub_hi;
1445 VecTy = typeSplit(VecTy).first;
1455 MVT WordTy = tyVector(VecTy, MVT::i32);
1456 SDValue WordVec = DAG.
getBitcast(WordTy, VecV);
1457 unsigned WordIdx = (
Idx*ElemWidth) / 32;
1459 SDValue W0Idx = DAG.
getConstant(WordIdx, dl, MVT::i32);
1460 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1464 SDValue W1Idx = DAG.
getConstant(WordIdx+1, dl, MVT::i32);
1465 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1466 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1471HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1473 MVT VecTy = ty(VecV);
1474 unsigned HwLen = Subtarget.getVectorLength();
1484 SmallVector<int,128>
Mask;
1486 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1493 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1494 for (
unsigned j = 0;
j != Rep; ++
j)
1511 unsigned Rep = 8 / ResLen;
1514 for (
unsigned r = 0; r != HwLen / 8; ++r) {
1516 for (
unsigned i = 0; i != ResLen; ++i) {
1517 for (
unsigned j = 0;
j != Rep; ++
j)
1522 SDValue
Zero = getZero(dl, MVT::i32, DAG);
1526 SDValue W0 = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32, {ShuffV,
Zero});
1527 SDValue W1 = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1529 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1530 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1535HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1537 MVT VecTy = ty(VecV);
1538 MVT SubTy = ty(SubV);
1539 unsigned HwLen = Subtarget.getVectorLength();
1543 bool IsPair = isHvxPairTy(VecTy);
1547 SDValue SingleV = VecV;
1551 V0 = LoHalf(VecV, DAG);
1552 V1 = HiHalf(VecV, DAG);
1557 if (isHvxSingleTy(SubTy)) {
1559 unsigned Idx = CN->getZExtValue();
1561 unsigned SubIdx = (
Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1584 if (!IdxN || !IdxN->isZero()) {
1592 unsigned RolBase = HwLen;
1595 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1598 SDValue R0 = LoHalf(V, DAG);
1599 SDValue R1 = HiHalf(V, DAG);
1600 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1603 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1607 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1622HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1624 MVT VecTy = ty(VecV);
1625 MVT SubTy = ty(SubV);
1626 assert(Subtarget.isHVXVectorType(VecTy,
true));
1631 unsigned HwLen = Subtarget.getVectorLength();
1632 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1635 unsigned BitBytes = HwLen / VecLen;
1636 unsigned BlockLen = HwLen / Scale;
1640 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1644 if (!IdxN || !IdxN->isZero()) {
1653 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1655 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1657 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1659 if (!IdxN || !IdxN->isZero()) {
1660 SDValue HwLenV = DAG.
getConstant(HwLen, dl, MVT::i32);
1661 SDValue ByteXdi = DAG.
getNode(
ISD::SUB, dl, MVT::i32, HwLenV, ByteIdx);
1668HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1673 assert(Subtarget.isHVXVectorType(ResTy));
1680 SDValue
False = getZero(dl, ResTy, DAG);
1685HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1693 unsigned HwLen = Subtarget.getVectorLength();
1695 MVT PredTy = ty(VecQ);
1697 assert(HwLen % PredLen == 0);
1704 for (
unsigned i = 0; i != HwLen/8; ++i) {
1705 for (
unsigned j = 0;
j != 8; ++
j)
1706 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1719 getZero(dl, VecTy, DAG));
1725 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1727 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1734 SmallVector<int,128>
Mask;
1735 for (
unsigned i = 0; i != HwLen; ++i)
1736 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1746 MVT InpTy = ty(VecV);
1754 return InpWidth < ResWidth
1762 if (InpWidth < ResWidth) {
1764 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1766 unsigned NarOpc =
Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1772HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1776 const SDLoc &dl(Vec);
1785 const SDLoc &dl(
Op);
1790 for (
unsigned i = 0; i !=
Size; ++i)
1791 Ops.push_back(
Op.getOperand(i));
1794 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1802 for (
unsigned i = 0; i !=
Size; i++)
1813 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1815 MVT SingleTy = typeSplit(VecTy).first;
1816 SDValue
V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1817 SDValue
V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1821 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1827 const SDLoc &dl(
Op);
1829 MVT ArgTy = ty(
Op.getOperand(0));
1831 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1833 SDValue ToInt16 = DAG.
getBitcast(MVT::i16,
Op.getOperand(0));
1849 const SDLoc &dl(
Op);
1856 for (SDValue V :
Op.getNode()->ops())
1863 for (SDValue &V : Elems) {
1866 MVT NTy = typeLegalize(Ty, DAG);
1870 V.getOperand(0),
V.getOperand(1)),
1875 switch (
V.getOpcode()) {
1883 V =
V.getOperand(0);
1894 unsigned HwLen = Subtarget.getVectorLength();
1897 SDValue Op0 =
Op.getOperand(0);
1901 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1903 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, Op0,
Op.getOperand(1));
1909 MVT HalfTy = typeSplit(VecTy).first;
1911 Ops.take_front(NumOp/2));
1913 Ops.take_back(NumOp/2));
1914 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, V0,
V1);
1924 SDValue Combined = combineConcatOfScalarPreds(
Op, BitBytes, DAG);
1927 SDValue
P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1931 unsigned InpLen = ty(Combined.
getOperand(0)).getVectorNumElements();
1933 SDValue S = DAG.
getConstant(HwLen - InpLen*BitBytes, dl, MVT::i32);
1934 SDValue Res = getZero(dl, ByteTy, DAG);
1935 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1946 SDValue VecV =
Op.getOperand(0);
1948 const SDLoc &dl(
Op);
1949 SDValue IdxV =
Op.getOperand(1);
1950 if (ElemTy == MVT::i1)
1951 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1953 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1959 const SDLoc &dl(
Op);
1960 SDValue VecV =
Op.getOperand(0);
1961 SDValue ValV =
Op.getOperand(1);
1962 SDValue IdxV =
Op.getOperand(2);
1964 if (ElemTy == MVT::i1)
1965 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1967 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1973 SDValue SrcV =
Op.getOperand(0);
1974 MVT SrcTy = ty(SrcV);
1976 SDValue IdxV =
Op.getOperand(1);
1980 const SDLoc &dl(
Op);
1983 if (ElemTy == MVT::i1)
1984 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1986 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1993 SDValue VecV =
Op.getOperand(0);
1994 SDValue ValV =
Op.getOperand(1);
1995 SDValue IdxV =
Op.getOperand(2);
1997 const SDLoc &dl(
Op);
1998 MVT VecTy = ty(VecV);
2000 if (ElemTy == MVT::i1)
2001 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
2003 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
2013 SDValue InpV =
Op.getOperand(0);
2015 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2016 return LowerHvxSignExt(
Op, DAG);
2023 SDValue InpV =
Op.getOperand(0);
2025 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2026 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
2033 SDValue InpV =
Op.getOperand(0);
2035 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2036 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
2044 const SDLoc &dl(
Op);
2046 SDValue InpV =
Op.getOperand(0);
2047 assert(ResTy == ty(InpV));
2072 const SDLoc &dl(
Op);
2076 SDValue Vs =
Op.getOperand(0);
2077 SDValue Vt =
Op.getOperand(1);
2079 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2080 unsigned Opc =
Op.getOpcode();
2084 return DAG.
getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2086 return DAG.
getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2096 const SDLoc &dl(
Op);
2097 unsigned Opc =
Op.getOpcode();
2098 SDValue Vu =
Op.getOperand(0);
2099 SDValue Vv =
Op.getOperand(1);
2102 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2109 bool SignedVu =
Opc == HexagonISD::SMUL_LOHI;
2110 bool SignedVv =
Opc == HexagonISD::SMUL_LOHI ||
Opc == HexagonISD::USMUL_LOHI;
2114 if (Subtarget.useHVXV62Ops())
2115 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2117 if (
Opc == HexagonISD::SMUL_LOHI) {
2120 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2121 SDValue
Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2127 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2132 SDValue Val =
Op.getOperand(0);
2134 MVT ValTy = ty(Val);
2135 const SDLoc &dl(
Op);
2138 unsigned HwLen = Subtarget.getVectorLength();
2146 if (PredLen < HwLen) {
2149 if (HwLen > PredLen * 2) {
2150 assert(HwLen == PredLen * 4);
2152 Val = getInstr(Hexagon::V6_vdealh, dl, ByteTy, Val, DAG);
2154 if (HwLen > PredLen) {
2155 assert(HwLen == PredLen * 2);
2156 Val = getInstr(Hexagon::V6_vdealb, dl, ByteTy, Val, DAG);
2161 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2165 SDValue W0 = extractHvxElementReg(VQ, DAG.
getConstant(0, dl, MVT::i32),
2176 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2177 SDValue
W = extractHvxElementReg(
2178 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2183 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2184 SDValue
C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2197 auto bitcastI32ToV32I1 = [&](SDValue Val32) {
2198 assert(Val32.getValueType().getSizeInBits() == 32 &&
2199 "Input must be 32 bits");
2203 for (
unsigned i = 0; i < 32; ++i)
2211 if (ResTy == MVT::v32i1 &&
2212 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2213 Subtarget.useHVX128BOps()) {
2214 SDValue Val32 = Val;
2215 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2217 return bitcastI32ToV32I1(Val32);
2220 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2228 SDValue LoRes = bitcastI32ToV32I1(
Lo);
2229 SDValue HiRes = bitcastI32ToV32I1(
Hi);
2238 unsigned HwLen = Subtarget.getVectorLength();
2242 SDValue ValAsVec = DAG.
getBitcast(ValAsVecTy, Val);
2250 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2254 for (
unsigned J = 0; J != 8; ++J) {
2261 SDValue ConstantVec = DAG.
getBuildVector(ConstantVecTy, dl, Tmp);
2262 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2274 const SDLoc &dl(
Op);
2277 MVT ValTy = ty(Val);
2280 if (!isHvxBoolTy(ValTy))
2287 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2291 unsigned HwLen = Subtarget.getVectorLength();
2295 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2299 for (
unsigned i = 0; i != NumBits / 32; ++i) {
2300 SDValue
W = extractHvxElementReg(VQ, DAG.
getConstant(i, dl, MVT::i32), dl,
2310 return DAG.
getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2313 if (NumBits == 64) {
2314 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2318 if (NumBits == 128) {
2319 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2320 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2325 SDValue Offset8 = DAG.
getConstant(8, dl, MVT::i32);
2336 const SDLoc &dl(
Op);
2341 if (!isHvxBoolTy(ResTy))
2347 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2355 if (NumBits == 32) {
2363 if (NumBits == 64) {
2371 if (NumBits == 128) {
2376 SDValue Offset8 = DAG.
getConstant(8, dl, MVT::i32);
2378 SDValue Hi64 = DAG.
getLoad(MVT::i64, dl, Chain, Ptr8,
2407 const SDLoc &dl(
Op);
2408 unsigned HwLen = Subtarget.getVectorLength();
2410 assert(HwLen % VecLen == 0);
2411 unsigned ElemSize = HwLen / VecLen;
2423 if (SDValue S = getVectorShiftByInt(
Op, DAG))
2429HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2431 unsigned Opc =
Op.getOpcode();
2436 SDValue
A =
Op.getOperand(0);
2437 SDValue
B =
Op.getOperand(1);
2438 SDValue S =
Op.getOperand(2);
2443 const SDLoc &dl(
Op);
2449 bool UseShifts = ElemTy != MVT::i8;
2450 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2453 if (SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2461 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2467 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2469 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2477 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2479 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2486 const SDLoc &dl(
Op);
2487 unsigned IntNo =
Op.getConstantOperandVal(0);
2490 auto Swap = [&](SDValue
P) {
2494 const SDLoc &
DL(
Op);
2499 case Intrinsic::hexagon_V6_vcvt_b_hf_128B:
2500 case Intrinsic::hexagon_V6_vcvt_h_hf_128B:
2501 case Intrinsic::hexagon_V6_vcvt_ub_hf_128B:
2502 case Intrinsic::hexagon_V6_vcvt_uh_hf_128B: {
2506 if (!HST.useHVXV79OpsOnly())
2512 SDValue Arg =
Op.getOperand(i);
2515 "Expecting a vector argument type for V6_vcvt_h_hf instrinsic.");
2517 Args.push_back(Entry);
2521 bool LongCalls = HST.useLongCalls();
2524 const char *
Name =
nullptr;
2526 case Intrinsic::hexagon_V6_vcvt_b_hf_128B: {
2528 :
"__qf_convert_hf_to_b_rne";
2531 case Intrinsic::hexagon_V6_vcvt_h_hf_128B: {
2533 :
"__qf_convert_hf_to_h_rne";
2536 case Intrinsic::hexagon_V6_vcvt_ub_hf_128B: {
2538 :
"__qf_convert_hf_to_ub_rne";
2541 case Intrinsic::hexagon_V6_vcvt_uh_hf_128B: {
2543 :
"__qf_convert_hf_to_uh_rne";
2549 "' in HexagonTargetLowering::LowerHvxIntrinsic");
2555 TargetLowering::CallLoweringInfo CLI(DAG);
2559 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
2560 return CallResult.first;
2562 case Intrinsic::hexagon_V6_pred_typecast:
2563 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2564 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2565 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2572 case Intrinsic::hexagon_V6_vmpyss_parts:
2573 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2574 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2576 case Intrinsic::hexagon_V6_vmpyuu_parts:
2577 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2578 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2580 case Intrinsic::hexagon_V6_vmpyus_parts:
2581 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2582 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2592 const SDLoc &dl(
Op);
2593 unsigned HwLen = Subtarget.getVectorLength();
2596 SDValue
Mask = MaskN->getMask();
2597 SDValue Chain = MaskN->getChain();
2598 SDValue
Base = MaskN->getBasePtr();
2601 unsigned Opc =
Op->getOpcode();
2618 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2622 if (MaskN->getAlign().value() % HwLen == 0) {
2623 SDValue
Store = getInstr(StoreOpc, dl, MVT::Other,
2630 auto StoreAlign = [&](SDValue
V, SDValue
A) {
2631 SDValue
Z = getZero(dl, ty(V), DAG);
2635 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2636 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2637 return std::make_pair(LoV, HiV);
2643 VectorPair Tmp = StoreAlign(MaskV,
Base);
2646 VectorPair ValueU = StoreAlign(
Value,
Base);
2650 getInstr(StoreOpc, dl, MVT::Other,
2651 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2662 uint64_t StoreMemSize = MaskN->getMemoryVT().getStoreSize().getFixedValue();
2663 if (StoreMemSize <= MaskN->
getAlign().value())
2667 getInstr(StoreOpc, dl, MVT::Other,
2668 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2677 assert(Subtarget.useHVXQFloatOps());
2682 MVT ArgTy = ty(
Op.getOperand(0));
2683 const SDLoc &dl(
Op);
2685 if (ArgTy == MVT::v64bf16) {
2686 MVT HalfTy = typeSplit(VecTy).first;
2687 SDValue BF16Vec =
Op.getOperand(0);
2689 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2694 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2695 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2696 SDValue
Result = getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2697 {VecPair.second, VecPair.first,
2703 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2705 SDValue F16Vec =
Op.getOperand(0);
2712 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2714 MVT HalfTy = typeSplit(VecTy).first;
2715 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2717 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2719 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2722 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2735 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2738 if (Subtarget.useHVXIEEEFPOps()) {
2740 if (FpTy == MVT::f16) {
2742 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2744 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2750 return EqualizeFpIntConversion(
Op, DAG);
2752 return ExpandHvxFpToInt(
Op, DAG);
2768 MVT ResTy = ty(PredOp);
2769 const SDLoc &dl(PredOp);
2772 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2773 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2774 SDValue(RegConst, 0));
2775 SDNode *PredTransfer =
2777 SDValue(SplatConst, 0), SDValue(RegConst, 0));
2778 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2779 SDValue(PredTransfer, 0));
2781 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2785 SDValue(PrefixSum, 0), SDValue(SplatConst, 0));
2786 SDNode *IndexShift =
2788 SDValue(SplatParam, 0), SDValue(Vsub, 0));
2791 SDValue(IndexShift, 0), SDValue(SplatConst, 0));
2792 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2793 SDValue(MaskOff, 0));
2794 return SDValue(Convert, 0);
2817 MVT ResTy = ty(PredOp);
2818 const SDLoc &dl(PredOp);
2828 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2829 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2830 SDValue(RegConst, 0));
2839 SDNode *PredTransfer =
2841 SDValue(SplatConst, 0), SDValue(RegConst, 0));
2843 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2844 SDValue(PredTransfer, 0));
2848 SDValue(PrefixSum, 0), SDValue(SplatConst, 0));
2850 SDNode *IndexShift_hi =
2852 SDValue(SplatHi, 0), SDValue(Vsub, 0));
2853 SDNode *IndexShift_lo =
2855 SDValue(SplatLo, 0), SDValue(Vsub, 0));
2857 SDNode *MaskOff_hi =
2859 SDValue(IndexShift_hi, 0), SDValue(SplatConst, 0));
2860 SDNode *MaskOff_lo =
2862 SDValue(IndexShift_lo, 0), SDValue(SplatConst, 0));
2866 SDValue(MaskOff_hi, 0), SDValue(MaskOff_lo, 0));
2868 DAG.
getMachineNode(Hexagon::V6_vconv_hf_h, dl, ResTy, SDValue(Pack, 0));
2869 return SDValue(Convert, 0);
2883 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2884 return LowerHvxPred32ToFp(
Op, DAG);
2885 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2886 return LowerHvxPred64ToFp(
Op, DAG);
2889 if (Subtarget.useHVXIEEEFPOps()) {
2891 if (FpTy == MVT::f16) {
2893 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2895 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2901 return EqualizeFpIntConversion(
Op, DAG);
2903 return ExpandHvxIntToFp(
Op, DAG);
2906HexagonTargetLowering::TypePair
2907HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2918 unsigned MaxWidth = std::max(Width0, Width1);
2920 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2927 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2928 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2932 return {WideETy0, WideETy1};
2943HexagonTargetLowering::TypePair
2944HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2954 unsigned MaxLen = std::max(Len0, Len1);
2967HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2968 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2977HexagonTargetLowering::VectorPair
3008HexagonTargetLowering::VectorPair
3009HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
3014 const SDLoc &dl(Val);
3015 MVT ValTy = ty(Val);
3029 MVT IntTy = tyVector(ValTy, ElemTy);
3034 SDValue LowBits = DAG.
getConstant((1ull << (Amt - 1)) - 1, dl, IntTy);
3036 SDValue AmtP1 = DAG.
getConstant(1ull << Amt, dl, IntTy);
3038 SDValue
Zero = getZero(dl, IntTy, DAG);
3041 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
3043 SDValue AmtM1 = DAG.
getConstant(Amt - 1, dl, IntTy);
3044 SDValue Tmp1 = DAG.
getNode(ShRight, dl, IntTy, Inp, AmtM1);
3045 SDValue Tmp2 = DAG.
getNode(ShRight, dl, IntTy, Tmp0, AmtM1);
3050 SDValue Tmp4 = DAG.
getNode(ShRight, dl, IntTy, {Tmp2, One});
3051 SDValue Tmp5 = DAG.
getNode(ShRight, dl, IntTy, {Tmp3, One});
3060 MVT
PairTy = typeJoin({VecTy, VecTy});
3086 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
3088 SDValue
T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
3090 SDValue
P0 = getInstr(Hexagon::V6_vmpyhus, dl,
PairTy, {
T1,
B}, DAG);
3092 SDValue T2 = LoHalf(P0, DAG);
3096 SDValue
P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
3098 SDValue
P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
3101 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3102 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
3103 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
3106 SDValue
P3 = getInstr(Hexagon::V6_vmpyhv, dl,
PairTy, {
T1, T4}, DAG);
3107 SDValue T5 = LoHalf(P3, DAG);
3114HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
3115 bool SignedB,
const SDLoc &dl,
3118 MVT
PairTy = typeJoin({VecTy, VecTy});
3123 if (SignedA && !SignedB) {
3136 SDValue
P0 = getInstr(Hexagon::V6_vmpyuhv, dl,
PairTy, {
A,
B}, DAG);
3139 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3140 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
3141 SDValue
T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
3145 SDValue
P1 = getInstr(Hexagon::V6_vmpyuhv, dl,
PairTy, {
A,
T1}, DAG);
3149 SDValue
P2 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy,
3150 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3153 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
3157 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3158 {HiHalf(P2, DAG), T3,
S16}, DAG);
3161 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3162 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
3166 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
3169 SDValue
Zero = getZero(dl, VecTy, DAG);
3173 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
3174 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
3175 }
else if (SignedB) {
3179 SDValue
Zero = getZero(dl, VecTy, DAG);
3181 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
3183 assert(!SignedA && !SignedB);
3190HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
3195 MVT
PairTy = typeJoin({VecTy, VecTy});
3198 if (SignedA && !SignedB) {
3205 SDValue
P0 = getInstr(Hexagon::V6_vmpyewuh_64, dl,
PairTy, {
A,
B}, DAG);
3207 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
3208 SDValue
Lo = LoHalf(P1, DAG);
3209 SDValue
Hi = HiHalf(P1, DAG);
3212 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
3213 SDValue
Zero = getZero(dl, VecTy, DAG);
3224 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
3225 SDValue
T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
3226 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
3227 }
else if (!SignedA) {
3228 SDValue
Zero = getZero(dl, VecTy, DAG);
3237 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
3255 unsigned Opc =
Op.getOpcode();
3259 SDValue Inp =
Op.getOperand(0);
3260 MVT InpTy = ty(Inp);
3266 const SDLoc &dl(
Op);
3269 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3270 SDValue WInp = resizeToWidth(Inp, WInpTy,
Signed, dl, DAG);
3271 SDValue Conv = DAG.
getNode(
Opc, dl, WResTy, WInp);
3272 SDValue Res = resizeToWidth(Conv, ResTy,
Signed, dl, DAG);
3278 unsigned Opc =
Op.getOpcode();
3281 const SDLoc &dl(
Op);
3282 SDValue Op0 =
Op.getOperand(0);
3283 MVT InpTy = ty(Op0);
3296 if (InpTy == MVT::v64f16) {
3297 if (Subtarget.useHVXV81Ops()) {
3300 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3304 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3309 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3389 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3390 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3393 SDValue
Zero = getZero(dl, ResTy, DAG);
3395 SDValue M80 = DAG.
getConstant(1ull << (ElemWidth - 1), dl, ResTy);
3396 SDValue M7F = DAG.
getConstant((1ull << (ElemWidth - 1)) - 1, dl, ResTy);
3400 SDValue MNE = DAG.
getConstant(ElemWidth - ExpWidth, dl, ResTy);
3403 SDValue ExpW = DAG.
getConstant(ExpWidth, dl, ResTy);
3407 SDValue MN2 = DAG.
getConstant(ElemWidth - 2, dl, ResTy);
3409 SDValue MW = DAG.
getConstant(ElemWidth, dl, ResTy);
3433 unsigned Opc =
Op.getOpcode();
3436 const SDLoc &dl(
Op);
3437 SDValue Op0 =
Op.getOperand(0);
3438 MVT InpTy = ty(Op0);
3471 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3473 SDValue
Zero = getZero(dl, InpTy, DAG);
3481 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3484 SDValue M80 = DAG.
getConstant(1ull << (ElemWidth - 1), dl, InpTy);
3490 SDValue Exp0 = DAG.
getConstant(ElemWidth + ExpBias, dl, InpTy);
3504 unsigned Opc =
Op.getOpcode();
3521 const SDLoc &dl(
Op);
3522 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3531 unsigned Opc =
Op.getConstantOperandVal(2);
3535HexagonTargetLowering::VectorPair
3539 const SDLoc &dl(
Op);
3541 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3542 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3544 return std::make_pair(TV, TV);
3547 for (SDValue
A :
Op.getNode()->ops()) {
3549 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3551 switch (
Op.getOpcode()) {
3552 case ISD::SIGN_EXTEND_INREG:
3553 case HexagonISD::SSAT:
3554 case HexagonISD::USAT:
3555 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3556 std::tie(Lo, Hi) = SplitVTNode(N);
3564 MVT HalfTy = typeSplit(ResTy).first;
3565 SDValue
L = DAG.
getNode(
Op.getOpcode(), dl, HalfTy, OpsL);
3566 SDValue
H = DAG.
getNode(
Op.getOpcode(), dl, HalfTy, OpsH);
3573 unsigned MemOpc = MemN->getOpcode();
3574 EVT MemTy = MemN->getMemoryVT();
3591 EVT LoMemVT, HiMemVT;
3592 bool HiIsEmpty =
false;
3593 std::tie(LoMemVT, HiMemVT) =
3599 const SDLoc &dl(
Op);
3600 SDValue Chain = MemN->getChain();
3601 SDValue Base0 = MemN->getBasePtr();
3605 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3606 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3622 SDValue Load0 = DAG.
getLoad(LoVT, dl, Chain, Base0, MOp0);
3623 SDValue Load1 = DAG.
getLoad(HiVT, dl, Chain, Base1, MOp1);
3634 SDValue Store0 = DAG.
getStore(Chain, dl, Vals.first, Base0, MOp0);
3635 SDValue Store1 = DAG.
getStore(Chain, dl, Vals.second, Base1, MOp1);
3642 assert(MaskN->isUnindexed());
3643 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3650 Masks.first, Thru.first, LoMemVT, MOp0,
3659 Masks.second, Thru.second, HiMemVT, MOp1,
3681 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3687 const SDLoc &dl(
Op);
3689 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3690 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3691 "Not widening loads of i1 yet");
3693 SDValue Chain = LoadN->getChain();
3694 SDValue
Base = LoadN->getBasePtr();
3698 unsigned HwLen = Subtarget.getVectorLength();
3700 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3703 SDValue
Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3711 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3719 const SDLoc &dl(
Op);
3721 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3722 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3723 "Not widening stores of i1 yet");
3725 SDValue Chain = StoreN->getChain();
3726 SDValue
Base = StoreN->getBasePtr();
3729 SDValue
Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3730 MVT ValueTy = ty(
Value);
3732 unsigned HwLen = Subtarget.getVectorLength();
3735 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3737 Len = ty(
Value).getVectorNumElements();
3739 assert(ty(
Value).getVectorNumElements() == HwLen);
3741 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3743 SDValue
Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3746 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3754 const SDLoc &dl(
Op);
3755 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3757 unsigned HwLen = Subtarget.getVectorLength();
3762 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3765 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3766 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3770 {WideOp0, WideOp1,
Op.getOperand(2)});
3772 EVT RetTy = typeLegalize(ty(
Op), DAG);
3774 {SetCC, getZero(dl, MVT::i32, DAG)});
3784 const SDLoc &dl(
Op);
3785 SDValue Inp =
Op.getOperand(0);
3786 MVT InpTy = ty(Inp);
3790 "Expected boolean result type");
3793 unsigned HwLen = Subtarget.getVectorLength();
3798 if (!Subtarget.isHVXVectorType(WideInpTy,
false))
3802 SDValue WideInp = appendUndef(Inp, WideInpTy, DAG);
3809 EVT RetTy = typeLegalize(ResTy, DAG);
3811 {WideTrunc, getZero(dl, MVT::i32, DAG)});
3816 unsigned Opc =
Op.getOpcode();
3817 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3819 return isHvxPairTy(ty(V));
3830 return SplitHvxMemOp(
Op, DAG);
3835 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3836 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3870 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3875 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3876 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3900 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3902 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3911 ty(
Op.getOperand(0)).getScalarType().isFloatingPoint())
3912 return LowerHvxFpSetoeq(
Op, DAG);
3929 case HexagonISD::SMUL_LOHI:
3930 case HexagonISD::UMUL_LOHI:
3931 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3936 return LowerHvxPartialReduceMLA(
Op, DAG);
3938 return LowerHvxVecReduceFMin(
Op, DAG);
3940 return LowerHvxVecReduceFMax(
Op, DAG);
3942 return LowerHvxVecReduceFMinimum(
Op, DAG);
3944 return LowerHvxVecReduceFMaximum(
Op, DAG);
3946 return LowerHvxFMinNum(
Op, DAG);
3948 return LowerHvxFMaxNum(
Op, DAG);
3966 unsigned Opc =
Op.getOpcode();
3968 case HexagonISD::SSAT:
3969 case HexagonISD::USAT:
3985 SDValue Inp =
Op.getOperand(0);
3986 MVT InpTy = ty(Inp);
3991 assert(InpWidth != ResWidth);
3993 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3996 const SDLoc &dl(
Op);
4000 auto repeatOp = [&](
unsigned NewWidth, SDValue Arg) {
4003 case HexagonISD::SSAT:
4004 case HexagonISD::USAT:
4008 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
4015 if (InpWidth < ResWidth) {
4017 while (InpWidth * 2 <= ResWidth)
4018 S = repeatOp(InpWidth *= 2, S);
4022 while (InpWidth / 2 >= ResWidth)
4023 S = repeatOp(InpWidth /= 2, S);
4030 SDValue Inp0 =
Op.getOperand(0);
4031 MVT InpTy = ty(Inp0);
4035 unsigned Opc =
Op.getOpcode();
4037 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
4042 auto [WInpTy, WResTy] =
4043 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
4044 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
4045 SDValue
W = appendUndef(Inp0, WInpTy, DAG);
4053 SDValue
T = ExpandHvxResizeIntoSteps(S, DAG);
4054 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
4055 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
4062 SDValue
T = ExpandHvxResizeIntoSteps(
Op, DAG);
4065 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
4068 return RemoveTLWrapper(
Op, DAG);
4074HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
4076 unsigned Opc =
N->getOpcode();
4079 if (
N->getNumOperands() > 0)
4080 Inp0 =
Op.getOperand(0);
4086 if (Subtarget.isHVXElementType(ty(
Op)) &&
4087 Subtarget.isHVXElementType(ty(Inp0))) {
4088 Results.push_back(CreateTLWrapper(
Op, DAG));
4100 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4101 if (SDValue
T = WidenHvxTruncateToBool(
Op, DAG))
4103 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4104 Subtarget.isHVXElementType(ty(Inp0))) {
4105 Results.push_back(CreateTLWrapper(
Op, DAG));
4109 if (shouldWidenToHvx(ty(Inp0), DAG)) {
4110 if (SDValue
T = WidenHvxSetCC(
Op, DAG))
4116 SDValue
Store = WidenHvxStore(
Op, DAG);
4122 if (isHvxPairTy(ty(
Op))) {
4123 SDValue S = SplitHvxMemOp(
Op, DAG);
4130 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
4131 SDValue S = SplitHvxMemOp(
Op, DAG);
4139 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4140 SDValue
T = EqualizeFpIntConversion(
Op, DAG);
4144 case HexagonISD::SSAT:
4145 case HexagonISD::USAT:
4148 Results.push_back(LegalizeHvxResize(
Op, DAG));
4156HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
4158 unsigned Opc =
N->getOpcode();
4161 if (
N->getNumOperands() > 0)
4162 Inp0 =
Op.getOperand(0);
4168 if (Subtarget.isHVXElementType(ty(
Op)) &&
4169 Subtarget.isHVXElementType(ty(Inp0))) {
4170 Results.push_back(CreateTLWrapper(
Op, DAG));
4177 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4178 if (SDValue
T = WidenHvxTruncateToBool(
Op, DAG))
4180 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4181 Subtarget.isHVXElementType(ty(Inp0))) {
4182 Results.push_back(CreateTLWrapper(
Op, DAG));
4186 if (shouldWidenToHvx(ty(
Op), DAG)) {
4187 if (SDValue
T = WidenHvxSetCC(
Op, DAG))
4192 if (shouldWidenToHvx(ty(
Op), DAG)) {
4193 SDValue
Load = WidenHvxLoad(
Op, DAG);
4201 if (isHvxBoolTy(ty(Inp0))) {
4202 SDValue
C = LowerHvxBitcast(
Op, DAG);
4208 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4209 SDValue
T = EqualizeFpIntConversion(
Op, DAG);
4213 case HexagonISD::SSAT:
4214 case HexagonISD::USAT:
4217 Results.push_back(LegalizeHvxResize(
Op, DAG));
4225HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
4226 DAGCombinerInfo &DCI)
const {
4231 SelectionDAG &DAG = DCI.DAG;
4232 const SDLoc &dl(
Op);
4236 SDValue Cast =
Op.getOperand(0);
4239 EVT TruncTy =
Op.getValueType();
4241 EVT SrcTy = Src.getValueType();
4248 if (2 * CastLen != SrcLen)
4251 SmallVector<int, 128>
Mask(SrcLen);
4252 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
4254 Mask[i + CastLen] = 2 * i + 1;
4258 return opSplit(Deal, dl, DAG).first;
4262HexagonTargetLowering::combineConcatOfShuffles(
SDValue Op,
4271 const SDLoc &dl(
Op);
4272 SDValue
V0 =
Op.getOperand(0);
4273 SDValue
V1 =
Op.getOperand(1);
4280 SetVector<SDValue> Order;
4286 if (Order.
size() > 2)
4291 EVT InpTy =
V0.getValueType();
4295 SmallVector<int, 128> LongMask;
4296 auto AppendToMask = [&](SDValue Shuffle) {
4298 ArrayRef<int>
Mask =
SV->getMask();
4299 SDValue
X = Shuffle.getOperand(0);
4300 SDValue
Y = Shuffle.getOperand(1);
4301 for (
int M : Mask) {
4306 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
4307 if (
static_cast<unsigned>(M) >= InpLen)
4310 int OutOffset = Order[0] == Src ? 0 : InpLen;
4319 SDValue
C1 = Order.
back();
4333HexagonTargetLowering::combineConcatOfScalarPreds(
SDValue Op,
unsigned BitBytes,
4335 const SDLoc &dl(
Op);
4338 MVT InpTy = ty(
Ops[0]);
4341 assert(InpLen <= 8 &&
"Too long for scalar predicate");
4342 assert(ResLen > 8 &&
"Too short for HVX vector predicate");
4344 unsigned Bytes = 8 / InpLen;
4347 if (Bytes <= BitBytes)
4351 unsigned SliceLen = Bytes / BitBytes;
4356 for (
unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4358 Inputs.slice(SliceLen * i, SliceLen));
4365SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4366 SDValue Op, DAGCombinerInfo &DCI)
const {
4370 if (ElemTy != MVT::i1) {
4371 return combineConcatOfShuffles(
Op, DCI.DAG);
4378SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4379 unsigned Opcode,
EVT AccEltType,
unsigned AccNumElements,
EVT InputType,
4382 const auto &Subtarget = DAG.
getSubtarget<HexagonSubtarget>();
4383 if (!Subtarget.useHVXOps())
4389 unsigned NativeRatio;
4390 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4402 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4403 if (RemainingReductionRatio == 1)
4408 InputNumElements / NativeRatio);
4411 return DAG.
getNode(Opcode,
DL, IntermediateType, Zero,
A,
B);
4417 EVT AccType =
Mul.getValueType();
4423 A =
Mul->getOperand(0);
4424 B =
Mul->getOperand(1);
4444 A =
A->getOperand(0);
4445 B =
B->getOperand(0);
4446 if (
A.getValueType() !=
B.getValueType())
4457 if (!Subtarget.useHVXOps())
4460 EVT ScalarType =
N->getValueType(0);
4467 unsigned RemainingReductionRatio;
4469 createExtendingPartialReduceMLA(Opcode, ScalarType, 1,
A.getValueType(),
4470 A,
B, RemainingReductionRatio,
DL, DAG);
4486SDValue HexagonTargetLowering::LowerHvxVecReduceFMinMax(
4489 SDValue Vec =
Op.getOperand(0);
4490 MVT VecTy = ty(Vec);
4491 SDNodeFlags
Flags =
Op->getFlags();
4492 bool ShouldStripNaN = IgnoreNaN && !
Flags.hasNoNaNs();
4495 SDValue OrigVec = Vec;
4496 MVT OrigVecTy = VecTy;
4500 auto ReplaceNaN = [&](SDValue
V, MVT Ty) -> SDValue {
4511 if (isHvxPairTy(VecTy)) {
4512 auto [
Lo,
Hi] = opSplit(Vec,
DL, DAG);
4513 MVT SingleTy = ty(
Lo);
4514 if (ShouldStripNaN) {
4515 Lo = ReplaceNaN(
Lo, SingleTy);
4516 Hi = ReplaceNaN(
Hi, SingleTy);
4518 Vec = DAG.
getNode(PairwiseOpc,
DL, SingleTy,
Lo,
Hi, Flags);
4520 }
else if (ShouldStripNaN) {
4521 Vec = ReplaceNaN(Vec, VecTy);
4528 unsigned HwLen = Subtarget.getVectorLength();
4529 unsigned NumElems = HwLen / ElemBytes;
4532 for (
unsigned Width = NumElems / 2; Width >= 1; Width /= 2) {
4533 SDValue RotAmt = DAG.
getConstant(Width * ElemBytes,
DL, MVT::i32);
4535 Curr = DAG.
getNode(PairwiseOpc,
DL, VecTy, Curr, Rotated, Flags);
4539 MVT ScalarTy =
Op.getSimpleValueType();
4547 if (ShouldStripNaN) {
4556 SDValue IsOrdInt = DAG.
getBitcast(IntTy, IsOrd);
4557 SDValue AnyNonNaN = DAG.
getSetCC(
DL, MVT::i1, IsOrdInt,
4578HexagonTargetLowering::LowerHvxVecReduceFMinimum(
SDValue Op,
4584HexagonTargetLowering::LowerHvxVecReduceFMaximum(
SDValue Op,
4596 auto A =
Op.getOperand(0),
B =
Op.getOperand(1);
4600 if (!
Flags.hasNoNaNs()) {
4623 auto A =
Op.getOperand(0),
B =
Op.getOperand(1);
4627 if (!
Flags.hasNoNaNs()) {
4653HexagonTargetLowering::splitExtendingPartialReduceMLA(
SDNode *
N,
4655 if (!Subtarget.useHVXOps())
4658 SDValue Acc =
N->getOperand(0);
4659 SDValue
A =
N->getOperand(1);
4660 SDValue
B =
N->getOperand(2);
4661 if (
A.getValueType() !=
B.getValueType())
4667 EVT InputType =
A.getValueType();
4672 unsigned RemainingReductionRatio;
4673 SDValue Partial = createExtendingPartialReduceMLA(
4687 DL, AccType, Acc, Partial, One);
4691HexagonTargetLowering::LowerHvxPartialReduceMLA(
SDValue Op,
4693 const SDLoc &
DL(
Op);
4694 SDValue Acc =
Op.getOperand(0);
4695 SDValue
A =
Op.getOperand(1);
4696 SDValue
B =
Op.getOperand(2);
4699 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4703 unsigned AccSubvectorNumElements =
4705 EVT AccSubvectorType =
4708 EVT InputType =
A.getValueType();
4711 unsigned InputSubvectorNumElements =
4714 InputSubvectorNumElements);
4719 for (
unsigned I = 0;
I != SubvectorNum; ++
I) {
4721 I * AccSubvectorNumElements);
4723 I * InputSubvectorNumElements);
4725 I * InputSubvectorNumElements);
4726 SDValue SubvectorMLA = DAG.
getNode(
Op.getOpcode(),
DL, AccSubvectorType,
4727 SubvectorAcc, SubvectorA, SubvectorB);
4767 auto ResTy = ty(
Op);
4768 auto A =
Op.getOperand(0),
B =
Op->getOperand(1);
4769 MVT FloatTy = ty(
A);
4771 bool IsF32 = (ElemTy == MVT::f32);
4773 assert((ElemTy == MVT::f16));
4775 const SDLoc &
DL(
Op);
4776 MVT IntElemTy = IsF32 ? MVT::i32 : MVT::i16;
4777 MVT IntVecTy = tyVector(FloatTy, IntElemTy);
4781 bool NoNaN =
Op->getFlags().hasNoNaNs();
4799 uint64_t AbsMask = IsF32 ? 0x7FFFFFFFull : 0x7FFFull;
4800 uint64_t NaNThresh = IsF32 ? 0x7F800000ull : 0x7C00ull;
4805 SDValue ThreshVec = DAG.
getConstant(NaNThresh,
DL, IntVecTy);
4822HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
4825 SelectionDAG &DAG = DCI.DAG;
4827 unsigned Opc =
Op.getOpcode();
4832 return combineTruncateBeforeLegal(
Op, DCI);
4834 return combineConcatVectorsBeforeLegal(
Op, DCI);
4836 if (DCI.isBeforeLegalizeOps())
4843 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
4844 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
4852 return getZero(dl, ty(
Op), DAG);
4854 case HexagonISD::VINSERTW0:
4855 if (isUndef(
Ops[1]))
4873HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4874 if (Subtarget.isHVXVectorType(Ty,
true))
4876 auto Action = getPreferredHvxVectorAction(Ty);
4878 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4883HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4884 if (Subtarget.isHVXVectorType(Ty,
true))
4886 auto Action = getPreferredHvxVectorAction(Ty);
4888 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4894 if (!Subtarget.useHVXOps())
4898 auto IsHvxTy = [
this](EVT Ty) {
4899 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4901 auto IsHvxOp = [
this](SDValue
Op) {
4902 return Op.getValueType().isSimple() &&
4903 Subtarget.isHVXVectorType(ty(
Op),
true);
4909 auto IsWidenedToHvx = [
this, &DAG](SDValue
Op) {
4910 if (!
Op.getValueType().isSimple())
4913 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4916 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
4917 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 > EnableXQFFastConvert("hexagon-qf-fast-convert", cl::Hidden, cl::init(false), cl::desc("Enable XQF fast conversion routine."))
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.
MachineRegisterInfo & MRI
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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 SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
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...
std::vector< ArgListEntry > ArgListTy
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
int getNumOccurrences() const
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 char Args[]
Key for Kernel::Metadata::mArgs.
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.
@ 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 - Same semantics as the llvm.minnum/maxnum intrinsics.
@ 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 - Same semantics as the llvm.minimum/maximum intrinsics.
@ 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 - Same semantics as the llvm.minimumnum/maximumnum intrinsics.
@ 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,...
LLVM_ABI StringRef getName(ID id)
Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
Flag
These should be considered private to the implementation of the MCInstrDesc class.
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.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
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