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()) {
95 bool Use64b = Subtarget.useHVX64BOps();
98 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
99 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
100 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
102 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
120 if (Subtarget.useHVX128BOps()) {
124 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
125 Subtarget.useHVXFloatingPoint()) {
127 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
128 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
130 for (MVT
T : FloatV) {
165 for (MVT
P : FloatW) {
187 if (Subtarget.useHVXQFloatOps()) {
190 }
else if (Subtarget.useHVXIEEEFPOps()) {
196 for (MVT
T : LegalV) {
223 if (
T.getScalarType() != MVT::i32) {
232 if (
T.getScalarType() != MVT::i32) {
260 if (Subtarget.useHVXFloatingPoint()) {
277 for (MVT
T : LegalW) {
332 if (
T.getScalarType() != MVT::i32) {
337 if (Subtarget.useHVXFloatingPoint()) {
384 for (MVT
T : LegalW) {
401 for (MVT
T : LegalV) {
416 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
419 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
424 unsigned HwLen = Subtarget.getVectorLength();
425 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
426 if (ElemTy == MVT::i1)
428 int ElemWidth = ElemTy.getFixedSizeInBits();
429 int MaxElems = (8*HwLen) / ElemWidth;
430 for (
int N = 2;
N < MaxElems;
N *= 2) {
441 if (Subtarget.useHVXFloatingPoint()) {
464HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
467 unsigned HwLen = Subtarget.getVectorLength();
470 if (ElemTy == MVT::i1 && VecLen > HwLen)
476 if (ElemTy == MVT::i1) {
491 unsigned HwWidth = 8*HwLen;
492 if (VecWidth > 2*HwWidth)
498 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
507HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
508 unsigned Opc =
Op.getOpcode();
528HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
529 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
533 Tys.second.getVectorNumElements());
536HexagonTargetLowering::TypePair
537HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
540 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
542 return { HalfTy, HalfTy };
546HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
553HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
560HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
569HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
575HexagonTargetLowering::VectorPair
576HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
578 TypePair Tys = typeSplit(ty(Vec));
581 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
585HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
586 return Subtarget.isHVXVectorType(Ty) &&
591HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
592 return Subtarget.isHVXVectorType(Ty) &&
597HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
598 return Subtarget.isHVXVectorType(Ty,
true) &&
602bool HexagonTargetLowering::allowsHvxMemoryAccess(
610 if (!Subtarget.isHVXVectorType(VecTy,
false))
617bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
619 if (!Subtarget.isHVXVectorType(VecTy))
627void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
629 unsigned Opc =
MI.getOpcode();
630 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
631 MachineBasicBlock &MB = *
MI.getParent();
635 auto At =
MI.getIterator();
638 case Hexagon::PS_vsplatib:
639 if (Subtarget.useHVXV62Ops()) {
642 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
644 .
add(
MI.getOperand(1));
646 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
651 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
652 const MachineOperand &InpOp =
MI.getOperand(1);
654 uint32_t
V = InpOp.
getImm() & 0xFF;
656 .
addImm(V << 24 | V << 16 | V << 8 | V);
662 case Hexagon::PS_vsplatrb:
663 if (Subtarget.useHVXV62Ops()) {
666 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
667 .
add(
MI.getOperand(1));
669 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
670 const MachineOperand &InpOp =
MI.getOperand(1);
671 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
674 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
679 case Hexagon::PS_vsplatih:
680 if (Subtarget.useHVXV62Ops()) {
683 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
685 .
add(
MI.getOperand(1));
687 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
692 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
693 const MachineOperand &InpOp =
MI.getOperand(1);
695 uint32_t
V = InpOp.
getImm() & 0xFFFF;
703 case Hexagon::PS_vsplatrh:
704 if (Subtarget.useHVXV62Ops()) {
707 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
708 .
add(
MI.getOperand(1));
712 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
713 const MachineOperand &InpOp =
MI.getOperand(1);
714 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
722 case Hexagon::PS_vsplatiw:
723 case Hexagon::PS_vsplatrw:
724 if (
Opc == Hexagon::PS_vsplatiw) {
726 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
728 .
add(
MI.getOperand(1));
729 MI.getOperand(1).ChangeToRegister(SplatV,
false);
732 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
738HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
748 const SDLoc &dl(ElemIdx);
754HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
757 assert(ElemWidth >= 8 && ElemWidth <= 32);
761 if (ty(Idx) != MVT::i32)
763 const SDLoc &dl(Idx);
770HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
777 if (ElemTy == MVT::i8)
781 MVT ResTy = tyVector(OpTy, MVT::i8);
784 SmallVector<int,128> ByteMask;
787 for (
unsigned I = 0;
I != ElemSize; ++
I)
790 int NewM =
M*ElemSize;
791 for (
unsigned I = 0;
I != ElemSize; ++
I)
797 opCastElem(Op1, MVT::i8, DAG), ByteMask);
804 unsigned VecLen = Values.
size();
808 unsigned HwLen = Subtarget.getVectorLength();
810 unsigned ElemSize = ElemWidth / 8;
811 assert(ElemSize*VecLen == HwLen);
815 !(Subtarget.useHVXFloatingPoint() &&
817 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
818 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
820 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
821 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
829 unsigned NumValues = Values.size();
832 for (
unsigned i = 0; i != NumValues; ++i) {
833 if (Values[i].isUndef())
836 if (!SplatV.getNode())
838 else if (SplatV != Values[i])
846 unsigned NumWords = Words.
size();
848 bool IsSplat =
isSplat(Words, SplatV);
849 if (IsSplat && isUndef(SplatV))
854 return getZero(dl, VecTy, DAG);
863 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
866 (Constant**)Consts.end());
868 Align Alignment(HwLen);
882 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
883 SmallVectorImpl<int> &SrcIdx) {
887 SrcIdx.push_back(-1);
900 int I =
C->getSExtValue();
901 assert(
I >= 0 &&
"Negative element index");
908 SmallVector<int,128> ExtIdx;
910 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
911 MVT ExtTy = ty(ExtVec);
913 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
917 SmallVector<int,128>
Mask;
918 BitVector
Used(ExtLen);
920 for (
int M : ExtIdx) {
930 for (
unsigned I = 0;
I != ExtLen; ++
I) {
931 if (
Mask.size() == ExtLen)
939 return ExtLen == VecLen ? S : LoHalf(S, DAG);
947 assert(4*Words.
size() == Subtarget.getVectorLength());
950 for (
unsigned i = 0; i != NumWords; ++i) {
952 if (Words[i].isUndef())
954 for (
unsigned j = i;
j != NumWords; ++
j)
955 if (Words[i] == Words[j])
958 if (VecHist[i] > VecHist[n])
962 SDValue HalfV = getZero(dl, VecTy, DAG);
963 if (VecHist[n] > 1) {
966 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
978 for (
unsigned i = 0; i != NumWords/2; ++i) {
980 if (Words[i] != Words[n] || VecHist[n] <= 1) {
987 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
991 {HalfV1, Words[i+NumWords/2]});
1014HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1015 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1016 MVT PredTy = ty(PredV);
1017 unsigned HwLen = Subtarget.getVectorLength();
1020 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1030 SmallVector<int,128>
Mask(HwLen);
1035 for (
unsigned i = 0; i != HwLen; ++i) {
1036 unsigned Num = i % Scale;
1037 unsigned Off = i / Scale;
1046 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1048 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1055 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1064 if (Bytes < BitBytes) {
1070 while (Bytes < BitBytes) {
1072 Words[IdxW].
clear();
1075 for (
const SDValue &W : Words[IdxW ^ 1]) {
1076 SDValue T = expandPredicate(W, dl, DAG);
1081 for (
const SDValue &W : Words[IdxW ^ 1]) {
1089 while (Bytes > BitBytes) {
1091 Words[IdxW].
clear();
1094 for (
const SDValue &W : Words[IdxW ^ 1]) {
1095 SDValue T = contractPredicate(W, dl, DAG);
1099 for (
const SDValue &W : Words[IdxW ^ 1]) {
1106 assert(Bytes == BitBytes);
1107 if (BitBytes == 1 && PredTy == MVT::v2i1)
1110 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1112 for (
const SDValue &W : Words[IdxW]) {
1126 unsigned VecLen = Values.
size();
1127 unsigned HwLen = Subtarget.getVectorLength();
1128 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1130 bool AllT =
true, AllF =
true;
1134 return !
N->isZero();
1143 if (VecLen <= HwLen) {
1147 assert(HwLen % VecLen == 0);
1148 unsigned BitBytes = HwLen / VecLen;
1155 for (
unsigned B = 0;
B != BitBytes; ++
B)
1162 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1165 for (;
B != 8; ++
B) {
1166 if (!Values[
I+
B].isUndef())
1179 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1189 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1194HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1199 assert(ElemWidth >= 8 && ElemWidth <= 32);
1202 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1205 if (ElemTy == MVT::i32)
1211 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1214 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1218HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1221 assert(ResTy == MVT::i1);
1223 unsigned HwLen = Subtarget.getVectorLength();
1227 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1231 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1233 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1237HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1242 assert(ElemWidth >= 8 && ElemWidth <= 32);
1247 MVT VecTy = ty(VecV);
1248 unsigned HwLen = Subtarget.getVectorLength();
1260 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1261 if (ElemTy == MVT::i32)
1262 return InsertWord(VecV, ValV, ByteIdx);
1268 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1273 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1274 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1276 ValV, SubIdx, dl, ElemTy, DAG);
1279 return InsertWord(VecV, Ins, ByteIdx);
1283HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1285 unsigned HwLen = Subtarget.getVectorLength();
1289 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1294 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1299HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1301 MVT VecTy = ty(VecV);
1302 unsigned HwLen = Subtarget.getVectorLength();
1310 if (isHvxPairTy(VecTy)) {
1311 unsigned SubIdx = Hexagon::vsub_lo;
1312 if (Idx * ElemWidth >= 8 * HwLen) {
1313 SubIdx = Hexagon::vsub_hi;
1317 VecTy = typeSplit(VecTy).first;
1327 MVT WordTy = tyVector(VecTy, MVT::i32);
1329 unsigned WordIdx = (Idx*ElemWidth) / 32;
1332 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1337 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1338 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1343HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1345 MVT VecTy = ty(VecV);
1346 unsigned HwLen = Subtarget.getVectorLength();
1354 unsigned Offset = Idx * BitBytes;
1356 SmallVector<int,128>
Mask;
1358 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1365 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1366 for (
unsigned j = 0;
j != Rep; ++
j)
1383 unsigned Rep = 8 / ResLen;
1386 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1388 for (
unsigned i = 0; i != ResLen; ++i) {
1389 for (
unsigned j = 0;
j != Rep; ++
j)
1401 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1402 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1407HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1409 MVT VecTy = ty(VecV);
1410 MVT SubTy = ty(SubV);
1411 unsigned HwLen = Subtarget.getVectorLength();
1415 bool IsPair = isHvxPairTy(VecTy);
1423 V0 = LoHalf(VecV, DAG);
1424 V1 = HiHalf(VecV, DAG);
1429 if (isHvxSingleTy(SubTy)) {
1431 unsigned Idx = CN->getZExtValue();
1433 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1456 if (!IdxN || !IdxN->isZero()) {
1464 unsigned RolBase = HwLen;
1479 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1494HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1496 MVT VecTy = ty(VecV);
1497 MVT SubTy = ty(SubV);
1498 assert(Subtarget.isHVXVectorType(VecTy,
true));
1503 unsigned HwLen = Subtarget.getVectorLength();
1504 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1507 unsigned BitBytes = HwLen / VecLen;
1508 unsigned BlockLen = HwLen / Scale;
1512 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1516 if (!IdxN || !IdxN->isZero()) {
1525 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1527 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1529 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1531 if (!IdxN || !IdxN->isZero()) {
1540HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1545 assert(Subtarget.isHVXVectorType(ResTy));
1552 SDValue False = getZero(dl, ResTy, DAG);
1553 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1557HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1565 unsigned HwLen = Subtarget.getVectorLength();
1567 MVT PredTy = ty(VecQ);
1569 assert(HwLen % PredLen == 0);
1576 for (
unsigned i = 0; i != HwLen/8; ++i) {
1577 for (
unsigned j = 0;
j != 8; ++
j)
1578 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1581 Align Alignment(HwLen);
1590 getZero(dl, VecTy, DAG));
1596 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1598 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1605 SmallVector<int,128>
Mask;
1606 for (
unsigned i = 0; i != HwLen; ++i)
1607 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1617 MVT InpTy = ty(VecV);
1625 return InpWidth < ResWidth
1626 ? DAG.
getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1633 if (InpWidth < ResWidth) {
1635 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1643HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1647 const SDLoc &dl(Vec);
1656 const SDLoc &dl(
Op);
1661 for (
unsigned i = 0; i !=
Size; ++i)
1662 Ops.push_back(
Op.getOperand(i));
1665 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1672 for (
unsigned i = 0; i !=
Size; i++)
1676 tyVector(VecTy, MVT::i16), NewOps);
1677 return DAG.
getBitcast(tyVector(VecTy, MVT::f16), T0);
1683 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1685 MVT SingleTy = typeSplit(VecTy).first;
1686 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1687 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1691 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1697 const SDLoc &dl(
Op);
1699 MVT ArgTy = ty(
Op.getOperand(0));
1701 if (ArgTy == MVT::f16) {
1719 const SDLoc &dl(
Op);
1736 MVT NTy = typeLegalize(Ty, DAG);
1740 V.getOperand(0),
V.getOperand(1)),
1745 switch (
V.getOpcode()) {
1753 V =
V.getOperand(0);
1764 unsigned HwLen = Subtarget.getVectorLength();
1771 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1779 MVT HalfTy = typeSplit(VecTy).first;
1781 Ops.take_front(NumOp/2));
1783 Ops.take_back(NumOp/2));
1792 for (
SDValue V :
Op.getNode()->op_values()) {
1793 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1797 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1800 SDValue Res = getZero(dl, ByteTy, DAG);
1801 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1814 const SDLoc &dl(
Op);
1816 if (ElemTy == MVT::i1)
1817 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1819 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1825 const SDLoc &dl(
Op);
1831 if (ElemTy == MVT::i1)
1832 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1834 if (ElemTy == MVT::f16) {
1836 tyVector(VecTy, MVT::i16),
1837 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1839 return DAG.
getBitcast(tyVector(VecTy, MVT::f16), T0);
1842 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1849 MVT SrcTy = ty(SrcV);
1855 const SDLoc &dl(
Op);
1858 if (ElemTy == MVT::i1)
1859 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1861 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1872 const SDLoc &dl(
Op);
1873 MVT VecTy = ty(VecV);
1875 if (ElemTy == MVT::i1)
1876 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1878 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1890 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1891 return LowerHvxSignExt(
Op, DAG);
1900 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1901 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1910 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1911 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1919 const SDLoc &dl(
Op);
1922 assert(ResTy == ty(InpV));
1947 const SDLoc &dl(
Op);
1954 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
1955 unsigned Opc =
Op.getOpcode();
1971 const SDLoc &dl(
Op);
1972 unsigned Opc =
Op.getOpcode();
1977 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
1989 if (Subtarget.useHVXV62Ops())
1990 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1995 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
1996 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2002 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2009 MVT ValTy = ty(Val);
2010 const SDLoc &dl(
Op);
2013 unsigned HwLen = Subtarget.getVectorLength();
2015 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2030 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2032 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2037 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2038 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2051 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2052 assert(Val32.getValueType().getSizeInBits() == 32 &&
2053 "Input must be 32 bits");
2057 for (
unsigned i = 0; i < 32; ++i)
2065 if (ResTy == MVT::v32i1 &&
2066 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2067 Subtarget.useHVX128BOps()) {
2069 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2070 Val32 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Val);
2071 return bitcastI32ToV32I1(Val32);
2074 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2092 unsigned HwLen = Subtarget.getVectorLength();
2104 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2108 for (
unsigned J = 0; J != 8; ++J) {
2116 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2140 const SDLoc &dl(
Op);
2141 unsigned HwLen = Subtarget.getVectorLength();
2143 assert(HwLen % VecLen == 0);
2144 unsigned ElemSize = HwLen / VecLen;
2156 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2162HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2164 unsigned Opc =
Op.getOpcode();
2176 const SDLoc &dl(
Op);
2182 bool UseShifts = ElemTy != MVT::i8;
2183 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2186 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2194 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2210 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2219 const SDLoc &dl(
Op);
2220 unsigned IntNo =
Op.getConstantOperandVal(0);
2228 case Intrinsic::hexagon_V6_pred_typecast:
2229 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2230 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2231 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2238 case Intrinsic::hexagon_V6_vmpyss_parts:
2239 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2242 case Intrinsic::hexagon_V6_vmpyuu_parts:
2243 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2246 case Intrinsic::hexagon_V6_vmpyus_parts:
2247 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2258 const SDLoc &dl(
Op);
2259 unsigned HwLen = Subtarget.getVectorLength();
2263 SDValue Chain = MaskN->getChain();
2267 unsigned Opc =
Op->getOpcode();
2270 if (
Opc == ISD::MLOAD) {
2284 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2288 if (MaskN->getAlign().value() % HwLen == 0) {
2297 SDValue Z = getZero(dl, ty(V), DAG);
2301 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2302 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2303 return std::make_pair(LoV, HiV);
2309 VectorPair Tmp = StoreAlign(MaskV,
Base);
2312 VectorPair ValueU = StoreAlign(
Value,
Base);
2316 getInstr(StoreOpc, dl, MVT::Other,
2317 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2319 getInstr(StoreOpc, dl, MVT::Other,
2320 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2330 assert(Subtarget.useHVXQFloatOps());
2332 assert(
Op->getOpcode() == ISD::FP_EXTEND);
2335 MVT ArgTy = ty(
Op.getOperand(0));
2336 const SDLoc &dl(
Op);
2337 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2346 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2348 MVT HalfTy = typeSplit(VecTy).first;
2349 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2351 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2353 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2356 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2369 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2372 if (Subtarget.useHVXIEEEFPOps()) {
2374 if (FpTy == MVT::f16) {
2376 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2378 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2384 return EqualizeFpIntConversion(
Op, DAG);
2386 return ExpandHvxFpToInt(
Op, DAG);
2402 MVT ResTy = ty(PredOp);
2403 const SDLoc &dl(PredOp);
2406 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2407 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2409 SDNode *PredTransfer =
2412 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2415 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2420 SDNode *IndexShift =
2426 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2451 MVT ResTy = ty(PredOp);
2452 const SDLoc &dl(PredOp);
2462 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2463 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2468 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, HiReg));
2471 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, LoReg));
2473 SDNode *PredTransfer =
2477 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2484 SDNode *IndexShift_hi =
2487 SDNode *IndexShift_lo =
2491 SDNode *MaskOff_hi =
2494 SDNode *MaskOff_lo =
2517 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2518 return LowerHvxPred32ToFp(
Op, DAG);
2519 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2520 return LowerHvxPred64ToFp(
Op, DAG);
2523 if (Subtarget.useHVXIEEEFPOps()) {
2525 if (FpTy == MVT::f16) {
2527 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2529 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2535 return EqualizeFpIntConversion(
Op, DAG);
2537 return ExpandHvxIntToFp(
Op, DAG);
2540HexagonTargetLowering::TypePair
2541HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2552 unsigned MaxWidth = std::max(Width0, Width1);
2554 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2561 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2562 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2566 return {WideETy0, WideETy1};
2577HexagonTargetLowering::TypePair
2578HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2588 unsigned MaxLen = std::max(Len0, Len1);
2601HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2602 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2611HexagonTargetLowering::VectorPair
2642HexagonTargetLowering::VectorPair
2643HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2648 const SDLoc &dl(Val);
2649 MVT ValTy = ty(Val);
2663 MVT IntTy = tyVector(ValTy, ElemTy);
2675 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2694 MVT
PairTy = typeJoin({VecTy, VecTy});
2720 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2722 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2730 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2732 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2735 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2736 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2737 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2748HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2749 bool SignedB,
const SDLoc &dl,
2752 MVT
PairTy = typeJoin({VecTy, VecTy});
2757 if (SignedA && !SignedB) {
2773 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2774 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2775 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2784 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2787 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2791 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2792 {HiHalf(P2, DAG), T3,
S16}, DAG);
2795 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2796 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2800 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2807 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2808 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2809 }
else if (SignedB) {
2815 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2817 assert(!SignedA && !SignedB);
2824HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2829 MVT
PairTy = typeJoin({VecTy, VecTy});
2832 if (SignedA && !SignedB) {
2841 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2846 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2858 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2859 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2860 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2861 }
else if (!SignedA) {
2871 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2889 unsigned Opc =
Op.getOpcode();
2894 MVT InpTy = ty(Inp);
2900 const SDLoc &dl(
Op);
2903 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2912 unsigned Opc =
Op.getOpcode();
2915 const SDLoc &dl(
Op);
2917 MVT InpTy = ty(Op0);
2997 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
2998 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3041 unsigned Opc =
Op.getOpcode();
3044 const SDLoc &dl(
Op);
3046 MVT InpTy = ty(Op0);
3079 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3089 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3112 unsigned Opc =
Op.getOpcode();
3129 const SDLoc &dl(
Op);
3130 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3139 unsigned Opc =
Op.getConstantOperandVal(2);
3143HexagonTargetLowering::VectorPair
3147 const SDLoc &dl(
Op);
3149 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3150 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3152 return std::make_pair(TV, TV);
3157 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3159 switch (
Op.getOpcode()) {
3160 case ISD::SIGN_EXTEND_INREG:
3161 case HexagonISD::SSAT:
3162 case HexagonISD::USAT:
3163 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3164 std::tie(Lo, Hi) = SplitVTNode(N);
3172 MVT HalfTy = typeSplit(ResTy).first;
3182 if (!MemN->getMemoryVT().isSimple())
3185 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3186 if (!isHvxPairTy(MemTy))
3189 const SDLoc &dl(
Op);
3190 unsigned HwLen = Subtarget.getVectorLength();
3191 MVT SingleTy = typeSplit(MemTy).first;
3192 SDValue Chain = MemN->getChain();
3193 SDValue Base0 = MemN->getBasePtr();
3198 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3199 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3201 uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3208 if (MemOpc == ISD::LOAD) {
3217 if (MemOpc == ISD::STORE) {
3225 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3228 assert(MaskN->isUnindexed());
3229 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3232 if (MemOpc == ISD::MLOAD) {
3248 if (MemOpc == ISD::MSTORE) {
3251 Masks.first, SingleTy, MOp0,
3254 Masks.second, SingleTy, MOp1,
3259 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3265 const SDLoc &dl(
Op);
3267 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3268 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3269 "Not widening loads of i1 yet");
3271 SDValue Chain = LoadN->getChain();
3276 unsigned HwLen = Subtarget.getVectorLength();
3278 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3281 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3289 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3297 const SDLoc &dl(
Op);
3299 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3300 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3301 "Not widening stores of i1 yet");
3303 SDValue Chain = StoreN->getChain();
3307 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3308 MVT ValueTy = ty(
Value);
3310 unsigned HwLen = Subtarget.getVectorLength();
3313 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3315 Len = ty(
Value).getVectorNumElements();
3317 assert(ty(
Value).getVectorNumElements() == HwLen);
3319 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3321 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3324 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3331 const SDLoc &dl(
Op);
3332 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3334 unsigned HwLen = Subtarget.getVectorLength();
3339 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3342 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3343 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3347 {WideOp0, WideOp1,
Op.getOperand(2)});
3349 EVT RetTy = typeLegalize(ty(
Op), DAG);
3351 {SetCC, getZero(dl, MVT::i32, DAG)});
3356 unsigned Opc =
Op.getOpcode();
3357 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3359 return isHvxPairTy(ty(V));
3370 return SplitHvxMemOp(
Op, DAG);
3375 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3376 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3386 case ISD::FMINIMUMNUM:
3387 case ISD::FMAXIMUMNUM:
3406 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3411 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3412 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3427 case ISD::BITCAST:
return LowerHvxBitcast(
Op, DAG);
3435 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3437 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3447 case ISD::MSTORE:
return LowerHvxMaskedOp(
Op, DAG);
3449 case ISD::LOAD:
return SDValue();
3450 case ISD::FP_EXTEND:
return LowerHvxFpExtend(
Op, DAG);
3476 unsigned Opc =
Op.getOpcode();
3496 MVT InpTy = ty(Inp);
3501 assert(InpWidth != ResWidth);
3503 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3506 const SDLoc &dl(
Op);
3510 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3518 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3525 if (InpWidth < ResWidth) {
3527 while (InpWidth * 2 <= ResWidth)
3528 S = repeatOp(InpWidth *= 2, S);
3532 while (InpWidth / 2 >= ResWidth)
3533 S = repeatOp(InpWidth /= 2, S);
3541 MVT InpTy = ty(Inp0);
3545 unsigned Opc =
Op.getOpcode();
3547 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3552 auto [WInpTy, WResTy] =
3553 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3554 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3555 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3563 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3564 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3565 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3566 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3569 return RemoveTLWrapper(
Op, DAG);
3575HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3577 unsigned Opc =
N->getOpcode();
3580 if (
N->getNumOperands() > 0)
3581 Inp0 =
Op.getOperand(0);
3588 if (Subtarget.isHVXElementType(ty(
Op)) &&
3589 Subtarget.isHVXElementType(ty(Inp0))) {
3590 Results.push_back(CreateTLWrapper(
Op, DAG));
3594 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3607 if (isHvxPairTy(ty(
Op))) {
3615 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3624 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3625 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3633 Results.push_back(LegalizeHvxResize(
Op, DAG));
3641HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3643 unsigned Opc =
N->getOpcode();
3646 if (
N->getNumOperands() > 0)
3647 Inp0 =
Op.getOperand(0);
3654 if (Subtarget.isHVXElementType(ty(
Op)) &&
3655 Subtarget.isHVXElementType(ty(Inp0))) {
3656 Results.push_back(CreateTLWrapper(
Op, DAG));
3660 if (shouldWidenToHvx(ty(
Op), DAG)) {
3666 if (shouldWidenToHvx(ty(
Op), DAG)) {
3675 if (isHvxBoolTy(ty(Inp0))) {
3682 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3683 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3691 Results.push_back(LegalizeHvxResize(
Op, DAG));
3699HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3700 DAGCombinerInfo &DCI)
const {
3705 SelectionDAG &DAG = DCI.DAG;
3706 const SDLoc &dl(
Op);
3708 if (
Op.getOperand(0).getOpcode() == ISD::BITCAST)
3713 EVT TruncTy =
Op.getValueType();
3715 EVT SrcTy = Src.getValueType();
3722 if (2 * CastLen != SrcLen)
3725 SmallVector<int, 128>
Mask(SrcLen);
3726 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3728 Mask[i + CastLen] = 2 * i + 1;
3732 return opSplit(Deal, dl, DAG).first;
3736HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3737 SDValue Op, DAGCombinerInfo &DCI)
const {
3745 SelectionDAG &DAG = DCI.DAG;
3746 const SDLoc &dl(
Op);
3755 SetVector<SDValue> Order;
3761 if (Order.
size() > 2)
3770 SmallVector<int, 128> LongMask;
3771 auto AppendToMask = [&](
SDValue Shuffle) {
3773 ArrayRef<int>
Mask = SV->getMask();
3776 for (
int M : Mask) {
3781 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3782 if (
static_cast<unsigned>(M) >= InpLen)
3785 int OutOffset = Order[0] == Src ? 0 : InpLen;
3802HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3805 SelectionDAG &DAG = DCI.DAG;
3807 unsigned Opc =
Op.getOpcode();
3812 return combineTruncateBeforeLegal(
Op, DCI);
3814 return combineConcatVectorsBeforeLegal(
Op, DCI);
3816 if (DCI.isBeforeLegalizeOps())
3842 return getZero(dl, ty(
Op), DAG);
3845 if (isUndef(
Ops[1]))
3863HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3864 if (Subtarget.isHVXVectorType(Ty,
true))
3866 auto Action = getPreferredHvxVectorAction(Ty);
3868 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3873HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3874 if (Subtarget.isHVXVectorType(Ty,
true))
3876 auto Action = getPreferredHvxVectorAction(Ty);
3878 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3884 if (!Subtarget.useHVXOps())
3888 auto IsHvxTy = [
this](EVT Ty) {
3889 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
3892 return Op.getValueType().isSimple() &&
3893 Subtarget.isHVXVectorType(ty(
Op),
true);
3899 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3900 if (!
Op.getValueType().isSimple())
3903 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3906 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.