21#include "llvm/IR/IntrinsicsHexagon.h"
32 cl::desc(
"Lower threshold (in bytes) for widening to HVX vectors"));
36 cl::desc(
"Enable FP fast conversion routine."));
38static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
39static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
40static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
41static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
48 switch (ElemTy.SimpleTy) {
50 return std::make_tuple(5, 15, 10);
52 return std::make_tuple(8, 127, 23);
54 return std::make_tuple(11, 1023, 52);
62HexagonTargetLowering::initializeHVXLowering() {
63 if (Subtarget.useHVX64BOps()) {
81 }
else if (Subtarget.useHVX128BOps()) {
91 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
97 if (Subtarget.useHVXV81Ops()) {
105 bool Use64b = Subtarget.useHVX64BOps();
108 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
109 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
110 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
112 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
130 if (Subtarget.useHVX128BOps()) {
140 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
141 Subtarget.useHVXFloatingPoint()) {
143 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
144 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
146 for (MVT
T : FloatV) {
181 if (Subtarget.useHVXV81Ops()) {
184 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
185 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
186 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
187 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
213 for (MVT
P : FloatW) {
235 if (Subtarget.useHVXQFloatOps()) {
238 }
else if (Subtarget.useHVXIEEEFPOps()) {
244 for (MVT
T : LegalV) {
271 if (
T.getScalarType() != MVT::i32) {
280 if (
T.getScalarType() != MVT::i32) {
308 if (Subtarget.useHVXFloatingPoint()) {
325 for (MVT
T : LegalW) {
380 if (
T.getScalarType() != MVT::i32) {
385 if (Subtarget.useHVXFloatingPoint()) {
432 for (MVT
T : LegalW) {
449 for (MVT
T : LegalV) {
464 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
467 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
472 unsigned HwLen = Subtarget.getVectorLength();
473 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
474 if (ElemTy == MVT::i1)
476 int ElemWidth = ElemTy.getFixedSizeInBits();
477 int MaxElems = (8*HwLen) / ElemWidth;
478 for (
int N = 2;
N < MaxElems;
N *= 2) {
489 if (Subtarget.useHVXFloatingPoint()) {
519 auto HvxType = [=](MVT ScalarT,
unsigned Factor = 1) {
528 typedef std::tuple<MVT, MVT, bool> ReductionSignature;
530 static const std::vector<ReductionSignature> NativeReductions = {
531 {MVT::i32, MVT::i8,
false},
534 for (
const auto &R : NativeReductions) {
536 MVT AccType = std::get<0>(R);
537 MVT InputType = std::get<1>(R);
538 unsigned Factor = std::get<2>(R) ? 2 : 1;
560 for (
unsigned ConcatFactor = 1; ConcatFactor <=
MaxExpandMLA;
562 for (
unsigned ReductionFactor = 1; ReductionFactor <=
MaxExpandMLA;
563 ReductionFactor <<= 1)
564 if (ConcatFactor * ReductionFactor != 1 &&
567 MLAOps, HvxType(AccType, Factor * ConcatFactor),
568 HvxType(InputType, Factor * ConcatFactor * ReductionFactor),
575HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
582 unsigned HwLen = Subtarget.getVectorLength();
585 if (ElemTy == MVT::i1 && VecLen > HwLen)
591 if (ElemTy == MVT::i1) {
606 unsigned HwWidth = 8*HwLen;
607 if (VecWidth > 2*HwWidth)
613 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
622HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
623 unsigned Opc =
Op.getOpcode();
625 case HexagonISD::SMUL_LOHI:
626 case HexagonISD::UMUL_LOHI:
627 case HexagonISD::USMUL_LOHI:
643HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
644 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
648 Tys.second.getVectorNumElements());
651HexagonTargetLowering::TypePair
652HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
655 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
657 return { HalfTy, HalfTy };
661HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
668HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
675HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
684HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
690HexagonTargetLowering::VectorPair
691HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
693 TypePair Tys = typeSplit(ty(Vec));
696 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
700HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
701 return Subtarget.isHVXVectorType(Ty) &&
706HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
707 return Subtarget.isHVXVectorType(Ty) &&
712HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
713 return Subtarget.isHVXVectorType(Ty,
true) &&
717bool HexagonTargetLowering::allowsHvxMemoryAccess(
725 if (!Subtarget.isHVXVectorType(VecTy,
false))
732bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
734 if (!Subtarget.isHVXVectorType(VecTy))
742void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
744 unsigned Opc =
MI.getOpcode();
745 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
746 MachineBasicBlock &MB = *
MI.getParent();
750 auto At =
MI.getIterator();
753 case Hexagon::PS_vsplatib:
754 if (Subtarget.useHVXV62Ops()) {
759 .
add(
MI.getOperand(1));
761 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
767 const MachineOperand &InpOp =
MI.getOperand(1);
769 uint32_t
V = InpOp.
getImm() & 0xFF;
771 .
addImm(V << 24 | V << 16 | V << 8 | V);
777 case Hexagon::PS_vsplatrb:
778 if (Subtarget.useHVXV62Ops()) {
781 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
782 .
add(
MI.getOperand(1));
785 const MachineOperand &InpOp =
MI.getOperand(1);
786 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
789 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
794 case Hexagon::PS_vsplatih:
795 if (Subtarget.useHVXV62Ops()) {
800 .
add(
MI.getOperand(1));
802 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
808 const MachineOperand &InpOp =
MI.getOperand(1);
810 uint32_t
V = InpOp.
getImm() & 0xFFFF;
818 case Hexagon::PS_vsplatrh:
819 if (Subtarget.useHVXV62Ops()) {
822 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
823 .
add(
MI.getOperand(1));
828 const MachineOperand &InpOp =
MI.getOperand(1);
829 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
837 case Hexagon::PS_vsplatiw:
838 case Hexagon::PS_vsplatrw:
839 if (
Opc == Hexagon::PS_vsplatiw) {
843 .
add(
MI.getOperand(1));
844 MI.getOperand(1).ChangeToRegister(SplatV,
false);
847 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
853HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
863 const SDLoc &dl(ElemIdx);
869HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
872 assert(ElemWidth >= 8 && ElemWidth <= 32);
876 if (ty(Idx) != MVT::i32)
878 const SDLoc &dl(Idx);
885HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
892 if (ElemTy == MVT::i8)
896 MVT ResTy = tyVector(OpTy, MVT::i8);
899 SmallVector<int,128> ByteMask;
902 for (
unsigned I = 0;
I != ElemSize; ++
I)
905 int NewM =
M*ElemSize;
906 for (
unsigned I = 0;
I != ElemSize; ++
I)
912 opCastElem(Op1, MVT::i8, DAG), ByteMask);
919 unsigned VecLen =
Values.size();
923 unsigned HwLen = Subtarget.getVectorLength();
925 unsigned ElemSize = ElemWidth / 8;
926 assert(ElemSize*VecLen == HwLen);
930 !(Subtarget.useHVXFloatingPoint() &&
932 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
933 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
935 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
936 SDValue W = buildVector32(
Values.slice(i, OpsPerWord), dl, PartVT, DAG);
944 unsigned NumValues =
Values.size();
947 for (
unsigned i = 0; i != NumValues; ++i) {
951 if (!SplatV.getNode())
953 else if (SplatV !=
Values[i])
961 unsigned NumWords = Words.
size();
963 bool IsSplat =
isSplat(Words, SplatV);
964 if (IsSplat && isUndef(SplatV))
969 return getZero(dl, VecTy, DAG);
978 bool AllConst = getBuildVectorConstInts(
Values, VecTy, DAG, Consts);
981 (Constant**)Consts.end());
983 Align Alignment(HwLen);
999 SmallVectorImpl<int> &SrcIdx) {
1003 SrcIdx.push_back(-1);
1016 int I =
C->getSExtValue();
1017 assert(
I >= 0 &&
"Negative element index");
1018 SrcIdx.push_back(
I);
1024 SmallVector<int,128> ExtIdx;
1026 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
1027 MVT ExtTy = ty(ExtVec);
1029 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
1033 SmallVector<int,128>
Mask;
1034 BitVector
Used(ExtLen);
1036 for (
int M : ExtIdx) {
1046 for (
unsigned I = 0;
I != ExtLen; ++
I) {
1047 if (
Mask.size() == ExtLen)
1055 return ExtLen == VecLen ? S : LoHalf(S, DAG);
1063 assert(4*Words.
size() == Subtarget.getVectorLength());
1066 for (
unsigned i = 0; i != NumWords; ++i) {
1068 if (Words[i].isUndef())
1070 for (
unsigned j = i;
j != NumWords; ++
j)
1071 if (Words[i] == Words[j])
1074 if (VecHist[i] > VecHist[n])
1078 SDValue HalfV = getZero(dl, VecTy, DAG);
1079 if (VecHist[n] > 1) {
1087 HalfV = DAG.
getNode(HexagonISD::VALIGN, dl, VecTy,
1088 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1100 for (
unsigned i = 0; i != NumWords/2; ++i) {
1102 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1105 N = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1106 {HalfV0, Words[i]});
1109 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1112 M = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1113 {HalfV1, Words[i+NumWords/2]});
1136HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1137 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1138 MVT PredTy = ty(PredV);
1139 unsigned HwLen = Subtarget.getVectorLength();
1142 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1152 SmallVector<int,128>
Mask(HwLen);
1157 for (
unsigned i = 0; i != HwLen; ++i) {
1158 unsigned Num = i % Scale;
1159 unsigned Off = i / Scale;
1168 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1170 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1177 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1189 while (Bytes < BitBytes) {
1191 Words[IdxW].
clear();
1194 for (
const SDValue &W : Words[IdxW ^ 1]) {
1195 SDValue T = expandPredicate(W, dl, DAG);
1200 for (
const SDValue &W : Words[IdxW ^ 1]) {
1208 assert(Bytes == BitBytes);
1209 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1211 for (
const SDValue &W : Words[IdxW]) {
1213 Vec = DAG.
getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1225 unsigned VecLen =
Values.size();
1226 unsigned HwLen = Subtarget.getVectorLength();
1227 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1229 bool AllT =
true, AllF =
true;
1233 return !
N->isZero();
1242 if (VecLen <= HwLen) {
1246 assert(HwLen % VecLen == 0);
1247 unsigned BitBytes = HwLen / VecLen;
1254 for (
unsigned B = 0;
B != BitBytes; ++
B)
1261 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1264 for (;
B != 8; ++
B) {
1283 return DAG.
getNode(HexagonISD::QTRUE, dl, VecTy);
1285 return DAG.
getNode(HexagonISD::QFALSE, dl, VecTy);
1288 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1293HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1298 assert(ElemWidth >= 8 && ElemWidth <= 32);
1301 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1302 SDValue ExWord = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1304 if (ElemTy == MVT::i32)
1310 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1313 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1317HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1320 assert(ResTy == MVT::i1);
1322 unsigned HwLen = Subtarget.getVectorLength();
1326 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1330 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1332 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1336HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1341 assert(ElemWidth >= 8 && ElemWidth <= 32);
1346 MVT VecTy = ty(VecV);
1347 unsigned HwLen = Subtarget.getVectorLength();
1352 SDValue InsV = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1359 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1360 if (ElemTy == MVT::i32)
1361 return InsertWord(VecV, ValV, ByteIdx);
1367 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1372 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1373 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1375 ValV, SubIdx, dl, ElemTy, DAG);
1378 return InsertWord(VecV, Ins, ByteIdx);
1382HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1384 unsigned HwLen = Subtarget.getVectorLength();
1388 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1393 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1398HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1400 MVT VecTy = ty(VecV);
1401 unsigned HwLen = Subtarget.getVectorLength();
1409 if (isHvxPairTy(VecTy)) {
1410 unsigned SubIdx = Hexagon::vsub_lo;
1411 if (Idx * ElemWidth >= 8 * HwLen) {
1412 SubIdx = Hexagon::vsub_hi;
1416 VecTy = typeSplit(VecTy).first;
1426 MVT WordTy = tyVector(VecTy, MVT::i32);
1428 unsigned WordIdx = (Idx*ElemWidth) / 32;
1431 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1436 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1437 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1442HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1444 MVT VecTy = ty(VecV);
1445 unsigned HwLen = Subtarget.getVectorLength();
1453 unsigned Offset = Idx * BitBytes;
1455 SmallVector<int,128>
Mask;
1457 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1464 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1465 for (
unsigned j = 0;
j != Rep; ++
j)
1482 unsigned Rep = 8 / ResLen;
1485 for (
unsigned r = 0; r != HwLen / 8; ++r) {
1487 for (
unsigned i = 0; i != ResLen; ++i) {
1488 for (
unsigned j = 0;
j != Rep; ++
j)
1500 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1501 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1506HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1508 MVT VecTy = ty(VecV);
1509 MVT SubTy = ty(SubV);
1510 unsigned HwLen = Subtarget.getVectorLength();
1514 bool IsPair = isHvxPairTy(VecTy);
1522 V0 = LoHalf(VecV, DAG);
1523 V1 = HiHalf(VecV, DAG);
1528 if (isHvxSingleTy(SubTy)) {
1530 unsigned Idx = CN->getZExtValue();
1532 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1555 if (!IdxN || !IdxN->isZero()) {
1563 unsigned RolBase = HwLen;
1566 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1571 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1574 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1578 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1593HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1595 MVT VecTy = ty(VecV);
1596 MVT SubTy = ty(SubV);
1597 assert(Subtarget.isHVXVectorType(VecTy,
true));
1602 unsigned HwLen = Subtarget.getVectorLength();
1603 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1606 unsigned BitBytes = HwLen / VecLen;
1607 unsigned BlockLen = HwLen / Scale;
1611 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1615 if (!IdxN || !IdxN->isZero()) {
1624 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1626 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1628 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1630 if (!IdxN || !IdxN->isZero()) {
1639HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1644 assert(Subtarget.isHVXVectorType(ResTy));
1651 SDValue False = getZero(dl, ResTy, DAG);
1652 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1656HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1664 unsigned HwLen = Subtarget.getVectorLength();
1666 MVT PredTy = ty(VecQ);
1668 assert(HwLen % PredLen == 0);
1675 for (
unsigned i = 0; i != HwLen/8; ++i) {
1676 for (
unsigned j = 0;
j != 8; ++
j)
1677 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1680 Align Alignment(HwLen);
1690 getZero(dl, VecTy, DAG));
1696 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1698 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1705 SmallVector<int,128>
Mask;
1706 for (
unsigned i = 0; i != HwLen; ++i)
1707 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1717 MVT InpTy = ty(VecV);
1725 return InpWidth < ResWidth
1733 if (InpWidth < ResWidth) {
1735 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1737 unsigned NarOpc =
Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1743HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1747 const SDLoc &dl(Vec);
1756 const SDLoc &dl(
Op);
1761 for (
unsigned i = 0; i !=
Size; ++i)
1762 Ops.push_back(
Op.getOperand(i));
1765 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1773 for (
unsigned i = 0; i !=
Size; i++)
1784 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1786 MVT SingleTy = typeSplit(VecTy).first;
1787 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1788 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1792 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1798 const SDLoc &dl(
Op);
1800 MVT ArgTy = ty(
Op.getOperand(0));
1802 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1820 const SDLoc &dl(
Op);
1837 MVT NTy = typeLegalize(Ty, DAG);
1841 V.getOperand(0),
V.getOperand(1)),
1846 switch (
V.getOpcode()) {
1854 V =
V.getOperand(0);
1865 unsigned HwLen = Subtarget.getVectorLength();
1872 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1874 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, Op0,
Op.getOperand(1));
1880 MVT HalfTy = typeSplit(VecTy).first;
1882 Ops.take_front(NumOp/2));
1884 Ops.take_back(NumOp/2));
1885 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, V0,
V1);
1895 SDValue Combined = combineConcatOfScalarPreds(
Op, BitBytes, DAG);
1898 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1902 unsigned InpLen = ty(Combined.
getOperand(0)).getVectorNumElements();
1905 SDValue Res = getZero(dl, ByteTy, DAG);
1906 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1919 const SDLoc &dl(
Op);
1921 if (ElemTy == MVT::i1)
1922 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1924 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1930 const SDLoc &dl(
Op);
1936 if (ElemTy == MVT::i1)
1937 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1939 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1941 tyVector(VecTy, MVT::i16),
1942 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1944 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1947 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1954 MVT SrcTy = ty(SrcV);
1960 const SDLoc &dl(
Op);
1963 if (ElemTy == MVT::i1)
1964 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1966 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1977 const SDLoc &dl(
Op);
1978 MVT VecTy = ty(VecV);
1980 if (ElemTy == MVT::i1)
1981 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1983 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1995 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1996 return LowerHvxSignExt(
Op, DAG);
2005 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2006 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
2015 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2016 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
2024 const SDLoc &dl(
Op);
2027 assert(ResTy == ty(InpV));
2052 const SDLoc &dl(
Op);
2059 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2060 unsigned Opc =
Op.getOpcode();
2064 return DAG.
getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2066 return DAG.
getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).
getValue(1);
2076 const SDLoc &dl(
Op);
2077 unsigned Opc =
Op.getOpcode();
2082 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2089 bool SignedVu =
Opc == HexagonISD::SMUL_LOHI;
2090 bool SignedVv =
Opc == HexagonISD::SMUL_LOHI ||
Opc == HexagonISD::USMUL_LOHI;
2094 if (Subtarget.useHVXV62Ops())
2095 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2097 if (
Opc == HexagonISD::SMUL_LOHI) {
2100 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2101 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2107 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2114 MVT ValTy = ty(Val);
2115 const SDLoc &dl(
Op);
2118 unsigned HwLen = Subtarget.getVectorLength();
2126 if (PredLen < HwLen) {
2129 if (HwLen > PredLen * 2) {
2130 assert(HwLen == PredLen * 4);
2132 Val = getInstr(Hexagon::V6_vdealh, dl, ByteTy, Val, DAG);
2134 if (HwLen > PredLen) {
2135 assert(HwLen == PredLen * 2);
2136 Val = getInstr(Hexagon::V6_vdealb, dl, ByteTy, Val, DAG);
2141 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2156 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2158 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2163 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2164 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2177 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2178 assert(Val32.getValueType().getSizeInBits() == 32 &&
2179 "Input must be 32 bits");
2183 for (
unsigned i = 0; i < 32; ++i)
2191 if (ResTy == MVT::v32i1 &&
2192 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2193 Subtarget.useHVX128BOps()) {
2195 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2197 return bitcastI32ToV32I1(Val32);
2200 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2218 unsigned HwLen = Subtarget.getVectorLength();
2230 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2234 for (
unsigned J = 0; J != 8; ++J) {
2242 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2254 const SDLoc &dl(
Op);
2257 MVT ValTy = ty(Val);
2260 if (!isHvxBoolTy(ValTy))
2267 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2271 unsigned HwLen = Subtarget.getVectorLength();
2275 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2279 for (
unsigned i = 0; i != NumBits / 32; ++i) {
2290 return DAG.
getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2293 if (NumBits == 64) {
2294 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2298 if (NumBits == 128) {
2299 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2300 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2316 const SDLoc &dl(
Op);
2321 if (!isHvxBoolTy(ResTy))
2327 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2335 if (NumBits == 32) {
2343 if (NumBits == 64) {
2351 if (NumBits == 128) {
2387 const SDLoc &dl(
Op);
2388 unsigned HwLen = Subtarget.getVectorLength();
2390 assert(HwLen % VecLen == 0);
2391 unsigned ElemSize = HwLen / VecLen;
2403 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2409HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2411 unsigned Opc =
Op.getOpcode();
2423 const SDLoc &dl(
Op);
2429 bool UseShifts = ElemTy != MVT::i8;
2430 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2433 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2441 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2447 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2449 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2457 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2459 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2466 const SDLoc &dl(
Op);
2467 unsigned IntNo =
Op.getConstantOperandVal(0);
2475 case Intrinsic::hexagon_V6_pred_typecast:
2476 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2477 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2478 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2485 case Intrinsic::hexagon_V6_vmpyss_parts:
2486 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2487 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2489 case Intrinsic::hexagon_V6_vmpyuu_parts:
2490 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2491 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2493 case Intrinsic::hexagon_V6_vmpyus_parts:
2494 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2495 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2505 const SDLoc &dl(
Op);
2506 unsigned HwLen = Subtarget.getVectorLength();
2510 SDValue Chain = MaskN->getChain();
2514 unsigned Opc =
Op->getOpcode();
2531 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2535 if (MaskN->getAlign().value() % HwLen == 0) {
2544 SDValue Z = getZero(dl, ty(V), DAG);
2548 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2549 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2550 return std::make_pair(LoV, HiV);
2556 VectorPair Tmp = StoreAlign(MaskV,
Base);
2559 VectorPair ValueU = StoreAlign(
Value,
Base);
2563 getInstr(StoreOpc, dl, MVT::Other,
2564 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2566 getInstr(StoreOpc, dl, MVT::Other,
2567 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2577 assert(Subtarget.useHVXQFloatOps());
2582 MVT ArgTy = ty(
Op.getOperand(0));
2583 const SDLoc &dl(
Op);
2585 if (ArgTy == MVT::v64bf16) {
2586 MVT HalfTy = typeSplit(VecTy).first;
2589 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2594 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2595 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2597 {VecPair.second, VecPair.first,
2603 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2612 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2614 MVT HalfTy = typeSplit(VecTy).first;
2615 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2617 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2619 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2622 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2635 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2638 if (Subtarget.useHVXIEEEFPOps()) {
2640 if (FpTy == MVT::f16) {
2642 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2644 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2650 return EqualizeFpIntConversion(
Op, DAG);
2652 return ExpandHvxFpToInt(
Op, DAG);
2668 MVT ResTy = ty(PredOp);
2669 const SDLoc &dl(PredOp);
2672 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2673 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2675 SDNode *PredTransfer =
2678 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2681 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2686 SDNode *IndexShift =
2692 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2717 MVT ResTy = ty(PredOp);
2718 const SDLoc &dl(PredOp);
2728 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2729 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2739 SDNode *PredTransfer =
2743 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2750 SDNode *IndexShift_hi =
2753 SDNode *IndexShift_lo =
2757 SDNode *MaskOff_hi =
2760 SDNode *MaskOff_lo =
2783 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2784 return LowerHvxPred32ToFp(
Op, DAG);
2785 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2786 return LowerHvxPred64ToFp(
Op, DAG);
2789 if (Subtarget.useHVXIEEEFPOps()) {
2791 if (FpTy == MVT::f16) {
2793 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2795 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2801 return EqualizeFpIntConversion(
Op, DAG);
2803 return ExpandHvxIntToFp(
Op, DAG);
2806HexagonTargetLowering::TypePair
2807HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2818 unsigned MaxWidth = std::max(Width0, Width1);
2820 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2827 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2828 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2832 return {WideETy0, WideETy1};
2843HexagonTargetLowering::TypePair
2844HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2854 unsigned MaxLen = std::max(Len0, Len1);
2867HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2868 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2877HexagonTargetLowering::VectorPair
2908HexagonTargetLowering::VectorPair
2909HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2914 const SDLoc &dl(Val);
2915 MVT ValTy = ty(Val);
2929 MVT IntTy = tyVector(ValTy, ElemTy);
2941 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2960 MVT
PairTy = typeJoin({VecTy, VecTy});
2986 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2988 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2996 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
3001 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3002 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
3003 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
3014HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
3015 bool SignedB,
const SDLoc &dl,
3018 MVT
PairTy = typeJoin({VecTy, VecTy});
3023 if (SignedA && !SignedB) {
3039 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3040 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
3041 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
3050 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3053 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
3057 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3058 {HiHalf(P2, DAG), T3,
S16}, DAG);
3061 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3062 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
3066 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
3073 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
3074 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
3075 }
else if (SignedB) {
3081 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
3083 assert(!SignedA && !SignedB);
3090HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
3095 MVT
PairTy = typeJoin({VecTy, VecTy});
3098 if (SignedA && !SignedB) {
3107 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
3112 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
3124 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
3125 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
3126 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
3127 }
else if (!SignedA) {
3137 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
3155 unsigned Opc =
Op.getOpcode();
3160 MVT InpTy = ty(Inp);
3166 const SDLoc &dl(
Op);
3169 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3178 unsigned Opc =
Op.getOpcode();
3181 const SDLoc &dl(
Op);
3183 MVT InpTy = ty(Op0);
3196 if (InpTy == MVT::v64f16) {
3197 if (Subtarget.useHVXV81Ops()) {
3200 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3204 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3209 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3289 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3290 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3333 unsigned Opc =
Op.getOpcode();
3336 const SDLoc &dl(
Op);
3338 MVT InpTy = ty(Op0);
3371 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3381 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3404 unsigned Opc =
Op.getOpcode();
3421 const SDLoc &dl(
Op);
3422 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3431 unsigned Opc =
Op.getConstantOperandVal(2);
3435HexagonTargetLowering::VectorPair
3439 const SDLoc &dl(
Op);
3441 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3442 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3444 return std::make_pair(TV, TV);
3449 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3451 switch (
Op.getOpcode()) {
3452 case ISD::SIGN_EXTEND_INREG:
3453 case HexagonISD::SSAT:
3454 case HexagonISD::USAT:
3455 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3456 std::tie(Lo, Hi) = SplitVTNode(N);
3464 MVT HalfTy = typeSplit(ResTy).first;
3473 unsigned MemOpc = MemN->getOpcode();
3474 EVT MemTy = MemN->getMemoryVT();
3491 EVT LoMemVT, HiMemVT;
3492 bool HiIsEmpty =
false;
3493 std::tie(LoMemVT, HiMemVT) =
3499 const SDLoc &dl(
Op);
3500 SDValue Chain = MemN->getChain();
3501 SDValue Base0 = MemN->getBasePtr();
3505 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3506 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3508 auto MemSize = [=](uint64_t
Size) {
3542 assert(MaskN->isUnindexed());
3543 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3550 Masks.first, Thru.first, LoMemVT, MOp0,
3559 Masks.second, Thru.second, HiMemVT, MOp1,
3581 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3587 const SDLoc &dl(
Op);
3589 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3590 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3591 "Not widening loads of i1 yet");
3593 SDValue Chain = LoadN->getChain();
3598 unsigned HwLen = Subtarget.getVectorLength();
3600 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3603 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3611 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3619 const SDLoc &dl(
Op);
3621 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3622 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3623 "Not widening stores of i1 yet");
3625 SDValue Chain = StoreN->getChain();
3629 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3630 MVT ValueTy = ty(
Value);
3632 unsigned HwLen = Subtarget.getVectorLength();
3635 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3637 Len = ty(
Value).getVectorNumElements();
3639 assert(ty(
Value).getVectorNumElements() == HwLen);
3641 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3643 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3646 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3653 const SDLoc &dl(
Op);
3654 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3656 unsigned HwLen = Subtarget.getVectorLength();
3661 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3664 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3665 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3669 {WideOp0, WideOp1,
Op.getOperand(2)});
3671 EVT RetTy = typeLegalize(ty(
Op), DAG);
3673 {SetCC, getZero(dl, MVT::i32, DAG)});
3683 const SDLoc &dl(
Op);
3685 MVT InpTy = ty(Inp);
3689 "Expected boolean result type");
3692 unsigned HwLen = Subtarget.getVectorLength();
3697 if (!Subtarget.isHVXVectorType(WideInpTy,
false))
3701 SDValue WideInp = appendUndef(Inp, WideInpTy, DAG);
3708 EVT RetTy = typeLegalize(ResTy, DAG);
3710 {WideTrunc, getZero(dl, MVT::i32, DAG)});
3715 unsigned Opc =
Op.getOpcode();
3716 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3718 return isHvxPairTy(ty(V));
3729 return SplitHvxMemOp(
Op, DAG);
3734 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3735 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3765 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3770 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3771 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3795 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3797 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3818 case HexagonISD::SMUL_LOHI:
3819 case HexagonISD::UMUL_LOHI:
3820 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3825 return LowerHvxPartialReduceMLA(
Op, DAG);
3843 unsigned Opc =
Op.getOpcode();
3845 case HexagonISD::SSAT:
3846 case HexagonISD::USAT:
3863 MVT InpTy = ty(Inp);
3868 assert(InpWidth != ResWidth);
3870 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3873 const SDLoc &dl(
Op);
3877 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3880 case HexagonISD::SSAT:
3881 case HexagonISD::USAT:
3885 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3892 if (InpWidth < ResWidth) {
3894 while (InpWidth * 2 <= ResWidth)
3895 S = repeatOp(InpWidth *= 2, S);
3899 while (InpWidth / 2 >= ResWidth)
3900 S = repeatOp(InpWidth /= 2, S);
3908 MVT InpTy = ty(Inp0);
3912 unsigned Opc =
Op.getOpcode();
3914 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3919 auto [WInpTy, WResTy] =
3920 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3921 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3922 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3930 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3931 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3932 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3939 SDValue T = ExpandHvxResizeIntoSteps(
Op, DAG);
3942 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3945 return RemoveTLWrapper(
Op, DAG);
3951HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3953 unsigned Opc =
N->getOpcode();
3956 if (
N->getNumOperands() > 0)
3957 Inp0 =
Op.getOperand(0);
3963 if (Subtarget.isHVXElementType(ty(
Op)) &&
3964 Subtarget.isHVXElementType(ty(Inp0))) {
3965 Results.push_back(CreateTLWrapper(
Op, DAG));
3977 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
3978 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
3980 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
3981 Subtarget.isHVXElementType(ty(Inp0))) {
3982 Results.push_back(CreateTLWrapper(
Op, DAG));
3986 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3999 if (isHvxPairTy(ty(
Op))) {
4007 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
4016 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4017 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4021 case HexagonISD::SSAT:
4022 case HexagonISD::USAT:
4025 Results.push_back(LegalizeHvxResize(
Op, DAG));
4033HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
4035 unsigned Opc =
N->getOpcode();
4038 if (
N->getNumOperands() > 0)
4039 Inp0 =
Op.getOperand(0);
4045 if (Subtarget.isHVXElementType(ty(
Op)) &&
4046 Subtarget.isHVXElementType(ty(Inp0))) {
4047 Results.push_back(CreateTLWrapper(
Op, DAG));
4054 !Subtarget.isHVXVectorType(ty(Inp0),
false)) {
4055 if (
SDValue T = WidenHvxTruncateToBool(
Op, DAG))
4057 }
else if (Subtarget.isHVXElementType(ty(
Op)) &&
4058 Subtarget.isHVXElementType(ty(Inp0))) {
4059 Results.push_back(CreateTLWrapper(
Op, DAG));
4063 if (shouldWidenToHvx(ty(
Op), DAG)) {
4069 if (shouldWidenToHvx(ty(
Op), DAG)) {
4078 if (isHvxBoolTy(ty(Inp0))) {
4085 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4086 SDValue T = EqualizeFpIntConversion(
Op, DAG);
4090 case HexagonISD::SSAT:
4091 case HexagonISD::USAT:
4094 Results.push_back(LegalizeHvxResize(
Op, DAG));
4102HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
4103 DAGCombinerInfo &DCI)
const {
4108 SelectionDAG &DAG = DCI.DAG;
4109 const SDLoc &dl(
Op);
4116 EVT TruncTy =
Op.getValueType();
4118 EVT SrcTy = Src.getValueType();
4125 if (2 * CastLen != SrcLen)
4128 SmallVector<int, 128>
Mask(SrcLen);
4129 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
4131 Mask[i + CastLen] = 2 * i + 1;
4135 return opSplit(Deal, dl, DAG).first;
4139HexagonTargetLowering::combineConcatOfShuffles(
SDValue Op,
4148 const SDLoc &dl(
Op);
4157 SetVector<SDValue> Order;
4163 if (Order.
size() > 2)
4172 SmallVector<int, 128> LongMask;
4173 auto AppendToMask = [&](
SDValue Shuffle) {
4175 ArrayRef<int>
Mask = SV->getMask();
4178 for (
int M : Mask) {
4183 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
4184 if (
static_cast<unsigned>(M) >= InpLen)
4187 int OutOffset = Order[0] == Src ? 0 : InpLen;
4210HexagonTargetLowering::combineConcatOfScalarPreds(
SDValue Op,
unsigned BitBytes,
4212 const SDLoc &dl(
Op);
4215 MVT InpTy = ty(
Ops[0]);
4218 assert(InpLen <= 8 &&
"Too long for scalar predicate");
4219 assert(ResLen > 8 &&
"Too short for HVX vector predicate");
4221 unsigned Bytes = 8 / InpLen;
4224 if (Bytes <= BitBytes)
4228 unsigned SliceLen = Bytes / BitBytes;
4233 for (
unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4235 Inputs.slice(SliceLen * i, SliceLen));
4242SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4243 SDValue Op, DAGCombinerInfo &DCI)
const {
4247 if (ElemTy != MVT::i1) {
4248 return combineConcatOfShuffles(
Op, DCI.DAG);
4255SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4256 unsigned Opcode,
EVT AccEltType,
unsigned AccNumElements,
EVT InputType,
4259 const auto &Subtarget = DAG.
getSubtarget<HexagonSubtarget>();
4260 if (!Subtarget.useHVXOps())
4266 unsigned NativeRatio;
4267 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4279 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4280 if (RemainingReductionRatio == 1)
4285 InputNumElements / NativeRatio);
4288 return DAG.
getNode(Opcode,
DL, IntermediateType, Zero,
A,
B);
4294 EVT AccType =
Mul.getValueType();
4300 A =
Mul->getOperand(0);
4301 B =
Mul->getOperand(1);
4321 A =
A->getOperand(0);
4322 B =
B->getOperand(0);
4323 if (
A.getValueType() !=
B.getValueType())
4334 if (!Subtarget.useHVXOps())
4337 EVT ScalarType =
N->getValueType(0);
4344 unsigned RemainingReductionRatio;
4346 createExtendingPartialReduceMLA(Opcode, ScalarType, 1,
A.getValueType(),
4347 A,
B, RemainingReductionRatio,
DL, DAG);
4364HexagonTargetLowering::splitExtendingPartialReduceMLA(
SDNode *
N,
4366 if (!Subtarget.useHVXOps())
4372 if (
A.getValueType() !=
B.getValueType())
4378 EVT InputType =
A.getValueType();
4383 unsigned RemainingReductionRatio;
4384 SDValue Partial = createExtendingPartialReduceMLA(
4398 DL, AccType, Acc, Partial, One);
4402HexagonTargetLowering::LowerHvxPartialReduceMLA(
SDValue Op,
4404 const SDLoc &
DL(
Op);
4410 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4414 unsigned AccSubvectorNumElements =
4416 EVT AccSubvectorType =
4419 EVT InputType =
A.getValueType();
4422 unsigned InputSubvectorNumElements =
4425 InputSubvectorNumElements);
4430 for (
unsigned I = 0;
I != SubvectorNum; ++
I) {
4432 I * AccSubvectorNumElements);
4434 I * InputSubvectorNumElements);
4436 I * InputSubvectorNumElements);
4438 SubvectorAcc, SubvectorA, SubvectorB);
4446HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
4449 SelectionDAG &DAG = DCI.DAG;
4451 unsigned Opc =
Op.getOpcode();
4456 return combineTruncateBeforeLegal(
Op, DCI);
4458 return combineConcatVectorsBeforeLegal(
Op, DCI);
4460 if (DCI.isBeforeLegalizeOps())
4467 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
4468 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
4472 if (
Ops[0].getOpcode() == HexagonISD::QTRUE)
4475 if (
Ops[0].getOpcode() == HexagonISD::QFALSE)
4476 return getZero(dl, ty(
Op), DAG);
4478 case HexagonISD::VINSERTW0:
4479 if (isUndef(
Ops[1]))
4497HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4498 if (Subtarget.isHVXVectorType(Ty,
true))
4500 auto Action = getPreferredHvxVectorAction(Ty);
4502 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4507HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4508 if (Subtarget.isHVXVectorType(Ty,
true))
4510 auto Action = getPreferredHvxVectorAction(Ty);
4512 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4518 if (!Subtarget.useHVXOps())
4522 auto IsHvxTy = [
this](EVT Ty) {
4523 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4526 return Op.getValueType().isSimple() &&
4527 Subtarget.isHVXVectorType(ty(
Op),
true);
4533 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
4534 if (!
Op.getValueType().isSimple())
4537 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4540 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const unsigned MaxExpandMLA
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static bool DetectExtendingMultiply(const SDValue &N, EVT ScalarType, unsigned &Opcode, SDValue &A, SDValue &B)
static cl::opt< unsigned > HvxWidenThreshold("hexagon-hvx-widen", cl::Hidden, cl::init(16), cl::desc("Lower threshold (in bytes) for widening to HVX vectors"))
static cl::opt< bool > EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false), cl::desc("Enable FP fast conversion routine."))
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
uint64_t getNumOperands() const
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
EVT getSetCCResultType(const DataLayout &, LLVMContext &C, EVT VT) const override
Return the ValueType of the result of SETCC operations.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
const SDValue & getBasePtr() const
static MVT getFloatingPointVT(unsigned BitWidth)
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
Flags
Flags values. These may be or'd together.
const MachinePointerInfo & getPointerInfo() const
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
unsigned getSubReg() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
iterator_range< value_op_iterator > op_values() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetSubtargetInfo & getSubtarget() const
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVMContext * getContext() const
LLVM_ABI std::pair< EVT, EVT > GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT, bool *HiIsEmpty) const
Compute the VTs needed for the low/hi parts of a type, dependent on an enveloping VT that has been sp...
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
size_type size() const
Determine the number of elements in the SetVector.
const value_type & front() const
Return the first element of the SetVector.
const value_type & back() const
Return the last element of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
const SDValue & getBasePtr() const
const SDValue & getValue() const
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
LegalizeAction getPartialReduceMLAAction(unsigned Opc, EVT AccVT, EVT InputVT) const
Return how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treated.
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ SIGN_EXTEND
Conversion operators.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
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.
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.
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