21#include "llvm/IR/IntrinsicsHexagon.h"
32 cl::desc(
"Lower threshold (in bytes) for widening to HVX vectors"));
36 cl::desc(
"Enable FP fast conversion routine."));
38static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
39static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
40static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
41static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
50 return std::make_tuple(5, 15, 10);
52 return std::make_tuple(8, 127, 23);
54 return std::make_tuple(11, 1023, 52);
62HexagonTargetLowering::initializeHVXLowering() {
63 if (Subtarget.useHVX64BOps()) {
81 }
else if (Subtarget.useHVX128BOps()) {
91 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
97 if (Subtarget.useHVXV81Ops()) {
105 bool Use64b = Subtarget.useHVX64BOps();
108 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
109 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
110 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
112 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
130 if (Subtarget.useHVX128BOps()) {
140 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
141 Subtarget.useHVXFloatingPoint()) {
143 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
144 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
146 for (MVT
T : FloatV) {
195 if (!Subtarget.useHVXV81Ops())
199 if (Subtarget.useHVXV81Ops()) {
202 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
203 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
204 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
205 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
231 for (MVT
P : FloatW) {
261 if (Subtarget.useHVXQFloatOps()) {
264 }
else if (Subtarget.useHVXIEEEFPOps()) {
270 for (MVT
T : LegalV) {
297 if (
T.getScalarType() != MVT::i32) {
306 if (
T.getScalarType() != MVT::i32) {
334 if (Subtarget.useHVXFloatingPoint()) {
351 for (MVT
T : LegalW) {
406 if (
T.getScalarType() != MVT::i32) {
411 if (Subtarget.useHVXFloatingPoint()) {
458 for (MVT
T : LegalW) {
475 for (MVT
T : LegalV) {
490 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
493 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
498 unsigned HwLen = Subtarget.getVectorLength();
499 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
500 if (ElemTy == MVT::i1)
502 int ElemWidth = ElemTy.getFixedSizeInBits();
503 int MaxElems = (8*HwLen) / ElemWidth;
504 for (
int N = 2;
N < MaxElems;
N *= 2) {
515 if (Subtarget.useHVXFloatingPoint()) {
545 auto HvxType = [=](MVT ScalarT,
unsigned Factor = 1) {
554 typedef std::tuple<MVT, MVT, bool> ReductionSignature;
556 static const std::vector<ReductionSignature> NativeReductions = {
557 {MVT::i32, MVT::i8,
false},
560 for (
const auto &R : NativeReductions) {
562 MVT AccType = std::get<0>(R);
563 MVT InputType = std::get<1>(R);
564 unsigned Factor = std::get<2>(R) ? 2 : 1;
586 for (
unsigned ConcatFactor = 1; ConcatFactor <=
MaxExpandMLA;
588 for (
unsigned ReductionFactor = 1; ReductionFactor <=
MaxExpandMLA;
589 ReductionFactor <<= 1)
590 if (ConcatFactor * ReductionFactor != 1 &&
593 MLAOps, HvxType(AccType, Factor * ConcatFactor),
594 HvxType(InputType, Factor * ConcatFactor * ReductionFactor),
601HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
608 unsigned HwLen = Subtarget.getVectorLength();
611 if (ElemTy == MVT::i1 && VecLen > HwLen)
617 if (ElemTy == MVT::i1) {
632 unsigned HwWidth = 8*HwLen;
633 if (VecWidth > 2*HwWidth)
639 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
648HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
649 unsigned Opc =
Op.getOpcode();
651 case HexagonISD::SMUL_LOHI:
652 case HexagonISD::UMUL_LOHI:
653 case HexagonISD::USMUL_LOHI:
669HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
670 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
674 Tys.second.getVectorNumElements());
677HexagonTargetLowering::TypePair
678HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
681 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
683 return { HalfTy, HalfTy };
687HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
694HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
701HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
710HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
716HexagonTargetLowering::VectorPair
717HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
719 TypePair Tys = typeSplit(ty(Vec));
722 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
726HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
727 return Subtarget.isHVXVectorType(Ty) &&
732HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
733 return Subtarget.isHVXVectorType(Ty) &&
738HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
739 return Subtarget.isHVXVectorType(Ty,
true) &&
743bool HexagonTargetLowering::allowsHvxMemoryAccess(
751 if (!Subtarget.isHVXVectorType(VecTy,
false))
758bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
760 if (!Subtarget.isHVXVectorType(VecTy))
768void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
770 unsigned Opc =
MI.getOpcode();
771 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
772 MachineBasicBlock &MB = *
MI.getParent();
779 case Hexagon::PS_vsplatib:
780 if (Subtarget.useHVXV62Ops()) {
785 .
add(
MI.getOperand(1));
787 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
793 const MachineOperand &InpOp =
MI.getOperand(1);
795 uint32_t
V = InpOp.
getImm() & 0xFF;
797 .
addImm(V << 24 | V << 16 | V << 8 | V);
803 case Hexagon::PS_vsplatrb:
804 if (Subtarget.useHVXV62Ops()) {
807 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
808 .
add(
MI.getOperand(1));
811 const MachineOperand &InpOp =
MI.getOperand(1);
812 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
815 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
820 case Hexagon::PS_vsplatih:
821 if (Subtarget.useHVXV62Ops()) {
826 .
add(
MI.getOperand(1));
828 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
834 const MachineOperand &InpOp =
MI.getOperand(1);
836 uint32_t
V = InpOp.
getImm() & 0xFFFF;
844 case Hexagon::PS_vsplatrh:
845 if (Subtarget.useHVXV62Ops()) {
848 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
849 .
add(
MI.getOperand(1));
854 const MachineOperand &InpOp =
MI.getOperand(1);
855 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
863 case Hexagon::PS_vsplatiw:
864 case Hexagon::PS_vsplatrw:
865 if (
Opc == Hexagon::PS_vsplatiw) {
869 .
add(
MI.getOperand(1));
870 MI.getOperand(1).ChangeToRegister(SplatV,
false);
873 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
879HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
889 const SDLoc &dl(ElemIdx);
895HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
898 assert(ElemWidth >= 8 && ElemWidth <= 32);
902 if (ty(Idx) != MVT::i32)
904 const SDLoc &dl(Idx);
911HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
918 if (ElemTy == MVT::i8)
922 MVT ResTy = tyVector(OpTy, MVT::i8);
925 SmallVector<int,128> ByteMask;
928 for (
unsigned I = 0;
I != ElemSize; ++
I)
931 int NewM =
M*ElemSize;
932 for (
unsigned I = 0;
I != ElemSize; ++
I)
938 opCastElem(Op1, MVT::i8, DAG), ByteMask);
945 unsigned VecLen =
Values.size();
949 unsigned HwLen = Subtarget.getVectorLength();
951 unsigned ElemSize = ElemWidth / 8;
952 assert(ElemSize*VecLen == HwLen);
956 !(Subtarget.useHVXFloatingPoint() &&
958 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
959 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
961 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
962 SDValue W = buildVector32(
Values.slice(i, OpsPerWord), dl, PartVT, DAG);
970 unsigned NumValues =
Values.size();
973 for (
unsigned i = 0; i != NumValues; ++i) {
977 if (!SplatV.getNode())
979 else if (SplatV !=
Values[i])
987 unsigned NumWords = Words.
size();
989 bool IsSplat =
isSplat(Words, SplatV);
990 if (IsSplat && isUndef(SplatV))
995 return getZero(dl, VecTy, DAG);
1004 bool AllConst = getBuildVectorConstInts(
Values, VecTy, DAG, Consts);
1007 (Constant**)Consts.end());
1025 SmallVectorImpl<int> &SrcIdx) {
1029 SrcIdx.push_back(-1);
1042 int I =
C->getSExtValue();
1043 assert(
I >= 0 &&
"Negative element index");
1044 SrcIdx.push_back(
I);
1050 SmallVector<int,128> ExtIdx;
1052 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
1053 MVT ExtTy = ty(ExtVec);
1055 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
1059 SmallVector<int,128>
Mask;
1060 BitVector
Used(ExtLen);
1062 for (
int M : ExtIdx) {
1072 for (
unsigned I = 0;
I != ExtLen; ++
I) {
1073 if (
Mask.size() == ExtLen)
1081 return ExtLen == VecLen ? S : LoHalf(S, DAG);
1089 assert(4*Words.
size() == Subtarget.getVectorLength());
1092 for (
unsigned i = 0; i != NumWords; ++i) {
1094 if (Words[i].isUndef())
1096 for (
unsigned j = i;
j != NumWords; ++
j)
1097 if (Words[i] == Words[j])
1100 if (VecHist[i] > VecHist[n])
1104 SDValue HalfV = getZero(dl, VecTy, DAG);
1105 if (VecHist[n] > 1) {
1113 HalfV = DAG.
getNode(HexagonISD::VALIGN, dl, VecTy,
1114 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1126 for (
unsigned i = 0; i != NumWords/2; ++i) {
1128 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1131 N = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1132 {HalfV0, Words[i]});
1135 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1138 M = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1139 {HalfV1, Words[i+NumWords/2]});
1162HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1163 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1164 MVT PredTy = ty(PredV);
1165 unsigned HwLen = Subtarget.getVectorLength();
1168 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1178 SmallVector<int,128>
Mask(HwLen);
1183 for (
unsigned i = 0; i != HwLen; ++i) {
1184 unsigned Num = i % Scale;
1185 unsigned Off = i / Scale;
1194 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1196 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1203 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1215 while (Bytes < BitBytes) {
1217 Words[IdxW].
clear();
1220 for (
const SDValue &W : Words[IdxW ^ 1]) {
1221 SDValue T = expandPredicate(W, dl, DAG);
1226 for (
const SDValue &W : Words[IdxW ^ 1]) {
1234 assert(Bytes == BitBytes);
1235 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1237 for (
const SDValue &W : Words[IdxW]) {
1239 Vec = DAG.
getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1251 unsigned VecLen =
Values.size();
1252 unsigned HwLen = Subtarget.getVectorLength();
1253 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1255 bool AllT =
true, AllF =
true;
1259 return !
N->isZero();
1268 if (VecLen <= HwLen) {
1272 assert(HwLen % VecLen == 0);
1273 unsigned BitBytes = HwLen / VecLen;
1280 for (
unsigned B = 0;
B != BitBytes; ++
B)
1287 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1290 for (;
B != 8; ++
B) {
1309 return DAG.
getNode(HexagonISD::QTRUE, dl, VecTy);
1311 return DAG.
getNode(HexagonISD::QFALSE, dl, VecTy);
1314 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1319HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1324 assert(ElemWidth >= 8 && ElemWidth <= 32);
1327 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1328 SDValue ExWord = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1330 if (ElemTy == MVT::i32)
1336 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1339 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1343HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1346 assert(ResTy == MVT::i1);
1348 unsigned HwLen = Subtarget.getVectorLength();
1352 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1356 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1358 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1362HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1367 assert(ElemWidth >= 8 && ElemWidth <= 32);
1372 MVT VecTy = ty(VecV);
1373 unsigned HwLen = Subtarget.getVectorLength();
1378 SDValue InsV = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1385 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1386 if (ElemTy == MVT::i32)
1387 return InsertWord(VecV, ValV, ByteIdx);
1393 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1398 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1399 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1401 ValV, SubIdx, dl, ElemTy, DAG);
1404 return InsertWord(VecV, Ins, ByteIdx);
1408HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1410 unsigned HwLen = Subtarget.getVectorLength();
1414 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1419 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1424HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1426 MVT VecTy = ty(VecV);
1427 unsigned HwLen = Subtarget.getVectorLength();
1435 if (isHvxPairTy(VecTy)) {
1436 unsigned SubIdx = Hexagon::vsub_lo;
1437 if (Idx * ElemWidth >= 8 * HwLen) {
1438 SubIdx = Hexagon::vsub_hi;
1442 VecTy = typeSplit(VecTy).first;
1452 MVT WordTy = tyVector(VecTy, MVT::i32);
1454 unsigned WordIdx = (Idx*ElemWidth) / 32;
1457 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1462 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1463 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1468HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1470 MVT VecTy = ty(VecV);
1471 unsigned HwLen = Subtarget.getVectorLength();
1479 unsigned Offset = Idx * BitBytes;
1481 SmallVector<int,128>
Mask;
1483 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1490 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1491 for (
unsigned j = 0;
j != Rep; ++
j)
1508 unsigned Rep = 8 / ResLen;
1511 for (
unsigned r = 0; r != HwLen / 8; ++r) {
1513 for (
unsigned i = 0; i != ResLen; ++i) {
1514 for (
unsigned j = 0;
j != Rep; ++
j)
1526 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1527 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1532HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1534 MVT VecTy = ty(VecV);
1535 MVT SubTy = ty(SubV);
1536 unsigned HwLen = Subtarget.getVectorLength();
1540 bool IsPair = isHvxPairTy(VecTy);
1548 V0 = LoHalf(VecV, DAG);
1549 V1 = HiHalf(VecV, DAG);
1554 if (isHvxSingleTy(SubTy)) {
1556 unsigned Idx = CN->getZExtValue();
1558 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1581 if (!IdxN || !IdxN->isZero()) {
1589 unsigned RolBase = HwLen;
1592 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1597 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1600 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1604 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1619HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1621 MVT VecTy = ty(VecV);
1622 MVT SubTy = ty(SubV);
1623 assert(Subtarget.isHVXVectorType(VecTy,
true));
1628 unsigned HwLen = Subtarget.getVectorLength();
1629 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1632 unsigned BitBytes = HwLen / VecLen;
1633 unsigned BlockLen = HwLen / Scale;
1637 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1641 if (!IdxN || !IdxN->isZero()) {
1650 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1652 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1654 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1656 if (!IdxN || !IdxN->isZero()) {
1665HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1670 assert(Subtarget.isHVXVectorType(ResTy));
1677 SDValue False = getZero(dl, ResTy, DAG);
1678 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1682HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1690 unsigned HwLen = Subtarget.getVectorLength();
1692 MVT PredTy = ty(VecQ);
1694 assert(HwLen % PredLen == 0);
1701 for (
unsigned i = 0; i != HwLen/8; ++i) {
1702 for (
unsigned j = 0;
j != 8; ++
j)
1703 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1716 getZero(dl, VecTy, DAG));
1722 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1724 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1731 SmallVector<int,128>
Mask;
1732 for (
unsigned i = 0; i != HwLen; ++i)
1733 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1743 MVT InpTy = ty(VecV);
1751 return InpWidth < ResWidth
1759 if (InpWidth < ResWidth) {
1761 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1763 unsigned NarOpc =
Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1769HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1773 const SDLoc &dl(Vec);
1782 const SDLoc &dl(
Op);
1787 for (
unsigned i = 0; i !=
Size; ++i)
1788 Ops.push_back(
Op.getOperand(i));
1791 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1799 for (
unsigned i = 0; i !=
Size; i++)
1810 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1812 MVT SingleTy = typeSplit(VecTy).first;
1813 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1814 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1818 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1824 const SDLoc &dl(
Op);
1826 MVT ArgTy = ty(
Op.getOperand(0));
1828 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1846 const SDLoc &dl(
Op);
1863 MVT NTy = typeLegalize(Ty, DAG);
1867 V.getOperand(0),
V.getOperand(1)),
1872 switch (
V.getOpcode()) {
1880 V =
V.getOperand(0);
1891 unsigned HwLen = Subtarget.getVectorLength();
1898 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1900 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, Op0,
Op.getOperand(1));
1906 MVT HalfTy = typeSplit(VecTy).first;
1908 Ops.take_front(NumOp/2));
1910 Ops.take_back(NumOp/2));
1911 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, V0,
V1);
1921 SDValue Combined = combineConcatOfScalarPreds(
Op, BitBytes, DAG);
1924 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1928 unsigned InpLen = ty(Combined.
getOperand(0)).getVectorNumElements();
1931 SDValue Res = getZero(dl, ByteTy, DAG);
1932 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1945 const SDLoc &dl(
Op);
1947 if (ElemTy == MVT::i1)
1948 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1950 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1956 const SDLoc &dl(
Op);
1962 if (ElemTy == MVT::i1)
1963 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1965 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1967 tyVector(VecTy, MVT::i16),
1968 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1970 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1973 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1980 MVT SrcTy = ty(SrcV);
1986 const SDLoc &dl(
Op);
1989 if (ElemTy == MVT::i1)
1990 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1992 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
2003 const SDLoc &dl(
Op);
2004 MVT VecTy = ty(VecV);
2006 if (ElemTy == MVT::i1)
2007 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
2009 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
2021 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2022 return LowerHvxSignExt(
Op, DAG);
2031 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2032 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
2041 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2042 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
2050 const SDLoc &dl(
Op);
2053 assert(ResTy == ty(InpV));
2078 const SDLoc &dl(
Op);
2085 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2086 unsigned Opc =
Op.getOpcode();
2090 return DAG.
getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2092 return DAG.
getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2102 const SDLoc &dl(
Op);
2103 unsigned Opc =
Op.getOpcode();
2108 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2115 bool SignedVu =
Opc == HexagonISD::SMUL_LOHI;
2116 bool SignedVv =
Opc == HexagonISD::SMUL_LOHI ||
Opc == HexagonISD::USMUL_LOHI;
2120 if (Subtarget.useHVXV62Ops())
2121 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2123 if (
Opc == HexagonISD::SMUL_LOHI) {
2126 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2127 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2133 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2140 MVT ValTy = ty(Val);
2141 const SDLoc &dl(
Op);
2144 unsigned HwLen = Subtarget.getVectorLength();
2152 if (PredLen < HwLen) {
2155 if (HwLen > PredLen * 2) {
2156 assert(HwLen == PredLen * 4);
2158 Val = getInstr(Hexagon::V6_vdealh, dl, ByteTy, Val, DAG);
2160 if (HwLen > PredLen) {
2161 assert(HwLen == PredLen * 2);
2162 Val = getInstr(Hexagon::V6_vdealb, dl, ByteTy, Val, DAG);
2167 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2182 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2184 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2189 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2190 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2203 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2204 assert(Val32.getValueType().getSizeInBits() == 32 &&
2205 "Input must be 32 bits");
2209 for (
unsigned i = 0; i < 32; ++i)
2217 if (ResTy == MVT::v32i1 &&
2218 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2219 Subtarget.useHVX128BOps()) {
2221 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2223 return bitcastI32ToV32I1(Val32);
2226 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2244 unsigned HwLen = Subtarget.getVectorLength();
2256 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2260 for (
unsigned J = 0; J != 8; ++J) {
2268 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2280 const SDLoc &dl(
Op);
2283 MVT ValTy = ty(Val);
2286 if (!isHvxBoolTy(ValTy))
2293 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2297 unsigned HwLen = Subtarget.getVectorLength();
2301 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2305 for (
unsigned i = 0; i != NumBits / 32; ++i) {
2316 return DAG.
getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2319 if (NumBits == 64) {
2320 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2324 if (NumBits == 128) {
2325 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2326 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2342 const SDLoc &dl(
Op);
2347 if (!isHvxBoolTy(ResTy))
2353 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2361 if (NumBits == 32) {
2369 if (NumBits == 64) {
2377 if (NumBits == 128) {
2413 const SDLoc &dl(
Op);
2414 unsigned HwLen = Subtarget.getVectorLength();
2416 assert(HwLen % VecLen == 0);
2417 unsigned ElemSize = HwLen / VecLen;
2429 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2435HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2437 unsigned Opc =
Op.getOpcode();
2449 const SDLoc &dl(
Op);
2455 bool UseShifts = ElemTy != MVT::i8;
2456 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2459 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2467 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2473 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2475 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2483 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2485 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2492 const SDLoc &dl(
Op);
2493 unsigned IntNo =
Op.getConstantOperandVal(0);
2501 case Intrinsic::hexagon_V6_pred_typecast:
2502 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2503 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2504 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2511 case Intrinsic::hexagon_V6_vmpyss_parts:
2512 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2513 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2515 case Intrinsic::hexagon_V6_vmpyuu_parts:
2516 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2517 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2519 case Intrinsic::hexagon_V6_vmpyus_parts:
2520 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2521 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2531 const SDLoc &dl(
Op);
2532 unsigned HwLen = Subtarget.getVectorLength();
2536 SDValue Chain = MaskN->getChain();
2540 unsigned Opc =
Op->getOpcode();
2557 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2561 if (MaskN->getAlign().value() % HwLen == 0) {
2570 SDValue Z = getZero(dl, ty(V), DAG);
2574 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2575 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2576 return std::make_pair(LoV, HiV);
2582 VectorPair Tmp = StoreAlign(MaskV,
Base);
2585 VectorPair ValueU = StoreAlign(
Value,
Base);
2589 getInstr(StoreOpc, dl, MVT::Other,
2590 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2601 uint64_t StoreMemSize = MaskN->getMemoryVT().getStoreSize().getFixedValue();
2602 if (StoreMemSize <= MaskN->
getAlign().value())
2606 getInstr(StoreOpc, dl, MVT::Other,
2607 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2616 assert(Subtarget.useHVXQFloatOps());
2621 MVT ArgTy = ty(
Op.getOperand(0));
2622 const SDLoc &dl(
Op);
2624 if (ArgTy == MVT::v64bf16) {
2625 MVT HalfTy = typeSplit(VecTy).first;
2628 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2633 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2634 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2636 {VecPair.second, VecPair.first,
2642 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2651 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2653 MVT HalfTy = typeSplit(VecTy).first;
2654 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2656 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2658 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2661 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2674 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2677 if (Subtarget.useHVXIEEEFPOps()) {
2679 if (FpTy == MVT::f16) {
2681 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2683 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2689 return EqualizeFpIntConversion(
Op, DAG);
2691 return ExpandHvxFpToInt(
Op, DAG);
2707 MVT ResTy = ty(PredOp);
2708 const SDLoc &dl(PredOp);
2711 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2712 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2714 SDNode *PredTransfer =
2717 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2720 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2725 SDNode *IndexShift =
2731 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2756 MVT ResTy = ty(PredOp);
2757 const SDLoc &dl(PredOp);
2767 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2768 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2778 SDNode *PredTransfer =
2782 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2789 SDNode *IndexShift_hi =
2792 SDNode *IndexShift_lo =
2796 SDNode *MaskOff_hi =
2799 SDNode *MaskOff_lo =
2822 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2823 return LowerHvxPred32ToFp(
Op, DAG);
2824 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2825 return LowerHvxPred64ToFp(
Op, DAG);
2828 if (Subtarget.useHVXIEEEFPOps()) {
2830 if (FpTy == MVT::f16) {
2832 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2834 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2840 return EqualizeFpIntConversion(
Op, DAG);
2842 return ExpandHvxIntToFp(
Op, DAG);
2845HexagonTargetLowering::TypePair
2846HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2857 unsigned MaxWidth = std::max(Width0, Width1);
2859 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2866 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2867 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2871 return {WideETy0, WideETy1};
2882HexagonTargetLowering::TypePair
2883HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2893 unsigned MaxLen = std::max(Len0, Len1);
2906HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2907 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2916HexagonTargetLowering::VectorPair
2947HexagonTargetLowering::VectorPair
2948HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2953 const SDLoc &dl(Val);
2954 MVT ValTy = ty(Val);
2968 MVT IntTy = tyVector(ValTy, ElemTy);
2980 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2999 MVT
PairTy = typeJoin({VecTy, VecTy});
3025 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
3027 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
3035 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
3040 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3041 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
3042 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
3053HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
3054 bool SignedB,
const SDLoc &dl,
3057 MVT
PairTy = typeJoin({VecTy, VecTy});
3062 if (SignedA && !SignedB) {
3078 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3079 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
3080 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
3089 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3092 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
3096 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3097 {HiHalf(P2, DAG), T3,
S16}, DAG);
3100 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3101 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
3105 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
3112 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
3113 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
3114 }
else if (SignedB) {
3120 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
3122 assert(!SignedA && !SignedB);
3129HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
3134 MVT
PairTy = typeJoin({VecTy, VecTy});
3137 if (SignedA && !SignedB) {
3146 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
3151 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
3163 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
3164 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
3165 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
3166 }
else if (!SignedA) {
3176 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
3194 unsigned Opc =
Op.getOpcode();
3199 MVT InpTy = ty(Inp);
3205 const SDLoc &dl(
Op);
3208 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3217 unsigned Opc =
Op.getOpcode();
3220 const SDLoc &dl(
Op);
3222 MVT InpTy = ty(Op0);
3235 if (InpTy == MVT::v64f16) {
3236 if (Subtarget.useHVXV81Ops()) {
3239 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3243 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3248 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3328 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3329 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3372 unsigned Opc =
Op.getOpcode();
3375 const SDLoc &dl(
Op);
3377 MVT InpTy = ty(Op0);
3410 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3420 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3443 unsigned Opc =
Op.getOpcode();
3460 const SDLoc &dl(
Op);
3461 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3470 unsigned Opc =
Op.getConstantOperandVal(2);
3474HexagonTargetLowering::VectorPair
3478 const SDLoc &dl(
Op);
3480 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3481 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3483 return std::make_pair(TV, TV);
3488 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3490 switch (
Op.getOpcode()) {
3491 case ISD::SIGN_EXTEND_INREG:
3492 case HexagonISD::SSAT:
3493 case HexagonISD::USAT:
3494 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3495 std::tie(Lo, Hi) = SplitVTNode(N);
3503 MVT HalfTy = typeSplit(ResTy).first;
3512 unsigned MemOpc = MemN->getOpcode();
3513 EVT MemTy = MemN->getMemoryVT();
3530 EVT LoMemVT, HiMemVT;
3531 bool HiIsEmpty =
false;
3532 std::tie(LoMemVT, HiMemVT) =
3538 const SDLoc &dl(
Op);
3539 SDValue Chain = MemN->getChain();
3540 SDValue Base0 = MemN->getBasePtr();
3544 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3545 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3581 assert(MaskN->isUnindexed());
3582 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3589 Masks.first, Thru.first, LoMemVT, MOp0,
3598 Masks.second, Thru.second, HiMemVT, MOp1,
3620 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3626 const SDLoc &dl(
Op);
3628 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3629 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3630 "Not widening loads of i1 yet");
3632 SDValue Chain = LoadN->getChain();
3637 unsigned HwLen = Subtarget.getVectorLength();
3639 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3642 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3650 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3658 const SDLoc &dl(
Op);
3660 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3661 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3662 "Not widening stores of i1 yet");
3664 SDValue Chain = StoreN->getChain();
3668 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3669 MVT ValueTy = ty(
Value);
3671 unsigned HwLen = Subtarget.getVectorLength();
3674 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3676 Len = ty(
Value).getVectorNumElements();
3678 assert(ty(
Value).getVectorNumElements() == HwLen);
3680 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3682 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3685 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3693 const SDLoc &dl(
Op);
3694 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3696 unsigned HwLen = Subtarget.getVectorLength();
3701 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3704 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3705 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3709 {WideOp0, WideOp1,
Op.getOperand(2)});
3711 EVT RetTy = typeLegalize(ty(
Op), DAG);
3713 {SetCC, getZero(dl, MVT::i32, DAG)});
3723 const SDLoc &dl(
Op);
3725 MVT InpTy = ty(Inp);
3729 "Expected boolean result type");
3732 unsigned HwLen = Subtarget.getVectorLength();
3737 if (!Subtarget.isHVXVectorType(WideInpTy,
false))
3741 SDValue WideInp = appendUndef(Inp, WideInpTy, DAG);
3748 EVT RetTy = typeLegalize(ResTy, DAG);
3750 {WideTrunc, getZero(dl, MVT::i32, DAG)});
3755 unsigned Opc =
Op.getOpcode();
3756 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3758 return isHvxPairTy(ty(V));
3769 return SplitHvxMemOp(
Op, DAG);
3774 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3775 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3809 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3814 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3815 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3839 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3841 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3850 ty(
Op.getOperand(0)).getScalarType().isFloatingPoint())
3851 return LowerHvxFpSetoeq(
Op, DAG);
3868 case HexagonISD::SMUL_LOHI:
3869 case HexagonISD::UMUL_LOHI:
3870 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3875 return LowerHvxPartialReduceMLA(
Op, DAG);
3877 return LowerHvxVecReduceFMin(
Op, DAG);
3879 return LowerHvxVecReduceFMax(
Op, DAG);
3881 return LowerHvxVecReduceFMinimum(
Op, DAG);
3883 return LowerHvxVecReduceFMaximum(
Op, DAG);
3885 return LowerHvxFMinNum(
Op, DAG);
3887 return LowerHvxFMaxNum(
Op, DAG);
3905 unsigned Opc =
Op.getOpcode();
3907 case HexagonISD::SSAT:
3908 case HexagonISD::USAT:
3925 MVT InpTy = ty(Inp);
3930 assert(InpWidth != ResWidth);
3932 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3935 const SDLoc &dl(
Op);
3939 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3942 case HexagonISD::SSAT:
3943 case HexagonISD::USAT:
3947 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3954 if (InpWidth < ResWidth) {
3956 while (InpWidth * 2 <= ResWidth)
3957 S = repeatOp(InpWidth *= 2, S);
3961 while (InpWidth / 2 >= ResWidth)
3962 S = repeatOp(InpWidth /= 2, S);
3970 MVT InpTy = ty(Inp0);
3974 unsigned Opc =
Op.getOpcode();
3976 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3981 auto [WInpTy, WResTy] =
3982 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3983 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3984 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3992 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3993 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3994 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
4001 SDValue T = ExpandHvxResizeIntoSteps(
Op, DAG);
4004 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
4007 return RemoveTLWrapper(
Op, DAG);
4013HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
4015 unsigned Opc =
N->getOpcode();
4018 if (
N->getNumOperands() > 0)
4019 Inp0 =
Op.getOperand(0);
4025 if (Subtarget.isHVXElementType(ty(
Op)) &&
4026 Subtarget.isHVXElementType(ty(Inp0))) {
4027 Results.push_back(CreateTLWrapper(
Op, DAG));
4039 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4040 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
4042 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4043 Subtarget.isHVXElementType(ty(Inp0))) {
4044 Results.push_back(CreateTLWrapper(
Op, DAG));
4048 if (shouldWidenToHvx(ty(Inp0), DAG)) {
4061 if (isHvxPairTy(ty(
Op))) {
4069 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
4078 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4079 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4083 case HexagonISD::SSAT:
4084 case HexagonISD::USAT:
4087 Results.push_back(LegalizeHvxResize(
Op, DAG));
4095HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
4097 unsigned Opc =
N->getOpcode();
4100 if (
N->getNumOperands() > 0)
4101 Inp0 =
Op.getOperand(0);
4107 if (Subtarget.isHVXElementType(ty(
Op)) &&
4108 Subtarget.isHVXElementType(ty(Inp0))) {
4109 Results.push_back(CreateTLWrapper(
Op, DAG));
4116 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4117 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
4119 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4120 Subtarget.isHVXElementType(ty(Inp0))) {
4121 Results.push_back(CreateTLWrapper(
Op, DAG));
4125 if (shouldWidenToHvx(ty(
Op), DAG)) {
4131 if (shouldWidenToHvx(ty(
Op), DAG)) {
4140 if (isHvxBoolTy(ty(Inp0))) {
4147 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4148 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4152 case HexagonISD::SSAT:
4153 case HexagonISD::USAT:
4156 Results.push_back(LegalizeHvxResize(
Op, DAG));
4164HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
4165 DAGCombinerInfo &DCI)
const {
4170 SelectionDAG &DAG = DCI.DAG;
4171 const SDLoc &dl(
Op);
4178 EVT TruncTy =
Op.getValueType();
4180 EVT SrcTy = Src.getValueType();
4187 if (2 * CastLen != SrcLen)
4190 SmallVector<int, 128>
Mask(SrcLen);
4191 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
4193 Mask[i + CastLen] = 2 * i + 1;
4197 return opSplit(Deal, dl, DAG).first;
4201HexagonTargetLowering::combineConcatOfShuffles(
SDValue Op,
4210 const SDLoc &dl(
Op);
4219 SetVector<SDValue> Order;
4225 if (Order.
size() > 2)
4230 EVT InpTy =
V0.getValueType();
4234 SmallVector<int, 128> LongMask;
4235 auto AppendToMask = [&](
SDValue Shuffle) {
4237 ArrayRef<int>
Mask =
SV->getMask();
4240 for (
int M : Mask) {
4245 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
4246 if (
static_cast<unsigned>(M) >= InpLen)
4249 int OutOffset = Order[0] == Src ? 0 : InpLen;
4272HexagonTargetLowering::combineConcatOfScalarPreds(
SDValue Op,
unsigned BitBytes,
4274 const SDLoc &dl(
Op);
4277 MVT InpTy = ty(
Ops[0]);
4280 assert(InpLen <= 8 &&
"Too long for scalar predicate");
4281 assert(ResLen > 8 &&
"Too short for HVX vector predicate");
4283 unsigned Bytes = 8 / InpLen;
4286 if (Bytes <= BitBytes)
4290 unsigned SliceLen = Bytes / BitBytes;
4295 for (
unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4297 Inputs.slice(SliceLen * i, SliceLen));
4304SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4305 SDValue Op, DAGCombinerInfo &DCI)
const {
4309 if (ElemTy != MVT::i1) {
4310 return combineConcatOfShuffles(
Op, DCI.DAG);
4317SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4318 unsigned Opcode,
EVT AccEltType,
unsigned AccNumElements,
EVT InputType,
4321 const auto &Subtarget = DAG.
getSubtarget<HexagonSubtarget>();
4322 if (!Subtarget.useHVXOps())
4328 unsigned NativeRatio;
4329 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4341 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4342 if (RemainingReductionRatio == 1)
4347 InputNumElements / NativeRatio);
4350 return DAG.
getNode(Opcode,
DL, IntermediateType, Zero,
A,
B);
4356 EVT AccType =
Mul.getValueType();
4362 A =
Mul->getOperand(0);
4363 B =
Mul->getOperand(1);
4383 A =
A->getOperand(0);
4384 B =
B->getOperand(0);
4385 if (
A.getValueType() !=
B.getValueType())
4396 if (!Subtarget.useHVXOps())
4399 EVT ScalarType =
N->getValueType(0);
4406 unsigned RemainingReductionRatio;
4408 createExtendingPartialReduceMLA(Opcode, ScalarType, 1,
A.getValueType(),
4409 A,
B, RemainingReductionRatio,
DL, DAG);
4425SDValue HexagonTargetLowering::LowerHvxVecReduceFMinMax(
4429 MVT VecTy = ty(Vec);
4430 SDNodeFlags
Flags =
Op->getFlags();
4431 bool ShouldStripNaN = IgnoreNaN && !
Flags.hasNoNaNs();
4435 MVT OrigVecTy = VecTy;
4450 if (isHvxPairTy(VecTy)) {
4451 auto [
Lo,
Hi] = opSplit(Vec,
DL, DAG);
4452 MVT SingleTy = ty(
Lo);
4453 if (ShouldStripNaN) {
4454 Lo = ReplaceNaN(
Lo, SingleTy);
4455 Hi = ReplaceNaN(
Hi, SingleTy);
4457 Vec = DAG.
getNode(PairwiseOpc,
DL, SingleTy,
Lo,
Hi, Flags);
4459 }
else if (ShouldStripNaN) {
4460 Vec = ReplaceNaN(Vec, VecTy);
4467 unsigned HwLen = Subtarget.getVectorLength();
4468 unsigned NumElems = HwLen / ElemBytes;
4471 for (
unsigned Width = NumElems / 2; Width >= 1; Width /= 2) {
4474 Curr = DAG.
getNode(PairwiseOpc,
DL, VecTy, Curr, Rotated, Flags);
4478 MVT ScalarTy =
Op.getSimpleValueType();
4486 if (ShouldStripNaN) {
4517HexagonTargetLowering::LowerHvxVecReduceFMinimum(
SDValue Op,
4523HexagonTargetLowering::LowerHvxVecReduceFMaximum(
SDValue Op,
4535 auto A =
Op.getOperand(0),
B =
Op.getOperand(1);
4539 if (!
Flags.hasNoNaNs()) {
4562 auto A =
Op.getOperand(0),
B =
Op.getOperand(1);
4566 if (!
Flags.hasNoNaNs()) {
4592HexagonTargetLowering::splitExtendingPartialReduceMLA(
SDNode *
N,
4594 if (!Subtarget.useHVXOps())
4600 if (
A.getValueType() !=
B.getValueType())
4606 EVT InputType =
A.getValueType();
4611 unsigned RemainingReductionRatio;
4612 SDValue Partial = createExtendingPartialReduceMLA(
4626 DL, AccType, Acc, Partial, One);
4630HexagonTargetLowering::LowerHvxPartialReduceMLA(
SDValue Op,
4632 const SDLoc &
DL(
Op);
4638 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4642 unsigned AccSubvectorNumElements =
4644 EVT AccSubvectorType =
4647 EVT InputType =
A.getValueType();
4650 unsigned InputSubvectorNumElements =
4653 InputSubvectorNumElements);
4658 for (
unsigned I = 0;
I != SubvectorNum; ++
I) {
4660 I * AccSubvectorNumElements);
4662 I * InputSubvectorNumElements);
4664 I * InputSubvectorNumElements);
4666 SubvectorAcc, SubvectorA, SubvectorB);
4706 auto ResTy = ty(
Op);
4707 auto A =
Op.getOperand(0),
B =
Op->getOperand(1);
4708 MVT FloatTy = ty(
A);
4710 bool IsF32 = (ElemTy == MVT::f32);
4712 assert((ElemTy == MVT::f16));
4714 const SDLoc &
DL(
Op);
4715 MVT IntElemTy = IsF32 ? MVT::i32 : MVT::i16;
4716 MVT IntVecTy = tyVector(FloatTy, IntElemTy);
4720 bool NoNaN =
Op->getFlags().hasNoNaNs();
4738 uint64_t AbsMask = IsF32 ? 0x7FFFFFFFull : 0x7FFFull;
4739 uint64_t NaNThresh = IsF32 ? 0x7F800000ull : 0x7C00ull;
4761HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
4764 SelectionDAG &DAG = DCI.DAG;
4766 unsigned Opc =
Op.getOpcode();
4771 return combineTruncateBeforeLegal(
Op, DCI);
4773 return combineConcatVectorsBeforeLegal(
Op, DCI);
4775 if (DCI.isBeforeLegalizeOps())
4782 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
4783 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
4791 return getZero(dl, ty(
Op), DAG);
4793 case HexagonISD::VINSERTW0:
4794 if (isUndef(
Ops[1]))
4812HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4813 if (Subtarget.isHVXVectorType(Ty,
true))
4815 auto Action = getPreferredHvxVectorAction(Ty);
4817 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4822HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4823 if (Subtarget.isHVXVectorType(Ty,
true))
4825 auto Action = getPreferredHvxVectorAction(Ty);
4827 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4833 if (!Subtarget.useHVXOps())
4837 auto IsHvxTy = [
this](EVT Ty) {
4838 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4841 return Op.getValueType().isSimple() &&
4842 Subtarget.isHVXVectorType(ty(
Op),
true);
4848 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
4849 if (!
Op.getValueType().isSimple())
4852 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4855 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const unsigned MaxExpandMLA
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static bool DetectExtendingMultiply(const SDValue &N, EVT ScalarType, unsigned &Opcode, SDValue &A, SDValue &B)
static cl::opt< unsigned > HvxWidenThreshold("hexagon-hvx-widen", cl::Hidden, cl::init(16), cl::desc("Lower threshold (in bytes) for widening to HVX vectors"))
static cl::opt< bool > EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false), cl::desc("Enable FP fast conversion routine."))
static MaybeAlign getAlign(Value *Ptr)
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
uint64_t getNumOperands() const
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
EVT getSetCCResultType(const DataLayout &, LLVMContext &C, EVT VT) const override
Return the ValueType of the result of SETCC operations.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
const SDValue & getBasePtr() const
static MVT getFloatingPointVT(unsigned BitWidth)
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
Flags
Flags values. These may be or'd together.
const MachinePointerInfo & getPointerInfo() const
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
unsigned getSubReg() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
iterator_range< value_op_iterator > op_values() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetSubtargetInfo & getSubtarget() const
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVMContext * getContext() const
LLVM_ABI std::pair< EVT, EVT > GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT, bool *HiIsEmpty) const
Compute the VTs needed for the low/hi parts of a type, dependent on an enveloping VT that has been sp...
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
size_type size() const
Determine the number of elements in the SetVector.
const value_type & front() const
Return the first element of the SetVector.
const value_type & back() const
Return the last element of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
const SDValue & getBasePtr() const
const SDValue & getValue() const
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
LegalizeAction getPartialReduceMLAAction(unsigned Opc, EVT AccVT, EVT InputVT) const
Return how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treated.
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ SIGN_EXTEND
Conversion operators.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
initializer< Ty > init(const Ty &Val)
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isVector() const
Return true if this is a vector value type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const