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 };
46 switch (ElemTy.SimpleTy) {
48 return std::make_tuple(5, 15, 10);
50 return std::make_tuple(8, 127, 23);
52 return std::make_tuple(11, 1023, 52);
60HexagonTargetLowering::initializeHVXLowering() {
61 if (Subtarget.useHVX64BOps()) {
79 }
else if (Subtarget.useHVX128BOps()) {
89 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
95 if (Subtarget.useHVXV81Ops()) {
103 bool Use64b = Subtarget.useHVX64BOps();
106 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
107 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
108 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
110 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
128 if (Subtarget.useHVX128BOps()) {
132 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
133 Subtarget.useHVXFloatingPoint()) {
135 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
136 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
138 for (MVT
T : FloatV) {
173 if (Subtarget.useHVXV81Ops()) {
176 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
177 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
178 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
179 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
205 for (MVT
P : FloatW) {
227 if (Subtarget.useHVXQFloatOps()) {
230 }
else if (Subtarget.useHVXIEEEFPOps()) {
236 for (MVT
T : LegalV) {
263 if (
T.getScalarType() != MVT::i32) {
272 if (
T.getScalarType() != MVT::i32) {
300 if (Subtarget.useHVXFloatingPoint()) {
317 for (MVT
T : LegalW) {
372 if (
T.getScalarType() != MVT::i32) {
377 if (Subtarget.useHVXFloatingPoint()) {
424 for (MVT
T : LegalW) {
441 for (MVT
T : LegalV) {
456 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
459 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
464 unsigned HwLen = Subtarget.getVectorLength();
465 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
466 if (ElemTy == MVT::i1)
468 int ElemWidth = ElemTy.getFixedSizeInBits();
469 int MaxElems = (8*HwLen) / ElemWidth;
470 for (
int N = 2;
N < MaxElems;
N *= 2) {
481 if (Subtarget.useHVXFloatingPoint()) {
504HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
511 unsigned HwLen = Subtarget.getVectorLength();
514 if (ElemTy == MVT::i1 && VecLen > HwLen)
520 if (ElemTy == MVT::i1) {
535 unsigned HwWidth = 8*HwLen;
536 if (VecWidth > 2*HwWidth)
542 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
551HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
552 unsigned Opc =
Op.getOpcode();
554 case HexagonISD::SMUL_LOHI:
555 case HexagonISD::UMUL_LOHI:
556 case HexagonISD::USMUL_LOHI:
572HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
573 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
577 Tys.second.getVectorNumElements());
580HexagonTargetLowering::TypePair
581HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
584 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
586 return { HalfTy, HalfTy };
590HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
597HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
604HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
613HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
619HexagonTargetLowering::VectorPair
620HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
622 TypePair Tys = typeSplit(ty(Vec));
625 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
629HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
630 return Subtarget.isHVXVectorType(Ty) &&
635HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
636 return Subtarget.isHVXVectorType(Ty) &&
641HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
642 return Subtarget.isHVXVectorType(Ty,
true) &&
646bool HexagonTargetLowering::allowsHvxMemoryAccess(
654 if (!Subtarget.isHVXVectorType(VecTy,
false))
661bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
663 if (!Subtarget.isHVXVectorType(VecTy))
671void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
673 unsigned Opc =
MI.getOpcode();
674 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
675 MachineBasicBlock &MB = *
MI.getParent();
679 auto At =
MI.getIterator();
682 case Hexagon::PS_vsplatib:
683 if (Subtarget.useHVXV62Ops()) {
686 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
688 .
add(
MI.getOperand(1));
690 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
695 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
696 const MachineOperand &InpOp =
MI.getOperand(1);
698 uint32_t
V = InpOp.
getImm() & 0xFF;
700 .
addImm(V << 24 | V << 16 | V << 8 | V);
706 case Hexagon::PS_vsplatrb:
707 if (Subtarget.useHVXV62Ops()) {
710 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
711 .
add(
MI.getOperand(1));
713 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
714 const MachineOperand &InpOp =
MI.getOperand(1);
715 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
718 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
723 case Hexagon::PS_vsplatih:
724 if (Subtarget.useHVXV62Ops()) {
727 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
729 .
add(
MI.getOperand(1));
731 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
736 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
737 const MachineOperand &InpOp =
MI.getOperand(1);
739 uint32_t
V = InpOp.
getImm() & 0xFFFF;
747 case Hexagon::PS_vsplatrh:
748 if (Subtarget.useHVXV62Ops()) {
751 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
752 .
add(
MI.getOperand(1));
756 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
757 const MachineOperand &InpOp =
MI.getOperand(1);
758 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
766 case Hexagon::PS_vsplatiw:
767 case Hexagon::PS_vsplatrw:
768 if (
Opc == Hexagon::PS_vsplatiw) {
770 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
772 .
add(
MI.getOperand(1));
773 MI.getOperand(1).ChangeToRegister(SplatV,
false);
776 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
782HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
792 const SDLoc &dl(ElemIdx);
798HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
801 assert(ElemWidth >= 8 && ElemWidth <= 32);
805 if (ty(Idx) != MVT::i32)
807 const SDLoc &dl(Idx);
814HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
821 if (ElemTy == MVT::i8)
825 MVT ResTy = tyVector(OpTy, MVT::i8);
828 SmallVector<int,128> ByteMask;
831 for (
unsigned I = 0;
I != ElemSize; ++
I)
834 int NewM =
M*ElemSize;
835 for (
unsigned I = 0;
I != ElemSize; ++
I)
841 opCastElem(Op1, MVT::i8, DAG), ByteMask);
848 unsigned VecLen = Values.
size();
852 unsigned HwLen = Subtarget.getVectorLength();
854 unsigned ElemSize = ElemWidth / 8;
855 assert(ElemSize*VecLen == HwLen);
859 !(Subtarget.useHVXFloatingPoint() &&
861 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
862 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
864 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
865 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
873 unsigned NumValues = Values.size();
876 for (
unsigned i = 0; i != NumValues; ++i) {
877 if (Values[i].isUndef())
880 if (!SplatV.getNode())
882 else if (SplatV != Values[i])
890 unsigned NumWords = Words.
size();
892 bool IsSplat =
isSplat(Words, SplatV);
893 if (IsSplat && isUndef(SplatV))
898 return getZero(dl, VecTy, DAG);
907 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
910 (Constant**)Consts.end());
912 Align Alignment(HwLen);
927 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
928 SmallVectorImpl<int> &SrcIdx) {
932 SrcIdx.push_back(-1);
945 int I =
C->getSExtValue();
946 assert(
I >= 0 &&
"Negative element index");
953 SmallVector<int,128> ExtIdx;
955 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
956 MVT ExtTy = ty(ExtVec);
958 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
962 SmallVector<int,128>
Mask;
963 BitVector
Used(ExtLen);
965 for (
int M : ExtIdx) {
975 for (
unsigned I = 0;
I != ExtLen; ++
I) {
976 if (
Mask.size() == ExtLen)
984 return ExtLen == VecLen ? S : LoHalf(S, DAG);
992 assert(4*Words.
size() == Subtarget.getVectorLength());
995 for (
unsigned i = 0; i != NumWords; ++i) {
997 if (Words[i].isUndef())
999 for (
unsigned j = i;
j != NumWords; ++
j)
1000 if (Words[i] == Words[j])
1003 if (VecHist[i] > VecHist[n])
1007 SDValue HalfV = getZero(dl, VecTy, DAG);
1008 if (VecHist[n] > 1) {
1010 HalfV = DAG.
getNode(HexagonISD::VALIGN, dl, VecTy,
1011 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1023 for (
unsigned i = 0; i != NumWords/2; ++i) {
1025 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1028 N = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1029 {HalfV0, Words[i]});
1032 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1035 M = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy,
1036 {HalfV1, Words[i+NumWords/2]});
1059HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1060 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1061 MVT PredTy = ty(PredV);
1062 unsigned HwLen = Subtarget.getVectorLength();
1065 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1075 SmallVector<int,128>
Mask(HwLen);
1080 for (
unsigned i = 0; i != HwLen; ++i) {
1081 unsigned Num = i % Scale;
1082 unsigned Off = i / Scale;
1091 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1093 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1100 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1109 if (Bytes < BitBytes) {
1115 while (Bytes < BitBytes) {
1117 Words[IdxW].
clear();
1120 for (
const SDValue &W : Words[IdxW ^ 1]) {
1121 SDValue T = expandPredicate(W, dl, DAG);
1126 for (
const SDValue &W : Words[IdxW ^ 1]) {
1134 while (Bytes > BitBytes) {
1136 Words[IdxW].
clear();
1139 for (
const SDValue &W : Words[IdxW ^ 1]) {
1140 SDValue T = contractPredicate(W, dl, DAG);
1144 for (
const SDValue &W : Words[IdxW ^ 1]) {
1151 assert(Bytes == BitBytes);
1152 if (BitBytes == 1 && PredTy == MVT::v2i1)
1155 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1157 for (
const SDValue &W : Words[IdxW]) {
1159 Vec = DAG.
getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1171 unsigned VecLen = Values.
size();
1172 unsigned HwLen = Subtarget.getVectorLength();
1173 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1175 bool AllT =
true, AllF =
true;
1179 return !
N->isZero();
1188 if (VecLen <= HwLen) {
1192 assert(HwLen % VecLen == 0);
1193 unsigned BitBytes = HwLen / VecLen;
1200 for (
unsigned B = 0;
B != BitBytes; ++
B)
1207 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1210 for (;
B != 8; ++
B) {
1211 if (!Values[
I+
B].isUndef())
1224 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1229 return DAG.
getNode(HexagonISD::QTRUE, dl, VecTy);
1231 return DAG.
getNode(HexagonISD::QFALSE, dl, VecTy);
1234 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1239HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1244 assert(ElemWidth >= 8 && ElemWidth <= 32);
1247 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1248 SDValue ExWord = DAG.
getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1250 if (ElemTy == MVT::i32)
1256 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1259 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1263HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1266 assert(ResTy == MVT::i1);
1268 unsigned HwLen = Subtarget.getVectorLength();
1272 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1276 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1278 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1282HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1287 assert(ElemWidth >= 8 && ElemWidth <= 32);
1292 MVT VecTy = ty(VecV);
1293 unsigned HwLen = Subtarget.getVectorLength();
1298 SDValue InsV = DAG.
getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1305 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1306 if (ElemTy == MVT::i32)
1307 return InsertWord(VecV, ValV, ByteIdx);
1313 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1318 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1319 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1321 ValV, SubIdx, dl, ElemTy, DAG);
1324 return InsertWord(VecV, Ins, ByteIdx);
1328HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1330 unsigned HwLen = Subtarget.getVectorLength();
1334 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1339 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1344HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1346 MVT VecTy = ty(VecV);
1347 unsigned HwLen = Subtarget.getVectorLength();
1355 if (isHvxPairTy(VecTy)) {
1356 unsigned SubIdx = Hexagon::vsub_lo;
1357 if (Idx * ElemWidth >= 8 * HwLen) {
1358 SubIdx = Hexagon::vsub_hi;
1362 VecTy = typeSplit(VecTy).first;
1372 MVT WordTy = tyVector(VecTy, MVT::i32);
1374 unsigned WordIdx = (Idx*ElemWidth) / 32;
1377 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1382 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1383 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1388HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1390 MVT VecTy = ty(VecV);
1391 unsigned HwLen = Subtarget.getVectorLength();
1399 unsigned Offset = Idx * BitBytes;
1401 SmallVector<int,128>
Mask;
1403 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1410 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1411 for (
unsigned j = 0;
j != Rep; ++
j)
1428 unsigned Rep = 8 / ResLen;
1431 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1433 for (
unsigned i = 0; i != ResLen; ++i) {
1434 for (
unsigned j = 0;
j != Rep; ++
j)
1446 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1447 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1452HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1454 MVT VecTy = ty(VecV);
1455 MVT SubTy = ty(SubV);
1456 unsigned HwLen = Subtarget.getVectorLength();
1460 bool IsPair = isHvxPairTy(VecTy);
1468 V0 = LoHalf(VecV, DAG);
1469 V1 = HiHalf(VecV, DAG);
1474 if (isHvxSingleTy(SubTy)) {
1476 unsigned Idx = CN->getZExtValue();
1478 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1501 if (!IdxN || !IdxN->isZero()) {
1509 unsigned RolBase = HwLen;
1512 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1517 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1520 SingleV = DAG.
getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1524 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1539HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1541 MVT VecTy = ty(VecV);
1542 MVT SubTy = ty(SubV);
1543 assert(Subtarget.isHVXVectorType(VecTy,
true));
1548 unsigned HwLen = Subtarget.getVectorLength();
1549 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1552 unsigned BitBytes = HwLen / VecLen;
1553 unsigned BlockLen = HwLen / Scale;
1557 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1561 if (!IdxN || !IdxN->isZero()) {
1570 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1572 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1574 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1576 if (!IdxN || !IdxN->isZero()) {
1585HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1590 assert(Subtarget.isHVXVectorType(ResTy));
1597 SDValue False = getZero(dl, ResTy, DAG);
1598 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1602HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1610 unsigned HwLen = Subtarget.getVectorLength();
1612 MVT PredTy = ty(VecQ);
1614 assert(HwLen % PredLen == 0);
1621 for (
unsigned i = 0; i != HwLen/8; ++i) {
1622 for (
unsigned j = 0;
j != 8; ++
j)
1623 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1626 Align Alignment(HwLen);
1636 getZero(dl, VecTy, DAG));
1642 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1644 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1651 SmallVector<int,128>
Mask;
1652 for (
unsigned i = 0; i != HwLen; ++i)
1653 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1663 MVT InpTy = ty(VecV);
1671 return InpWidth < ResWidth
1679 if (InpWidth < ResWidth) {
1681 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1683 unsigned NarOpc =
Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1689HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1693 const SDLoc &dl(Vec);
1702 const SDLoc &dl(
Op);
1707 for (
unsigned i = 0; i !=
Size; ++i)
1708 Ops.push_back(
Op.getOperand(i));
1711 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1719 for (
unsigned i = 0; i !=
Size; i++)
1730 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1732 MVT SingleTy = typeSplit(VecTy).first;
1733 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1734 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1738 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1744 const SDLoc &dl(
Op);
1746 MVT ArgTy = ty(
Op.getOperand(0));
1748 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1766 const SDLoc &dl(
Op);
1783 MVT NTy = typeLegalize(Ty, DAG);
1787 V.getOperand(0),
V.getOperand(1)),
1792 switch (
V.getOpcode()) {
1800 V =
V.getOperand(0);
1811 unsigned HwLen = Subtarget.getVectorLength();
1818 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1820 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, Op0,
Op.getOperand(1));
1826 MVT HalfTy = typeSplit(VecTy).first;
1828 Ops.take_front(NumOp/2));
1830 Ops.take_back(NumOp/2));
1831 return DAG.
getNode(HexagonISD::QCAT, dl, VecTy, V0, V1);
1839 for (
SDValue V :
Op.getNode()->op_values()) {
1840 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1844 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1847 SDValue Res = getZero(dl, ByteTy, DAG);
1848 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1861 const SDLoc &dl(
Op);
1863 if (ElemTy == MVT::i1)
1864 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1866 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1872 const SDLoc &dl(
Op);
1878 if (ElemTy == MVT::i1)
1879 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1881 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1883 tyVector(VecTy, MVT::i16),
1884 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1886 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1889 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1896 MVT SrcTy = ty(SrcV);
1902 const SDLoc &dl(
Op);
1905 if (ElemTy == MVT::i1)
1906 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1908 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1919 const SDLoc &dl(
Op);
1920 MVT VecTy = ty(VecV);
1922 if (ElemTy == MVT::i1)
1923 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1925 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1937 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1938 return LowerHvxSignExt(
Op, DAG);
1947 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1948 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1957 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1958 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1966 const SDLoc &dl(
Op);
1969 assert(ResTy == ty(InpV));
1994 const SDLoc &dl(
Op);
2001 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2002 unsigned Opc =
Op.getOpcode();
2006 return DAG.
getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).getValue(1);
2008 return DAG.
getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).getValue(1);
2018 const SDLoc &dl(
Op);
2019 unsigned Opc =
Op.getOpcode();
2024 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2031 bool SignedVu =
Opc == HexagonISD::SMUL_LOHI;
2032 bool SignedVv =
Opc == HexagonISD::SMUL_LOHI ||
Opc == HexagonISD::USMUL_LOHI;
2036 if (Subtarget.useHVXV62Ops())
2037 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2039 if (
Opc == HexagonISD::SMUL_LOHI) {
2042 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2043 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2049 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2056 MVT ValTy = ty(Val);
2057 const SDLoc &dl(
Op);
2060 unsigned HwLen = Subtarget.getVectorLength();
2062 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2077 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2079 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2084 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2085 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2098 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2099 assert(Val32.getValueType().getSizeInBits() == 32 &&
2100 "Input must be 32 bits");
2104 for (
unsigned i = 0; i < 32; ++i)
2112 if (ResTy == MVT::v32i1 &&
2113 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2114 Subtarget.useHVX128BOps()) {
2116 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2118 return bitcastI32ToV32I1(Val32);
2121 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2139 unsigned HwLen = Subtarget.getVectorLength();
2151 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2155 for (
unsigned J = 0; J != 8; ++J) {
2163 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2187 const SDLoc &dl(
Op);
2188 unsigned HwLen = Subtarget.getVectorLength();
2190 assert(HwLen % VecLen == 0);
2191 unsigned ElemSize = HwLen / VecLen;
2203 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2209HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2211 unsigned Opc =
Op.getOpcode();
2223 const SDLoc &dl(
Op);
2229 bool UseShifts = ElemTy != MVT::i8;
2230 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2233 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2241 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2247 DAG.
getNode(HexagonISD::VASL, dl, InpTy, {
A, IsLeft ? ModS : NegS});
2249 DAG.
getNode(HexagonISD::VLSR, dl, InpTy, {
B, IsLeft ? NegS : ModS});
2257 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2259 unsigned MOpc =
Opc ==
ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2266 const SDLoc &dl(
Op);
2267 unsigned IntNo =
Op.getConstantOperandVal(0);
2275 case Intrinsic::hexagon_V6_pred_typecast:
2276 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2277 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2278 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2285 case Intrinsic::hexagon_V6_vmpyss_parts:
2286 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2287 return Swap(DAG.
getNode(HexagonISD::SMUL_LOHI, dl,
Op->getVTList(),
2289 case Intrinsic::hexagon_V6_vmpyuu_parts:
2290 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2291 return Swap(DAG.
getNode(HexagonISD::UMUL_LOHI, dl,
Op->getVTList(),
2293 case Intrinsic::hexagon_V6_vmpyus_parts:
2294 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2295 return Swap(DAG.
getNode(HexagonISD::USMUL_LOHI, dl,
Op->getVTList(),
2305 const SDLoc &dl(
Op);
2306 unsigned HwLen = Subtarget.getVectorLength();
2310 SDValue Chain = MaskN->getChain();
2314 unsigned Opc =
Op->getOpcode();
2331 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2335 if (MaskN->getAlign().value() % HwLen == 0) {
2344 SDValue Z = getZero(dl, ty(V), DAG);
2348 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2349 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2350 return std::make_pair(LoV, HiV);
2356 VectorPair Tmp = StoreAlign(MaskV,
Base);
2359 VectorPair ValueU = StoreAlign(
Value,
Base);
2363 getInstr(StoreOpc, dl, MVT::Other,
2364 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2366 getInstr(StoreOpc, dl, MVT::Other,
2367 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2377 assert(Subtarget.useHVXQFloatOps());
2382 MVT ArgTy = ty(
Op.getOperand(0));
2383 const SDLoc &dl(
Op);
2385 if (ArgTy == MVT::v64bf16) {
2386 MVT HalfTy = typeSplit(VecTy).first;
2389 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2394 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2395 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2397 {VecPair.second, VecPair.first,
2403 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2412 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2414 MVT HalfTy = typeSplit(VecTy).first;
2415 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2417 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2419 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2422 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2435 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2438 if (Subtarget.useHVXIEEEFPOps()) {
2440 if (FpTy == MVT::f16) {
2442 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2444 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2450 return EqualizeFpIntConversion(
Op, DAG);
2452 return ExpandHvxFpToInt(
Op, DAG);
2468 MVT ResTy = ty(PredOp);
2469 const SDLoc &dl(PredOp);
2472 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2473 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2475 SDNode *PredTransfer =
2478 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2481 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2486 SDNode *IndexShift =
2492 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2517 MVT ResTy = ty(PredOp);
2518 const SDLoc &dl(PredOp);
2528 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2529 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2539 SDNode *PredTransfer =
2543 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2550 SDNode *IndexShift_hi =
2553 SDNode *IndexShift_lo =
2557 SDNode *MaskOff_hi =
2560 SDNode *MaskOff_lo =
2583 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2584 return LowerHvxPred32ToFp(
Op, DAG);
2585 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2586 return LowerHvxPred64ToFp(
Op, DAG);
2589 if (Subtarget.useHVXIEEEFPOps()) {
2591 if (FpTy == MVT::f16) {
2593 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2595 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2601 return EqualizeFpIntConversion(
Op, DAG);
2603 return ExpandHvxIntToFp(
Op, DAG);
2606HexagonTargetLowering::TypePair
2607HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2618 unsigned MaxWidth = std::max(Width0, Width1);
2620 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2627 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2628 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2632 return {WideETy0, WideETy1};
2643HexagonTargetLowering::TypePair
2644HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2654 unsigned MaxLen = std::max(Len0, Len1);
2667HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2668 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2677HexagonTargetLowering::VectorPair
2708HexagonTargetLowering::VectorPair
2709HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2714 const SDLoc &dl(Val);
2715 MVT ValTy = ty(Val);
2729 MVT IntTy = tyVector(ValTy, ElemTy);
2741 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2760 MVT
PairTy = typeJoin({VecTy, VecTy});
2786 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2788 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2796 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2798 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2801 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2802 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2803 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2814HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2815 bool SignedB,
const SDLoc &dl,
2818 MVT
PairTy = typeJoin({VecTy, VecTy});
2823 if (SignedA && !SignedB) {
2839 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2840 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2841 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2850 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2853 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2857 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2858 {HiHalf(P2, DAG), T3,
S16}, DAG);
2861 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2862 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2866 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2873 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2874 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2875 }
else if (SignedB) {
2881 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2883 assert(!SignedA && !SignedB);
2890HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2895 MVT
PairTy = typeJoin({VecTy, VecTy});
2898 if (SignedA && !SignedB) {
2907 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2912 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2924 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2925 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2926 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2927 }
else if (!SignedA) {
2937 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2955 unsigned Opc =
Op.getOpcode();
2960 MVT InpTy = ty(Inp);
2966 const SDLoc &dl(
Op);
2969 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2978 unsigned Opc =
Op.getOpcode();
2981 const SDLoc &dl(
Op);
2983 MVT InpTy = ty(Op0);
2996 if (InpTy == MVT::v64f16) {
2997 if (Subtarget.useHVXV81Ops()) {
3000 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3004 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3009 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3089 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3090 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3133 unsigned Opc =
Op.getOpcode();
3136 const SDLoc &dl(
Op);
3138 MVT InpTy = ty(Op0);
3171 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3181 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3204 unsigned Opc =
Op.getOpcode();
3221 const SDLoc &dl(
Op);
3222 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3231 unsigned Opc =
Op.getConstantOperandVal(2);
3235HexagonTargetLowering::VectorPair
3239 const SDLoc &dl(
Op);
3241 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3242 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3244 return std::make_pair(TV, TV);
3249 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3251 switch (
Op.getOpcode()) {
3252 case ISD::SIGN_EXTEND_INREG:
3253 case HexagonISD::SSAT:
3254 case HexagonISD::USAT:
3255 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3256 std::tie(Lo, Hi) = SplitVTNode(N);
3264 MVT HalfTy = typeSplit(ResTy).first;
3274 if (!MemN->getMemoryVT().isSimple())
3277 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3278 if (!isHvxPairTy(MemTy))
3281 const SDLoc &dl(
Op);
3282 unsigned HwLen = Subtarget.getVectorLength();
3283 MVT SingleTy = typeSplit(MemTy).first;
3284 SDValue Chain = MemN->getChain();
3285 SDValue Base0 = MemN->getBasePtr();
3290 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3291 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3320 assert(MaskN->isUnindexed());
3321 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3343 Masks.first, SingleTy, MOp0,
3346 Masks.second, SingleTy, MOp1,
3351 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3357 const SDLoc &dl(
Op);
3359 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3360 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3361 "Not widening loads of i1 yet");
3363 SDValue Chain = LoadN->getChain();
3368 unsigned HwLen = Subtarget.getVectorLength();
3370 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3373 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3381 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3389 const SDLoc &dl(
Op);
3391 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3392 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3393 "Not widening stores of i1 yet");
3395 SDValue Chain = StoreN->getChain();
3399 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3400 MVT ValueTy = ty(
Value);
3402 unsigned HwLen = Subtarget.getVectorLength();
3405 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3407 Len = ty(
Value).getVectorNumElements();
3409 assert(ty(
Value).getVectorNumElements() == HwLen);
3411 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3413 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3416 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3423 const SDLoc &dl(
Op);
3424 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3426 unsigned HwLen = Subtarget.getVectorLength();
3431 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3434 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3435 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3439 {WideOp0, WideOp1,
Op.getOperand(2)});
3441 EVT RetTy = typeLegalize(ty(
Op), DAG);
3443 {SetCC, getZero(dl, MVT::i32, DAG)});
3448 unsigned Opc =
Op.getOpcode();
3449 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3451 return isHvxPairTy(ty(V));
3462 return SplitHvxMemOp(
Op, DAG);
3467 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3468 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3498 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3503 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3504 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3527 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3529 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3549 case HexagonISD::SMUL_LOHI:
3550 case HexagonISD::UMUL_LOHI:
3551 case HexagonISD::USMUL_LOHI:
return LowerHvxMulLoHi(
Op, DAG);
3568 unsigned Opc =
Op.getOpcode();
3570 case HexagonISD::SSAT:
3571 case HexagonISD::USAT:
3588 MVT InpTy = ty(Inp);
3593 assert(InpWidth != ResWidth);
3595 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3598 const SDLoc &dl(
Op);
3602 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3605 case HexagonISD::SSAT:
3606 case HexagonISD::USAT:
3610 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3617 if (InpWidth < ResWidth) {
3619 while (InpWidth * 2 <= ResWidth)
3620 S = repeatOp(InpWidth *= 2, S);
3624 while (InpWidth / 2 >= ResWidth)
3625 S = repeatOp(InpWidth /= 2, S);
3633 MVT InpTy = ty(Inp0);
3637 unsigned Opc =
Op.getOpcode();
3639 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3644 auto [WInpTy, WResTy] =
3645 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3646 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3647 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3655 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3656 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3657 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3658 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3661 return RemoveTLWrapper(
Op, DAG);
3667HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3669 unsigned Opc =
N->getOpcode();
3672 if (
N->getNumOperands() > 0)
3673 Inp0 =
Op.getOperand(0);
3680 if (Subtarget.isHVXElementType(ty(
Op)) &&
3681 Subtarget.isHVXElementType(ty(Inp0))) {
3682 Results.push_back(CreateTLWrapper(
Op, DAG));
3686 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3699 if (isHvxPairTy(ty(
Op))) {
3707 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3716 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3717 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3721 case HexagonISD::SSAT:
3722 case HexagonISD::USAT:
3725 Results.push_back(LegalizeHvxResize(
Op, DAG));
3733HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3735 unsigned Opc =
N->getOpcode();
3738 if (
N->getNumOperands() > 0)
3739 Inp0 =
Op.getOperand(0);
3746 if (Subtarget.isHVXElementType(ty(
Op)) &&
3747 Subtarget.isHVXElementType(ty(Inp0))) {
3748 Results.push_back(CreateTLWrapper(
Op, DAG));
3752 if (shouldWidenToHvx(ty(
Op), DAG)) {
3758 if (shouldWidenToHvx(ty(
Op), DAG)) {
3767 if (isHvxBoolTy(ty(Inp0))) {
3774 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3775 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3779 case HexagonISD::SSAT:
3780 case HexagonISD::USAT:
3783 Results.push_back(LegalizeHvxResize(
Op, DAG));
3791HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3792 DAGCombinerInfo &DCI)
const {
3797 SelectionDAG &DAG = DCI.DAG;
3798 const SDLoc &dl(
Op);
3805 EVT TruncTy =
Op.getValueType();
3807 EVT SrcTy = Src.getValueType();
3814 if (2 * CastLen != SrcLen)
3817 SmallVector<int, 128>
Mask(SrcLen);
3818 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3820 Mask[i + CastLen] = 2 * i + 1;
3824 return opSplit(Deal, dl, DAG).first;
3828HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3829 SDValue Op, DAGCombinerInfo &DCI)
const {
3837 SelectionDAG &DAG = DCI.DAG;
3838 const SDLoc &dl(
Op);
3847 SetVector<SDValue> Order;
3853 if (Order.
size() > 2)
3862 SmallVector<int, 128> LongMask;
3863 auto AppendToMask = [&](
SDValue Shuffle) {
3865 ArrayRef<int>
Mask = SV->getMask();
3868 for (
int M : Mask) {
3873 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3874 if (
static_cast<unsigned>(M) >= InpLen)
3877 int OutOffset = Order[0] == Src ? 0 : InpLen;
3894HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3897 SelectionDAG &DAG = DCI.DAG;
3899 unsigned Opc =
Op.getOpcode();
3904 return combineTruncateBeforeLegal(
Op, DCI);
3906 return combineConcatVectorsBeforeLegal(
Op, DCI);
3908 if (DCI.isBeforeLegalizeOps())
3917 if (C1->
getOpcode() == HexagonISD::QTRUE)
3925 return C->isZero() ? DAG.
getNode(HexagonISD::QFALSE, dl, ty(
Op))
3926 : DAG.
getNode(HexagonISD::QTRUE, dl, ty(
Op));
3934 return getZero(dl, ty(
Op), DAG);
3936 case HexagonISD::VINSERTW0:
3937 if (isUndef(
Ops[1]))
3955HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3956 if (Subtarget.isHVXVectorType(Ty,
true))
3958 auto Action = getPreferredHvxVectorAction(Ty);
3960 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3965HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3966 if (Subtarget.isHVXVectorType(Ty,
true))
3968 auto Action = getPreferredHvxVectorAction(Ty);
3970 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3976 if (!Subtarget.useHVXOps())
3980 auto IsHvxTy = [
this](EVT Ty) {
3981 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
3984 return Op.getValueType().isSimple() &&
3985 Subtarget.isHVXVectorType(ty(
Op),
true);
3991 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3992 if (!
Op.getValueType().isSimple())
3995 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3998 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static cl::opt< unsigned > HvxWidenThreshold("hexagon-hvx-widen", cl::Hidden, cl::init(16), cl::desc("Lower threshold (in bytes) for widening to HVX vectors"))
static cl::opt< bool > EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false), cl::desc("Enable FP fast conversion routine."))
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
const SmallVectorImpl< MachineOperand > & Cond
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
uint64_t getNumOperands() const
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
EVT getSetCCResultType(const DataLayout &, LLVMContext &C, EVT VT) const override
Return the ValueType of the result of SETCC operations.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
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 & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Flags
Flags values. These may be or'd together.
unsigned getSubReg() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
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.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
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...
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)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
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 getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
size_type size() const
Determine the number of elements in the SetVector.
const value_type & front() const
Return the first element of the SetVector.
const value_type & back() const
Return the last element of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
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 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)
#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...
@ 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.
@ 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,...
@ Undef
Value of the register doesn't matter.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
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.