21#include "llvm/IR/IntrinsicsHexagon.h"
32 cl::desc(
"Lower threshold (in bytes) for widening to HVX vectors"));
34static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
35static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
36static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
37static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
42 switch (ElemTy.SimpleTy) {
44 return std::make_tuple(5, 15, 10);
46 return std::make_tuple(8, 127, 23);
48 return std::make_tuple(11, 1023, 52);
56HexagonTargetLowering::initializeHVXLowering() {
57 if (Subtarget.useHVX64BOps()) {
75 }
else if (Subtarget.useHVX128BOps()) {
85 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
91 if (Subtarget.useHVXV81Ops()) {
99 bool Use64b = Subtarget.useHVX64BOps();
102 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
103 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
104 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
106 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
124 if (Subtarget.useHVX128BOps()) {
128 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
129 Subtarget.useHVXFloatingPoint()) {
131 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
132 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
134 for (MVT
T : FloatV) {
169 if (Subtarget.useHVXV81Ops()) {
172 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
173 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
174 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
175 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
176 setPromoteTo(ISD::FMINNUM, MVT::v64bf16, MVT::v64f32);
177 setPromoteTo(ISD::FMAXNUM, MVT::v64bf16, MVT::v64f32);
193 for (MVT
P : FloatW) {
215 if (Subtarget.useHVXQFloatOps()) {
218 }
else if (Subtarget.useHVXIEEEFPOps()) {
224 for (MVT
T : LegalV) {
251 if (
T.getScalarType() != MVT::i32) {
260 if (
T.getScalarType() != MVT::i32) {
288 if (Subtarget.useHVXFloatingPoint()) {
305 for (MVT
T : LegalW) {
360 if (
T.getScalarType() != MVT::i32) {
365 if (Subtarget.useHVXFloatingPoint()) {
412 for (MVT
T : LegalW) {
429 for (MVT
T : LegalV) {
444 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
447 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
452 unsigned HwLen = Subtarget.getVectorLength();
453 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
454 if (ElemTy == MVT::i1)
456 int ElemWidth = ElemTy.getFixedSizeInBits();
457 int MaxElems = (8*HwLen) / ElemWidth;
458 for (
int N = 2;
N < MaxElems;
N *= 2) {
469 if (Subtarget.useHVXFloatingPoint()) {
492HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
499 unsigned HwLen = Subtarget.getVectorLength();
502 if (ElemTy == MVT::i1 && VecLen > HwLen)
508 if (ElemTy == MVT::i1) {
523 unsigned HwWidth = 8*HwLen;
524 if (VecWidth > 2*HwWidth)
530 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
539HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
540 unsigned Opc =
Op.getOpcode();
560HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
561 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
565 Tys.second.getVectorNumElements());
568HexagonTargetLowering::TypePair
569HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
572 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
574 return { HalfTy, HalfTy };
578HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
585HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
592HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
601HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
607HexagonTargetLowering::VectorPair
608HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
610 TypePair Tys = typeSplit(ty(Vec));
613 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
617HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
618 return Subtarget.isHVXVectorType(Ty) &&
623HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
624 return Subtarget.isHVXVectorType(Ty) &&
629HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
630 return Subtarget.isHVXVectorType(Ty,
true) &&
634bool HexagonTargetLowering::allowsHvxMemoryAccess(
642 if (!Subtarget.isHVXVectorType(VecTy,
false))
649bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
651 if (!Subtarget.isHVXVectorType(VecTy))
659void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
661 unsigned Opc =
MI.getOpcode();
662 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
663 MachineBasicBlock &MB = *
MI.getParent();
667 auto At =
MI.getIterator();
670 case Hexagon::PS_vsplatib:
671 if (Subtarget.useHVXV62Ops()) {
674 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
676 .
add(
MI.getOperand(1));
678 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
683 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
684 const MachineOperand &InpOp =
MI.getOperand(1);
686 uint32_t
V = InpOp.
getImm() & 0xFF;
688 .
addImm(V << 24 | V << 16 | V << 8 | V);
694 case Hexagon::PS_vsplatrb:
695 if (Subtarget.useHVXV62Ops()) {
698 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
699 .
add(
MI.getOperand(1));
701 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
702 const MachineOperand &InpOp =
MI.getOperand(1);
703 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
706 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
711 case Hexagon::PS_vsplatih:
712 if (Subtarget.useHVXV62Ops()) {
715 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
717 .
add(
MI.getOperand(1));
719 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
724 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
725 const MachineOperand &InpOp =
MI.getOperand(1);
727 uint32_t
V = InpOp.
getImm() & 0xFFFF;
735 case Hexagon::PS_vsplatrh:
736 if (Subtarget.useHVXV62Ops()) {
739 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
740 .
add(
MI.getOperand(1));
744 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
745 const MachineOperand &InpOp =
MI.getOperand(1);
746 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
754 case Hexagon::PS_vsplatiw:
755 case Hexagon::PS_vsplatrw:
756 if (
Opc == Hexagon::PS_vsplatiw) {
758 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
760 .
add(
MI.getOperand(1));
761 MI.getOperand(1).ChangeToRegister(SplatV,
false);
764 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
770HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
780 const SDLoc &dl(ElemIdx);
786HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
789 assert(ElemWidth >= 8 && ElemWidth <= 32);
793 if (ty(Idx) != MVT::i32)
795 const SDLoc &dl(Idx);
802HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
809 if (ElemTy == MVT::i8)
813 MVT ResTy = tyVector(OpTy, MVT::i8);
816 SmallVector<int,128> ByteMask;
819 for (
unsigned I = 0;
I != ElemSize; ++
I)
822 int NewM =
M*ElemSize;
823 for (
unsigned I = 0;
I != ElemSize; ++
I)
829 opCastElem(Op1, MVT::i8, DAG), ByteMask);
836 unsigned VecLen = Values.
size();
840 unsigned HwLen = Subtarget.getVectorLength();
842 unsigned ElemSize = ElemWidth / 8;
843 assert(ElemSize*VecLen == HwLen);
847 !(Subtarget.useHVXFloatingPoint() &&
849 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
850 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
852 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
853 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
861 unsigned NumValues = Values.size();
864 for (
unsigned i = 0; i != NumValues; ++i) {
865 if (Values[i].isUndef())
868 if (!SplatV.getNode())
870 else if (SplatV != Values[i])
878 unsigned NumWords = Words.
size();
880 bool IsSplat =
isSplat(Words, SplatV);
881 if (IsSplat && isUndef(SplatV))
886 return getZero(dl, VecTy, DAG);
895 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
898 (Constant**)Consts.end());
900 Align Alignment(HwLen);
914 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
915 SmallVectorImpl<int> &SrcIdx) {
919 SrcIdx.push_back(-1);
932 int I =
C->getSExtValue();
933 assert(
I >= 0 &&
"Negative element index");
940 SmallVector<int,128> ExtIdx;
942 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
943 MVT ExtTy = ty(ExtVec);
945 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
949 SmallVector<int,128>
Mask;
950 BitVector
Used(ExtLen);
952 for (
int M : ExtIdx) {
962 for (
unsigned I = 0;
I != ExtLen; ++
I) {
963 if (
Mask.size() == ExtLen)
971 return ExtLen == VecLen ? S : LoHalf(S, DAG);
979 assert(4*Words.
size() == Subtarget.getVectorLength());
982 for (
unsigned i = 0; i != NumWords; ++i) {
984 if (Words[i].isUndef())
986 for (
unsigned j = i;
j != NumWords; ++
j)
987 if (Words[i] == Words[j])
990 if (VecHist[i] > VecHist[n])
994 SDValue HalfV = getZero(dl, VecTy, DAG);
995 if (VecHist[n] > 1) {
998 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1010 for (
unsigned i = 0; i != NumWords/2; ++i) {
1012 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1016 {HalfV0, Words[i]});
1019 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1023 {HalfV1, Words[i+NumWords/2]});
1046HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1047 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1048 MVT PredTy = ty(PredV);
1049 unsigned HwLen = Subtarget.getVectorLength();
1052 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1062 SmallVector<int,128>
Mask(HwLen);
1067 for (
unsigned i = 0; i != HwLen; ++i) {
1068 unsigned Num = i % Scale;
1069 unsigned Off = i / Scale;
1078 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1080 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1087 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1096 if (Bytes < BitBytes) {
1102 while (Bytes < BitBytes) {
1104 Words[IdxW].
clear();
1107 for (
const SDValue &W : Words[IdxW ^ 1]) {
1108 SDValue T = expandPredicate(W, dl, DAG);
1113 for (
const SDValue &W : Words[IdxW ^ 1]) {
1121 while (Bytes > BitBytes) {
1123 Words[IdxW].
clear();
1126 for (
const SDValue &W : Words[IdxW ^ 1]) {
1127 SDValue T = contractPredicate(W, dl, DAG);
1131 for (
const SDValue &W : Words[IdxW ^ 1]) {
1138 assert(Bytes == BitBytes);
1139 if (BitBytes == 1 && PredTy == MVT::v2i1)
1142 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1144 for (
const SDValue &W : Words[IdxW]) {
1158 unsigned VecLen = Values.
size();
1159 unsigned HwLen = Subtarget.getVectorLength();
1160 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1162 bool AllT =
true, AllF =
true;
1166 return !
N->isZero();
1175 if (VecLen <= HwLen) {
1179 assert(HwLen % VecLen == 0);
1180 unsigned BitBytes = HwLen / VecLen;
1187 for (
unsigned B = 0;
B != BitBytes; ++
B)
1194 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1197 for (;
B != 8; ++
B) {
1198 if (!Values[
I+
B].isUndef())
1211 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1221 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1226HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1231 assert(ElemWidth >= 8 && ElemWidth <= 32);
1234 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1237 if (ElemTy == MVT::i32)
1243 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1246 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1250HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1253 assert(ResTy == MVT::i1);
1255 unsigned HwLen = Subtarget.getVectorLength();
1259 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1263 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1265 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1269HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1274 assert(ElemWidth >= 8 && ElemWidth <= 32);
1279 MVT VecTy = ty(VecV);
1280 unsigned HwLen = Subtarget.getVectorLength();
1292 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1293 if (ElemTy == MVT::i32)
1294 return InsertWord(VecV, ValV, ByteIdx);
1300 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1305 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1306 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1308 ValV, SubIdx, dl, ElemTy, DAG);
1311 return InsertWord(VecV, Ins, ByteIdx);
1315HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1317 unsigned HwLen = Subtarget.getVectorLength();
1321 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1326 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1331HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1333 MVT VecTy = ty(VecV);
1334 unsigned HwLen = Subtarget.getVectorLength();
1342 if (isHvxPairTy(VecTy)) {
1343 unsigned SubIdx = Hexagon::vsub_lo;
1344 if (Idx * ElemWidth >= 8 * HwLen) {
1345 SubIdx = Hexagon::vsub_hi;
1349 VecTy = typeSplit(VecTy).first;
1359 MVT WordTy = tyVector(VecTy, MVT::i32);
1361 unsigned WordIdx = (Idx*ElemWidth) / 32;
1364 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1369 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1370 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1375HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1377 MVT VecTy = ty(VecV);
1378 unsigned HwLen = Subtarget.getVectorLength();
1386 unsigned Offset = Idx * BitBytes;
1388 SmallVector<int,128>
Mask;
1390 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1397 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1398 for (
unsigned j = 0;
j != Rep; ++
j)
1415 unsigned Rep = 8 / ResLen;
1418 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1420 for (
unsigned i = 0; i != ResLen; ++i) {
1421 for (
unsigned j = 0;
j != Rep; ++
j)
1433 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1434 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1439HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1441 MVT VecTy = ty(VecV);
1442 MVT SubTy = ty(SubV);
1443 unsigned HwLen = Subtarget.getVectorLength();
1447 bool IsPair = isHvxPairTy(VecTy);
1455 V0 = LoHalf(VecV, DAG);
1456 V1 = HiHalf(VecV, DAG);
1461 if (isHvxSingleTy(SubTy)) {
1463 unsigned Idx = CN->getZExtValue();
1465 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1488 if (!IdxN || !IdxN->isZero()) {
1496 unsigned RolBase = HwLen;
1511 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1526HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1528 MVT VecTy = ty(VecV);
1529 MVT SubTy = ty(SubV);
1530 assert(Subtarget.isHVXVectorType(VecTy,
true));
1535 unsigned HwLen = Subtarget.getVectorLength();
1536 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1539 unsigned BitBytes = HwLen / VecLen;
1540 unsigned BlockLen = HwLen / Scale;
1544 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1548 if (!IdxN || !IdxN->isZero()) {
1557 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1559 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1561 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1563 if (!IdxN || !IdxN->isZero()) {
1572HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1577 assert(Subtarget.isHVXVectorType(ResTy));
1584 SDValue False = getZero(dl, ResTy, DAG);
1585 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1589HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1597 unsigned HwLen = Subtarget.getVectorLength();
1599 MVT PredTy = ty(VecQ);
1601 assert(HwLen % PredLen == 0);
1608 for (
unsigned i = 0; i != HwLen/8; ++i) {
1609 for (
unsigned j = 0;
j != 8; ++
j)
1610 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1613 Align Alignment(HwLen);
1622 getZero(dl, VecTy, DAG));
1628 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1630 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1637 SmallVector<int,128>
Mask;
1638 for (
unsigned i = 0; i != HwLen; ++i)
1639 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1649 MVT InpTy = ty(VecV);
1657 return InpWidth < ResWidth
1658 ? DAG.
getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1665 if (InpWidth < ResWidth) {
1667 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1675HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1679 const SDLoc &dl(Vec);
1688 const SDLoc &dl(
Op);
1693 for (
unsigned i = 0; i !=
Size; ++i)
1694 Ops.push_back(
Op.getOperand(i));
1697 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1705 for (
unsigned i = 0; i !=
Size; i++)
1716 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1718 MVT SingleTy = typeSplit(VecTy).first;
1719 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1720 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1724 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1730 const SDLoc &dl(
Op);
1732 MVT ArgTy = ty(
Op.getOperand(0));
1734 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1752 const SDLoc &dl(
Op);
1769 MVT NTy = typeLegalize(Ty, DAG);
1773 V.getOperand(0),
V.getOperand(1)),
1778 switch (
V.getOpcode()) {
1786 V =
V.getOperand(0);
1797 unsigned HwLen = Subtarget.getVectorLength();
1804 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1812 MVT HalfTy = typeSplit(VecTy).first;
1814 Ops.take_front(NumOp/2));
1816 Ops.take_back(NumOp/2));
1825 for (
SDValue V :
Op.getNode()->op_values()) {
1826 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1830 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1833 SDValue Res = getZero(dl, ByteTy, DAG);
1834 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1847 const SDLoc &dl(
Op);
1849 if (ElemTy == MVT::i1)
1850 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1852 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1858 const SDLoc &dl(
Op);
1864 if (ElemTy == MVT::i1)
1865 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1867 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1869 tyVector(VecTy, MVT::i16),
1870 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1872 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1875 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1882 MVT SrcTy = ty(SrcV);
1888 const SDLoc &dl(
Op);
1891 if (ElemTy == MVT::i1)
1892 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1894 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1905 const SDLoc &dl(
Op);
1906 MVT VecTy = ty(VecV);
1908 if (ElemTy == MVT::i1)
1909 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1911 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1923 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1924 return LowerHvxSignExt(
Op, DAG);
1933 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1934 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1943 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1944 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1952 const SDLoc &dl(
Op);
1955 assert(ResTy == ty(InpV));
1980 const SDLoc &dl(
Op);
1987 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
1988 unsigned Opc =
Op.getOpcode();
2004 const SDLoc &dl(
Op);
2005 unsigned Opc =
Op.getOpcode();
2010 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2022 if (Subtarget.useHVXV62Ops())
2023 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2028 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2029 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2035 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2042 MVT ValTy = ty(Val);
2043 const SDLoc &dl(
Op);
2046 unsigned HwLen = Subtarget.getVectorLength();
2048 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2063 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2065 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2070 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2071 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2084 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2085 assert(Val32.getValueType().getSizeInBits() == 32 &&
2086 "Input must be 32 bits");
2090 for (
unsigned i = 0; i < 32; ++i)
2098 if (ResTy == MVT::v32i1 &&
2099 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2100 Subtarget.useHVX128BOps()) {
2102 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2103 Val32 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Val);
2104 return bitcastI32ToV32I1(Val32);
2107 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2125 unsigned HwLen = Subtarget.getVectorLength();
2137 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2141 for (
unsigned J = 0; J != 8; ++J) {
2149 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2173 const SDLoc &dl(
Op);
2174 unsigned HwLen = Subtarget.getVectorLength();
2176 assert(HwLen % VecLen == 0);
2177 unsigned ElemSize = HwLen / VecLen;
2189 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2195HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2197 unsigned Opc =
Op.getOpcode();
2209 const SDLoc &dl(
Op);
2215 bool UseShifts = ElemTy != MVT::i8;
2216 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2219 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2227 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2243 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2252 const SDLoc &dl(
Op);
2253 unsigned IntNo =
Op.getConstantOperandVal(0);
2261 case Intrinsic::hexagon_V6_pred_typecast:
2262 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2263 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2264 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2271 case Intrinsic::hexagon_V6_vmpyss_parts:
2272 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2275 case Intrinsic::hexagon_V6_vmpyuu_parts:
2276 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2279 case Intrinsic::hexagon_V6_vmpyus_parts:
2280 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2291 const SDLoc &dl(
Op);
2292 unsigned HwLen = Subtarget.getVectorLength();
2296 SDValue Chain = MaskN->getChain();
2300 unsigned Opc =
Op->getOpcode();
2303 if (
Opc == ISD::MLOAD) {
2317 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2321 if (MaskN->getAlign().value() % HwLen == 0) {
2330 SDValue Z = getZero(dl, ty(V), DAG);
2334 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2335 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2336 return std::make_pair(LoV, HiV);
2342 VectorPair Tmp = StoreAlign(MaskV,
Base);
2345 VectorPair ValueU = StoreAlign(
Value,
Base);
2349 getInstr(StoreOpc, dl, MVT::Other,
2350 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2352 getInstr(StoreOpc, dl, MVT::Other,
2353 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2363 assert(Subtarget.useHVXQFloatOps());
2365 assert(
Op->getOpcode() == ISD::FP_EXTEND);
2368 MVT ArgTy = ty(
Op.getOperand(0));
2369 const SDLoc &dl(
Op);
2371 if (ArgTy == MVT::v64bf16) {
2372 MVT HalfTy = typeSplit(VecTy).first;
2375 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2380 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2381 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2383 {VecPair.second, VecPair.first,
2389 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2398 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2400 MVT HalfTy = typeSplit(VecTy).first;
2401 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2403 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2405 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2408 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2421 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2424 if (Subtarget.useHVXIEEEFPOps()) {
2426 if (FpTy == MVT::f16) {
2428 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2430 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2436 return EqualizeFpIntConversion(
Op, DAG);
2438 return ExpandHvxFpToInt(
Op, DAG);
2454 MVT ResTy = ty(PredOp);
2455 const SDLoc &dl(PredOp);
2458 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2459 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2461 SDNode *PredTransfer =
2464 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2467 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2472 SDNode *IndexShift =
2478 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2503 MVT ResTy = ty(PredOp);
2504 const SDLoc &dl(PredOp);
2514 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2515 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2520 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, HiReg));
2523 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, LoReg));
2525 SDNode *PredTransfer =
2529 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2536 SDNode *IndexShift_hi =
2539 SDNode *IndexShift_lo =
2543 SDNode *MaskOff_hi =
2546 SDNode *MaskOff_lo =
2569 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2570 return LowerHvxPred32ToFp(
Op, DAG);
2571 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2572 return LowerHvxPred64ToFp(
Op, DAG);
2575 if (Subtarget.useHVXIEEEFPOps()) {
2577 if (FpTy == MVT::f16) {
2579 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2581 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2587 return EqualizeFpIntConversion(
Op, DAG);
2589 return ExpandHvxIntToFp(
Op, DAG);
2592HexagonTargetLowering::TypePair
2593HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2604 unsigned MaxWidth = std::max(Width0, Width1);
2606 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2613 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2614 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2618 return {WideETy0, WideETy1};
2629HexagonTargetLowering::TypePair
2630HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2640 unsigned MaxLen = std::max(Len0, Len1);
2653HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2654 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2663HexagonTargetLowering::VectorPair
2694HexagonTargetLowering::VectorPair
2695HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2700 const SDLoc &dl(Val);
2701 MVT ValTy = ty(Val);
2715 MVT IntTy = tyVector(ValTy, ElemTy);
2727 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2746 MVT
PairTy = typeJoin({VecTy, VecTy});
2772 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2774 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2782 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2784 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2787 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2788 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2789 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2800HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2801 bool SignedB,
const SDLoc &dl,
2804 MVT
PairTy = typeJoin({VecTy, VecTy});
2809 if (SignedA && !SignedB) {
2825 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2826 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2827 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2836 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2839 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2843 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2844 {HiHalf(P2, DAG), T3,
S16}, DAG);
2847 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2848 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2852 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2859 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2860 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2861 }
else if (SignedB) {
2867 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2869 assert(!SignedA && !SignedB);
2876HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2881 MVT
PairTy = typeJoin({VecTy, VecTy});
2884 if (SignedA && !SignedB) {
2893 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2898 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2910 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2911 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2912 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2913 }
else if (!SignedA) {
2923 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2941 unsigned Opc =
Op.getOpcode();
2946 MVT InpTy = ty(Inp);
2952 const SDLoc &dl(
Op);
2955 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2964 unsigned Opc =
Op.getOpcode();
2967 const SDLoc &dl(
Op);
2969 MVT InpTy = ty(Op0);
3049 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3050 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3093 unsigned Opc =
Op.getOpcode();
3096 const SDLoc &dl(
Op);
3098 MVT InpTy = ty(Op0);
3131 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3141 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3164 unsigned Opc =
Op.getOpcode();
3181 const SDLoc &dl(
Op);
3182 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3191 unsigned Opc =
Op.getConstantOperandVal(2);
3195HexagonTargetLowering::VectorPair
3199 const SDLoc &dl(
Op);
3201 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3202 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3204 return std::make_pair(TV, TV);
3209 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3211 switch (
Op.getOpcode()) {
3212 case ISD::SIGN_EXTEND_INREG:
3213 case HexagonISD::SSAT:
3214 case HexagonISD::USAT:
3215 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3216 std::tie(Lo, Hi) = SplitVTNode(N);
3224 MVT HalfTy = typeSplit(ResTy).first;
3234 if (!MemN->getMemoryVT().isSimple())
3237 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3238 if (!isHvxPairTy(MemTy))
3241 const SDLoc &dl(
Op);
3242 unsigned HwLen = Subtarget.getVectorLength();
3243 MVT SingleTy = typeSplit(MemTy).first;
3244 SDValue Chain = MemN->getChain();
3245 SDValue Base0 = MemN->getBasePtr();
3250 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3251 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3253 uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3260 if (MemOpc == ISD::LOAD) {
3269 if (MemOpc == ISD::STORE) {
3277 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3280 assert(MaskN->isUnindexed());
3281 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3284 if (MemOpc == ISD::MLOAD) {
3300 if (MemOpc == ISD::MSTORE) {
3303 Masks.first, SingleTy, MOp0,
3306 Masks.second, SingleTy, MOp1,
3311 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3317 const SDLoc &dl(
Op);
3319 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3320 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3321 "Not widening loads of i1 yet");
3323 SDValue Chain = LoadN->getChain();
3328 unsigned HwLen = Subtarget.getVectorLength();
3330 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3333 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3341 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3349 const SDLoc &dl(
Op);
3351 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3352 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3353 "Not widening stores of i1 yet");
3355 SDValue Chain = StoreN->getChain();
3359 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3360 MVT ValueTy = ty(
Value);
3362 unsigned HwLen = Subtarget.getVectorLength();
3365 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3367 Len = ty(
Value).getVectorNumElements();
3369 assert(ty(
Value).getVectorNumElements() == HwLen);
3371 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3373 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3376 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3383 const SDLoc &dl(
Op);
3384 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3386 unsigned HwLen = Subtarget.getVectorLength();
3391 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3394 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3395 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3399 {WideOp0, WideOp1,
Op.getOperand(2)});
3401 EVT RetTy = typeLegalize(ty(
Op), DAG);
3403 {SetCC, getZero(dl, MVT::i32, DAG)});
3408 unsigned Opc =
Op.getOpcode();
3409 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3411 return isHvxPairTy(ty(V));
3422 return SplitHvxMemOp(
Op, DAG);
3427 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3428 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3438 case ISD::FMINIMUMNUM:
3439 case ISD::FMAXIMUMNUM:
3458 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3463 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3464 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3479 case ISD::BITCAST:
return LowerHvxBitcast(
Op, DAG);
3487 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3489 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3499 case ISD::MSTORE:
return LowerHvxMaskedOp(
Op, DAG);
3501 case ISD::LOAD:
return SDValue();
3502 case ISD::FP_EXTEND:
return LowerHvxFpExtend(
Op, DAG);
3528 unsigned Opc =
Op.getOpcode();
3548 MVT InpTy = ty(Inp);
3553 assert(InpWidth != ResWidth);
3555 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3558 const SDLoc &dl(
Op);
3562 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3570 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3577 if (InpWidth < ResWidth) {
3579 while (InpWidth * 2 <= ResWidth)
3580 S = repeatOp(InpWidth *= 2, S);
3584 while (InpWidth / 2 >= ResWidth)
3585 S = repeatOp(InpWidth /= 2, S);
3593 MVT InpTy = ty(Inp0);
3597 unsigned Opc =
Op.getOpcode();
3599 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3604 auto [WInpTy, WResTy] =
3605 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3606 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3607 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3615 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3616 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3617 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3618 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3621 return RemoveTLWrapper(
Op, DAG);
3627HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3629 unsigned Opc =
N->getOpcode();
3632 if (
N->getNumOperands() > 0)
3633 Inp0 =
Op.getOperand(0);
3640 if (Subtarget.isHVXElementType(ty(
Op)) &&
3641 Subtarget.isHVXElementType(ty(Inp0))) {
3642 Results.push_back(CreateTLWrapper(
Op, DAG));
3646 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3659 if (isHvxPairTy(ty(
Op))) {
3667 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3676 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3677 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3685 Results.push_back(LegalizeHvxResize(
Op, DAG));
3693HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3695 unsigned Opc =
N->getOpcode();
3698 if (
N->getNumOperands() > 0)
3699 Inp0 =
Op.getOperand(0);
3706 if (Subtarget.isHVXElementType(ty(
Op)) &&
3707 Subtarget.isHVXElementType(ty(Inp0))) {
3708 Results.push_back(CreateTLWrapper(
Op, DAG));
3712 if (shouldWidenToHvx(ty(
Op), DAG)) {
3718 if (shouldWidenToHvx(ty(
Op), DAG)) {
3727 if (isHvxBoolTy(ty(Inp0))) {
3734 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3735 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3743 Results.push_back(LegalizeHvxResize(
Op, DAG));
3751HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3752 DAGCombinerInfo &DCI)
const {
3757 SelectionDAG &DAG = DCI.DAG;
3758 const SDLoc &dl(
Op);
3760 if (
Op.getOperand(0).getOpcode() == ISD::BITCAST)
3765 EVT TruncTy =
Op.getValueType();
3767 EVT SrcTy = Src.getValueType();
3774 if (2 * CastLen != SrcLen)
3777 SmallVector<int, 128>
Mask(SrcLen);
3778 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3780 Mask[i + CastLen] = 2 * i + 1;
3784 return opSplit(Deal, dl, DAG).first;
3788HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3789 SDValue Op, DAGCombinerInfo &DCI)
const {
3797 SelectionDAG &DAG = DCI.DAG;
3798 const SDLoc &dl(
Op);
3807 SetVector<SDValue> Order;
3813 if (Order.
size() > 2)
3822 SmallVector<int, 128> LongMask;
3823 auto AppendToMask = [&](
SDValue Shuffle) {
3825 ArrayRef<int>
Mask = SV->getMask();
3828 for (
int M : Mask) {
3833 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3834 if (
static_cast<unsigned>(M) >= InpLen)
3837 int OutOffset = Order[0] == Src ? 0 : InpLen;
3854HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3857 SelectionDAG &DAG = DCI.DAG;
3859 unsigned Opc =
Op.getOpcode();
3864 return combineTruncateBeforeLegal(
Op, DCI);
3866 return combineConcatVectorsBeforeLegal(
Op, DCI);
3868 if (DCI.isBeforeLegalizeOps())
3894 return getZero(dl, ty(
Op), DAG);
3897 if (isUndef(
Ops[1]))
3915HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3916 if (Subtarget.isHVXVectorType(Ty,
true))
3918 auto Action = getPreferredHvxVectorAction(Ty);
3920 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3925HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3926 if (Subtarget.isHVXVectorType(Ty,
true))
3928 auto Action = getPreferredHvxVectorAction(Ty);
3930 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3936 if (!Subtarget.useHVXOps())
3940 auto IsHvxTy = [
this](EVT Ty) {
3941 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
3944 return Op.getValueType().isSimple() &&
3945 Subtarget.isHVXVectorType(ty(
Op),
true);
3951 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3952 if (!
Op.getValueType().isSimple())
3955 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3958 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"))
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 ...
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...
@ 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.
@ 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 ...
@ 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.
@ 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.
@ 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)...
@ 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.