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);
1067 while (Bytes < BitBytes) {
1069 Words[IdxW].
clear();
1072 for (
const SDValue &W : Words[IdxW ^ 1]) {
1073 SDValue T = expandPredicate(W, dl, DAG);
1078 for (
const SDValue &W : Words[IdxW ^ 1]) {
1086 assert(Bytes == BitBytes);
1088 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1090 for (
const SDValue &W : Words[IdxW]) {
1104 unsigned VecLen = Values.
size();
1105 unsigned HwLen = Subtarget.getVectorLength();
1106 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1108 bool AllT =
true, AllF =
true;
1112 return !
N->isZero();
1121 if (VecLen <= HwLen) {
1125 assert(HwLen % VecLen == 0);
1126 unsigned BitBytes = HwLen / VecLen;
1133 for (
unsigned B = 0;
B != BitBytes; ++
B)
1140 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1143 for (;
B != 8; ++
B) {
1144 if (!Values[
I+
B].isUndef())
1157 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1167 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1172HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1177 assert(ElemWidth >= 8 && ElemWidth <= 32);
1180 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1183 if (ElemTy == MVT::i32)
1189 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1192 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1196HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1199 assert(ResTy == MVT::i1);
1201 unsigned HwLen = Subtarget.getVectorLength();
1205 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1209 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1211 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1215HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1220 assert(ElemWidth >= 8 && ElemWidth <= 32);
1225 MVT VecTy = ty(VecV);
1226 unsigned HwLen = Subtarget.getVectorLength();
1238 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1239 if (ElemTy == MVT::i32)
1240 return InsertWord(VecV, ValV, ByteIdx);
1246 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1251 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1252 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1254 ValV, SubIdx, dl, ElemTy, DAG);
1257 return InsertWord(VecV, Ins, ByteIdx);
1261HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1263 unsigned HwLen = Subtarget.getVectorLength();
1267 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1272 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1277HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1279 MVT VecTy = ty(VecV);
1280 unsigned HwLen = Subtarget.getVectorLength();
1288 if (isHvxPairTy(VecTy)) {
1289 unsigned SubIdx = Hexagon::vsub_lo;
1290 if (Idx * ElemWidth >= 8 * HwLen) {
1291 SubIdx = Hexagon::vsub_hi;
1295 VecTy = typeSplit(VecTy).first;
1305 MVT WordTy = tyVector(VecTy, MVT::i32);
1307 unsigned WordIdx = (Idx*ElemWidth) / 32;
1310 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1315 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1316 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1321HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1323 MVT VecTy = ty(VecV);
1324 unsigned HwLen = Subtarget.getVectorLength();
1332 unsigned Offset = Idx * BitBytes;
1334 SmallVector<int,128>
Mask;
1336 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1343 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1344 for (
unsigned j = 0;
j != Rep; ++
j)
1361 unsigned Rep = 8 / ResLen;
1364 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1366 for (
unsigned i = 0; i != ResLen; ++i) {
1367 for (
unsigned j = 0;
j != Rep; ++
j)
1379 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1380 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1385HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1387 MVT VecTy = ty(VecV);
1388 MVT SubTy = ty(SubV);
1389 unsigned HwLen = Subtarget.getVectorLength();
1393 bool IsPair = isHvxPairTy(VecTy);
1401 V0 = LoHalf(VecV, DAG);
1402 V1 = HiHalf(VecV, DAG);
1407 if (isHvxSingleTy(SubTy)) {
1409 unsigned Idx = CN->getZExtValue();
1411 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1434 if (!IdxN || !IdxN->isZero()) {
1442 unsigned RolBase = HwLen;
1457 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1472HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1474 MVT VecTy = ty(VecV);
1475 MVT SubTy = ty(SubV);
1476 assert(Subtarget.isHVXVectorType(VecTy,
true));
1481 unsigned HwLen = Subtarget.getVectorLength();
1482 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1485 unsigned BitBytes = HwLen / VecLen;
1486 unsigned BlockLen = HwLen / Scale;
1490 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1494 if (!IdxN || !IdxN->isZero()) {
1503 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1505 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1507 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1509 if (!IdxN || !IdxN->isZero()) {
1518HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1523 assert(Subtarget.isHVXVectorType(ResTy));
1530 SDValue False = getZero(dl, ResTy, DAG);
1531 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1535HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1543 unsigned HwLen = Subtarget.getVectorLength();
1545 MVT PredTy = ty(VecQ);
1547 assert(HwLen % PredLen == 0);
1554 for (
unsigned i = 0; i != HwLen/8; ++i) {
1555 for (
unsigned j = 0;
j != 8; ++
j)
1556 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1559 Align Alignment(HwLen);
1568 getZero(dl, VecTy, DAG));
1574 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1576 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1583 SmallVector<int,128>
Mask;
1584 for (
unsigned i = 0; i != HwLen; ++i)
1585 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1595 MVT InpTy = ty(VecV);
1603 return InpWidth < ResWidth
1604 ? DAG.
getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1611 if (InpWidth < ResWidth) {
1613 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1621HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1625 const SDLoc &dl(Vec);
1634 const SDLoc &dl(
Op);
1639 for (
unsigned i = 0; i !=
Size; ++i)
1640 Ops.push_back(
Op.getOperand(i));
1643 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1650 for (
unsigned i = 0; i !=
Size; i++)
1654 tyVector(VecTy, MVT::i16), NewOps);
1655 return DAG.
getBitcast(tyVector(VecTy, MVT::f16), T0);
1661 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1663 MVT SingleTy = typeSplit(VecTy).first;
1664 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1665 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1669 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1675 const SDLoc &dl(
Op);
1677 MVT ArgTy = ty(
Op.getOperand(0));
1679 if (ArgTy == MVT::f16) {
1697 const SDLoc &dl(
Op);
1714 MVT NTy = typeLegalize(Ty, DAG);
1718 V.getOperand(0),
V.getOperand(1)),
1723 switch (
V.getOpcode()) {
1731 V =
V.getOperand(0);
1742 unsigned HwLen = Subtarget.getVectorLength();
1749 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1757 MVT HalfTy = typeSplit(VecTy).first;
1759 Ops.take_front(NumOp/2));
1761 Ops.take_back(NumOp/2));
1770 for (
SDValue V :
Op.getNode()->op_values()) {
1771 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1775 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1778 SDValue Res = getZero(dl, ByteTy, DAG);
1779 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1792 const SDLoc &dl(
Op);
1794 if (ElemTy == MVT::i1)
1795 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1797 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1803 const SDLoc &dl(
Op);
1809 if (ElemTy == MVT::i1)
1810 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1812 if (ElemTy == MVT::f16) {
1814 tyVector(VecTy, MVT::i16),
1815 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1817 return DAG.
getBitcast(tyVector(VecTy, MVT::f16), T0);
1820 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1827 MVT SrcTy = ty(SrcV);
1833 const SDLoc &dl(
Op);
1836 if (ElemTy == MVT::i1)
1837 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1839 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1850 const SDLoc &dl(
Op);
1851 MVT VecTy = ty(VecV);
1853 if (ElemTy == MVT::i1)
1854 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1856 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1868 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1869 return LowerHvxSignExt(
Op, DAG);
1878 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1879 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1888 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1889 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1897 const SDLoc &dl(
Op);
1900 assert(ResTy == ty(InpV));
1925 const SDLoc &dl(
Op);
1932 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
1933 unsigned Opc =
Op.getOpcode();
1949 const SDLoc &dl(
Op);
1950 unsigned Opc =
Op.getOpcode();
1955 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
1967 if (Subtarget.useHVXV62Ops())
1968 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1973 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
1974 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
1980 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1987 MVT ValTy = ty(Val);
1988 const SDLoc &dl(
Op);
1991 unsigned HwLen = Subtarget.getVectorLength();
1993 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2008 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2010 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2015 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2016 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2029 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2030 assert(Val32.getValueType().getSizeInBits() == 32 &&
2031 "Input must be 32 bits");
2035 for (
unsigned i = 0; i < 32; ++i)
2043 if (ResTy == MVT::v32i1 &&
2044 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2045 Subtarget.useHVX128BOps()) {
2047 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2048 Val32 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Val);
2049 return bitcastI32ToV32I1(Val32);
2052 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2070 unsigned HwLen = Subtarget.getVectorLength();
2082 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2086 for (
unsigned J = 0; J != 8; ++J) {
2094 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2118 const SDLoc &dl(
Op);
2119 unsigned HwLen = Subtarget.getVectorLength();
2121 assert(HwLen % VecLen == 0);
2122 unsigned ElemSize = HwLen / VecLen;
2134 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2140HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2142 unsigned Opc =
Op.getOpcode();
2154 const SDLoc &dl(
Op);
2160 bool UseShifts = ElemTy != MVT::i8;
2161 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2164 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2172 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2188 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2197 const SDLoc &dl(
Op);
2198 unsigned IntNo =
Op.getConstantOperandVal(0);
2206 case Intrinsic::hexagon_V6_pred_typecast:
2207 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2208 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2209 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2216 case Intrinsic::hexagon_V6_vmpyss_parts:
2217 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2220 case Intrinsic::hexagon_V6_vmpyuu_parts:
2221 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2224 case Intrinsic::hexagon_V6_vmpyus_parts:
2225 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2236 const SDLoc &dl(
Op);
2237 unsigned HwLen = Subtarget.getVectorLength();
2241 SDValue Chain = MaskN->getChain();
2245 unsigned Opc =
Op->getOpcode();
2248 if (
Opc == ISD::MLOAD) {
2262 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2266 if (MaskN->getAlign().value() % HwLen == 0) {
2275 SDValue Z = getZero(dl, ty(V), DAG);
2279 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2280 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2281 return std::make_pair(LoV, HiV);
2287 VectorPair Tmp = StoreAlign(MaskV,
Base);
2290 VectorPair ValueU = StoreAlign(
Value,
Base);
2294 getInstr(StoreOpc, dl, MVT::Other,
2295 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2297 getInstr(StoreOpc, dl, MVT::Other,
2298 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2308 assert(Subtarget.useHVXQFloatOps());
2310 assert(
Op->getOpcode() == ISD::FP_EXTEND);
2313 MVT ArgTy = ty(
Op.getOperand(0));
2314 const SDLoc &dl(
Op);
2315 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2324 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2326 MVT HalfTy = typeSplit(VecTy).first;
2327 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2329 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2331 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2334 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2347 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2350 if (Subtarget.useHVXIEEEFPOps()) {
2352 if (FpTy == MVT::f16) {
2354 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2356 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2362 return EqualizeFpIntConversion(
Op, DAG);
2364 return ExpandHvxFpToInt(
Op, DAG);
2380 MVT ResTy = ty(PredOp);
2381 const SDLoc &dl(PredOp);
2384 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2385 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2387 SDNode *PredTransfer =
2390 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2393 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2398 SDNode *IndexShift =
2404 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2429 MVT ResTy = ty(PredOp);
2430 const SDLoc &dl(PredOp);
2440 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2441 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2446 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, HiReg));
2449 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, LoReg));
2451 SDNode *PredTransfer =
2455 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2462 SDNode *IndexShift_hi =
2465 SDNode *IndexShift_lo =
2469 SDNode *MaskOff_hi =
2472 SDNode *MaskOff_lo =
2495 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2496 return LowerHvxPred32ToFp(
Op, DAG);
2497 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2498 return LowerHvxPred64ToFp(
Op, DAG);
2501 if (Subtarget.useHVXIEEEFPOps()) {
2503 if (FpTy == MVT::f16) {
2505 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2507 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2513 return EqualizeFpIntConversion(
Op, DAG);
2515 return ExpandHvxIntToFp(
Op, DAG);
2518HexagonTargetLowering::TypePair
2519HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2530 unsigned MaxWidth = std::max(Width0, Width1);
2532 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2539 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2540 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2544 return {WideETy0, WideETy1};
2555HexagonTargetLowering::TypePair
2556HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2566 unsigned MaxLen = std::max(Len0, Len1);
2579HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2580 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2589HexagonTargetLowering::VectorPair
2620HexagonTargetLowering::VectorPair
2621HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2626 const SDLoc &dl(Val);
2627 MVT ValTy = ty(Val);
2641 MVT IntTy = tyVector(ValTy, ElemTy);
2653 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2672 MVT
PairTy = typeJoin({VecTy, VecTy});
2698 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2700 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2708 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2710 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2713 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2714 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2715 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2726HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2727 bool SignedB,
const SDLoc &dl,
2730 MVT
PairTy = typeJoin({VecTy, VecTy});
2735 if (SignedA && !SignedB) {
2751 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2752 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2753 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2762 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2765 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2769 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2770 {HiHalf(P2, DAG), T3,
S16}, DAG);
2773 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2774 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2778 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2785 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2786 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2787 }
else if (SignedB) {
2793 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2795 assert(!SignedA && !SignedB);
2802HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2807 MVT
PairTy = typeJoin({VecTy, VecTy});
2810 if (SignedA && !SignedB) {
2819 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2824 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2836 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2837 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2838 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2839 }
else if (!SignedA) {
2849 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2867 unsigned Opc =
Op.getOpcode();
2872 MVT InpTy = ty(Inp);
2878 const SDLoc &dl(
Op);
2881 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2890 unsigned Opc =
Op.getOpcode();
2893 const SDLoc &dl(
Op);
2895 MVT InpTy = ty(Op0);
2975 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
2976 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3019 unsigned Opc =
Op.getOpcode();
3022 const SDLoc &dl(
Op);
3024 MVT InpTy = ty(Op0);
3057 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3067 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3090 unsigned Opc =
Op.getOpcode();
3107 const SDLoc &dl(
Op);
3108 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3117 unsigned Opc =
Op.getConstantOperandVal(2);
3121HexagonTargetLowering::VectorPair
3125 const SDLoc &dl(
Op);
3127 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3128 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3130 return std::make_pair(TV, TV);
3135 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3137 switch (
Op.getOpcode()) {
3138 case ISD::SIGN_EXTEND_INREG:
3139 case HexagonISD::SSAT:
3140 case HexagonISD::USAT:
3141 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3142 std::tie(Lo, Hi) = SplitVTNode(N);
3150 MVT HalfTy = typeSplit(ResTy).first;
3160 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3161 if (!isHvxPairTy(MemTy))
3164 const SDLoc &dl(
Op);
3165 unsigned HwLen = Subtarget.getVectorLength();
3166 MVT SingleTy = typeSplit(MemTy).first;
3167 SDValue Chain = MemN->getChain();
3168 SDValue Base0 = MemN->getBasePtr();
3173 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3174 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3176 uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3183 if (MemOpc == ISD::LOAD) {
3192 if (MemOpc == ISD::STORE) {
3200 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3203 assert(MaskN->isUnindexed());
3204 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3207 if (MemOpc == ISD::MLOAD) {
3223 if (MemOpc == ISD::MSTORE) {
3226 Masks.first, SingleTy, MOp0,
3229 Masks.second, SingleTy, MOp1,
3234 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3240 const SDLoc &dl(
Op);
3242 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3243 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3244 "Not widening loads of i1 yet");
3246 SDValue Chain = LoadN->getChain();
3251 unsigned HwLen = Subtarget.getVectorLength();
3253 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3256 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3264 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3272 const SDLoc &dl(
Op);
3274 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3275 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3276 "Not widening stores of i1 yet");
3278 SDValue Chain = StoreN->getChain();
3282 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3283 MVT ValueTy = ty(
Value);
3285 unsigned HwLen = Subtarget.getVectorLength();
3288 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3290 Len = ty(
Value).getVectorNumElements();
3292 assert(ty(
Value).getVectorNumElements() == HwLen);
3294 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3296 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3299 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3306 const SDLoc &dl(
Op);
3307 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3309 unsigned HwLen = Subtarget.getVectorLength();
3314 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3317 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3318 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3322 {WideOp0, WideOp1,
Op.getOperand(2)});
3324 EVT RetTy = typeLegalize(ty(
Op), DAG);
3326 {SetCC, getZero(dl, MVT::i32, DAG)});
3331 unsigned Opc =
Op.getOpcode();
3332 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3334 return isHvxPairTy(ty(V));
3345 return SplitHvxMemOp(
Op, DAG);
3350 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3351 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3361 case ISD::FMINIMUMNUM:
3362 case ISD::FMAXIMUMNUM:
3381 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3386 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3387 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3402 case ISD::BITCAST:
return LowerHvxBitcast(
Op, DAG);
3410 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3412 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3422 case ISD::MSTORE:
return LowerHvxMaskedOp(
Op, DAG);
3424 case ISD::LOAD:
return SDValue();
3425 case ISD::FP_EXTEND:
return LowerHvxFpExtend(
Op, DAG);
3451 unsigned Opc =
Op.getOpcode();
3471 MVT InpTy = ty(Inp);
3476 assert(InpWidth != ResWidth);
3478 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3481 const SDLoc &dl(
Op);
3485 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3493 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3500 if (InpWidth < ResWidth) {
3502 while (InpWidth * 2 <= ResWidth)
3503 S = repeatOp(InpWidth *= 2, S);
3507 while (InpWidth / 2 >= ResWidth)
3508 S = repeatOp(InpWidth /= 2, S);
3516 MVT InpTy = ty(Inp0);
3520 unsigned Opc =
Op.getOpcode();
3522 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3527 auto [WInpTy, WResTy] =
3528 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3529 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3530 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3538 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3539 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3540 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3541 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3544 return RemoveTLWrapper(
Op, DAG);
3550HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3552 unsigned Opc =
N->getOpcode();
3555 if (
N->getNumOperands() > 0)
3556 Inp0 =
Op.getOperand(0);
3563 if (Subtarget.isHVXElementType(ty(
Op)) &&
3564 Subtarget.isHVXElementType(ty(Inp0))) {
3565 Results.push_back(CreateTLWrapper(
Op, DAG));
3569 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3582 if (isHvxPairTy(ty(
Op))) {
3590 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3599 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3600 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3608 Results.push_back(LegalizeHvxResize(
Op, DAG));
3616HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3618 unsigned Opc =
N->getOpcode();
3621 if (
N->getNumOperands() > 0)
3622 Inp0 =
Op.getOperand(0);
3629 if (Subtarget.isHVXElementType(ty(
Op)) &&
3630 Subtarget.isHVXElementType(ty(Inp0))) {
3631 Results.push_back(CreateTLWrapper(
Op, DAG));
3635 if (shouldWidenToHvx(ty(
Op), DAG)) {
3641 if (shouldWidenToHvx(ty(
Op), DAG)) {
3650 if (isHvxBoolTy(ty(Inp0))) {
3657 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3658 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3666 Results.push_back(LegalizeHvxResize(
Op, DAG));
3674HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3675 DAGCombinerInfo &DCI)
const {
3680 SelectionDAG &DAG = DCI.DAG;
3681 const SDLoc &dl(
Op);
3683 if (
Op.getOperand(0).getOpcode() == ISD::BITCAST)
3688 EVT TruncTy =
Op.getValueType();
3690 EVT SrcTy = Src.getValueType();
3697 if (2 * CastLen != SrcLen)
3700 SmallVector<int, 128>
Mask(SrcLen);
3701 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3703 Mask[i + CastLen] = 2 * i + 1;
3707 return opSplit(Deal, dl, DAG).first;
3711HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3712 SDValue Op, DAGCombinerInfo &DCI)
const {
3720 SelectionDAG &DAG = DCI.DAG;
3721 const SDLoc &dl(
Op);
3730 SetVector<SDValue> Order;
3736 if (Order.
size() > 2)
3745 SmallVector<int, 128> LongMask;
3746 auto AppendToMask = [&](
SDValue Shuffle) {
3748 ArrayRef<int>
Mask = SV->getMask();
3751 for (
int M : Mask) {
3756 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3757 if (
static_cast<unsigned>(M) >= InpLen)
3760 int OutOffset = Order[0] == Src ? 0 : InpLen;
3777HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3780 SelectionDAG &DAG = DCI.DAG;
3782 unsigned Opc =
Op.getOpcode();
3787 return combineTruncateBeforeLegal(
Op, DCI);
3789 return combineConcatVectorsBeforeLegal(
Op, DCI);
3791 if (DCI.isBeforeLegalizeOps())
3817 return getZero(dl, ty(
Op), DAG);
3820 if (isUndef(
Ops[1]))
3838HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3839 if (Subtarget.isHVXVectorType(Ty,
true))
3841 auto Action = getPreferredHvxVectorAction(Ty);
3843 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3848HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3849 if (Subtarget.isHVXVectorType(Ty,
true))
3851 auto Action = getPreferredHvxVectorAction(Ty);
3853 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3859 if (!Subtarget.useHVXOps())
3863 auto IsHvxTy = [
this](EVT Ty) {
3864 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
3867 return Op.getValueType().isSimple() &&
3868 Subtarget.isHVXVectorType(ty(
Op),
true);
3874 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3875 if (!
Op.getValueType().isSimple())
3878 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3881 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.