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())
122 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
123 Subtarget.useHVXFloatingPoint()) {
125 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
126 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
128 for (MVT
T : FloatV) {
163 for (MVT
P : FloatW) {
185 if (Subtarget.useHVXQFloatOps()) {
188 }
else if (Subtarget.useHVXIEEEFPOps()) {
194 for (MVT
T : LegalV) {
221 if (
T.getScalarType() != MVT::i32) {
230 if (
T.getScalarType() != MVT::i32) {
258 if (Subtarget.useHVXFloatingPoint()) {
275 for (MVT
T : LegalW) {
330 if (
T.getScalarType() != MVT::i32) {
335 if (Subtarget.useHVXFloatingPoint()) {
382 for (MVT
T : LegalW) {
399 for (MVT
T : LegalV) {
414 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
417 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
422 unsigned HwLen = Subtarget.getVectorLength();
423 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
424 if (ElemTy == MVT::i1)
426 int ElemWidth = ElemTy.getFixedSizeInBits();
427 int MaxElems = (8*HwLen) / ElemWidth;
428 for (
int N = 2;
N < MaxElems;
N *= 2) {
439 if (Subtarget.useHVXFloatingPoint()) {
462HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
465 unsigned HwLen = Subtarget.getVectorLength();
468 if (ElemTy == MVT::i1 && VecLen > HwLen)
474 if (ElemTy == MVT::i1) {
489 unsigned HwWidth = 8*HwLen;
490 if (VecWidth > 2*HwWidth)
496 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
505HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
506 unsigned Opc =
Op.getOpcode();
526HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
527 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
531 Tys.second.getVectorNumElements());
534HexagonTargetLowering::TypePair
535HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
538 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
540 return { HalfTy, HalfTy };
544HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
551HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
558HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
567HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
573HexagonTargetLowering::VectorPair
574HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
576 TypePair Tys = typeSplit(ty(Vec));
579 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
583HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
584 return Subtarget.isHVXVectorType(Ty) &&
589HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
590 return Subtarget.isHVXVectorType(Ty) &&
595HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
596 return Subtarget.isHVXVectorType(Ty,
true) &&
600bool HexagonTargetLowering::allowsHvxMemoryAccess(
608 if (!Subtarget.isHVXVectorType(VecTy,
false))
615bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
617 if (!Subtarget.isHVXVectorType(VecTy))
625void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
627 unsigned Opc =
MI.getOpcode();
628 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
629 MachineBasicBlock &MB = *
MI.getParent();
633 auto At =
MI.getIterator();
636 case Hexagon::PS_vsplatib:
637 if (Subtarget.useHVXV62Ops()) {
640 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
642 .
add(
MI.getOperand(1));
644 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
649 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
650 const MachineOperand &InpOp =
MI.getOperand(1);
652 uint32_t
V = InpOp.
getImm() & 0xFF;
654 .
addImm(V << 24 | V << 16 | V << 8 | V);
660 case Hexagon::PS_vsplatrb:
661 if (Subtarget.useHVXV62Ops()) {
664 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
665 .
add(
MI.getOperand(1));
667 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
668 const MachineOperand &InpOp =
MI.getOperand(1);
669 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
672 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
677 case Hexagon::PS_vsplatih:
678 if (Subtarget.useHVXV62Ops()) {
681 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
683 .
add(
MI.getOperand(1));
685 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
690 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
691 const MachineOperand &InpOp =
MI.getOperand(1);
693 uint32_t
V = InpOp.
getImm() & 0xFFFF;
701 case Hexagon::PS_vsplatrh:
702 if (Subtarget.useHVXV62Ops()) {
705 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
706 .
add(
MI.getOperand(1));
710 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
711 const MachineOperand &InpOp =
MI.getOperand(1);
712 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
720 case Hexagon::PS_vsplatiw:
721 case Hexagon::PS_vsplatrw:
722 if (
Opc == Hexagon::PS_vsplatiw) {
724 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
726 .
add(
MI.getOperand(1));
727 MI.getOperand(1).ChangeToRegister(SplatV,
false);
730 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
736HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
746 const SDLoc &dl(ElemIdx);
752HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
755 assert(ElemWidth >= 8 && ElemWidth <= 32);
759 if (ty(Idx) != MVT::i32)
761 const SDLoc &dl(Idx);
768HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
775 if (ElemTy == MVT::i8)
779 MVT ResTy = tyVector(OpTy, MVT::i8);
782 SmallVector<int,128> ByteMask;
785 for (
unsigned I = 0;
I != ElemSize; ++
I)
788 int NewM =
M*ElemSize;
789 for (
unsigned I = 0;
I != ElemSize; ++
I)
795 opCastElem(Op1, MVT::i8, DAG), ByteMask);
802 unsigned VecLen = Values.
size();
806 unsigned HwLen = Subtarget.getVectorLength();
808 unsigned ElemSize = ElemWidth / 8;
809 assert(ElemSize*VecLen == HwLen);
813 !(Subtarget.useHVXFloatingPoint() &&
815 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
816 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
818 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
819 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
827 unsigned NumValues = Values.size();
830 for (
unsigned i = 0; i != NumValues; ++i) {
831 if (Values[i].isUndef())
834 if (!SplatV.getNode())
836 else if (SplatV != Values[i])
844 unsigned NumWords = Words.
size();
846 bool IsSplat =
isSplat(Words, SplatV);
847 if (IsSplat && isUndef(SplatV))
852 return getZero(dl, VecTy, DAG);
861 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
864 (Constant**)Consts.end());
866 Align Alignment(HwLen);
880 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
881 SmallVectorImpl<int> &SrcIdx) {
885 SrcIdx.push_back(-1);
898 int I =
C->getSExtValue();
899 assert(
I >= 0 &&
"Negative element index");
906 SmallVector<int,128> ExtIdx;
908 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
909 MVT ExtTy = ty(ExtVec);
911 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
915 SmallVector<int,128>
Mask;
916 BitVector
Used(ExtLen);
918 for (
int M : ExtIdx) {
928 for (
unsigned I = 0;
I != ExtLen; ++
I) {
929 if (
Mask.size() == ExtLen)
937 return ExtLen == VecLen ? S : LoHalf(S, DAG);
945 assert(4*Words.
size() == Subtarget.getVectorLength());
948 for (
unsigned i = 0; i != NumWords; ++i) {
950 if (Words[i].isUndef())
952 for (
unsigned j = i;
j != NumWords; ++
j)
953 if (Words[i] == Words[j])
956 if (VecHist[i] > VecHist[n])
960 SDValue HalfV = getZero(dl, VecTy, DAG);
961 if (VecHist[n] > 1) {
964 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
976 for (
unsigned i = 0; i != NumWords/2; ++i) {
978 if (Words[i] != Words[n] || VecHist[n] <= 1) {
985 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
989 {HalfV1, Words[i+NumWords/2]});
1012HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1013 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1014 MVT PredTy = ty(PredV);
1015 unsigned HwLen = Subtarget.getVectorLength();
1018 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1028 SmallVector<int,128>
Mask(HwLen);
1033 for (
unsigned i = 0; i != HwLen; ++i) {
1034 unsigned Num = i % Scale;
1035 unsigned Off = i / Scale;
1044 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1046 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1053 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1065 while (Bytes < BitBytes) {
1067 Words[IdxW].
clear();
1070 for (
const SDValue &W : Words[IdxW ^ 1]) {
1071 SDValue T = expandPredicate(W, dl, DAG);
1076 for (
const SDValue &W : Words[IdxW ^ 1]) {
1084 assert(Bytes == BitBytes);
1086 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1088 for (
const SDValue &W : Words[IdxW]) {
1102 unsigned VecLen = Values.
size();
1103 unsigned HwLen = Subtarget.getVectorLength();
1104 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1106 bool AllT =
true, AllF =
true;
1110 return !
N->isZero();
1119 if (VecLen <= HwLen) {
1123 assert(HwLen % VecLen == 0);
1124 unsigned BitBytes = HwLen / VecLen;
1131 for (
unsigned B = 0;
B != BitBytes; ++
B)
1138 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1141 for (;
B != 8; ++
B) {
1142 if (!Values[
I+
B].isUndef())
1155 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1165 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1170HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1175 assert(ElemWidth >= 8 && ElemWidth <= 32);
1178 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1181 if (ElemTy == MVT::i32)
1187 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1190 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1194HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1197 assert(ResTy == MVT::i1);
1199 unsigned HwLen = Subtarget.getVectorLength();
1203 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1207 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1209 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1213HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1218 assert(ElemWidth >= 8 && ElemWidth <= 32);
1223 MVT VecTy = ty(VecV);
1224 unsigned HwLen = Subtarget.getVectorLength();
1236 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1237 if (ElemTy == MVT::i32)
1238 return InsertWord(VecV, ValV, ByteIdx);
1244 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1249 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1250 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1252 ValV, SubIdx, dl, ElemTy, DAG);
1255 return InsertWord(VecV, Ins, ByteIdx);
1259HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1261 unsigned HwLen = Subtarget.getVectorLength();
1265 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1270 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1275HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1277 MVT VecTy = ty(VecV);
1278 unsigned HwLen = Subtarget.getVectorLength();
1286 if (isHvxPairTy(VecTy)) {
1287 unsigned SubIdx = Hexagon::vsub_lo;
1288 if (Idx * ElemWidth >= 8 * HwLen) {
1289 SubIdx = Hexagon::vsub_hi;
1293 VecTy = typeSplit(VecTy).first;
1303 MVT WordTy = tyVector(VecTy, MVT::i32);
1305 unsigned WordIdx = (Idx*ElemWidth) / 32;
1308 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1313 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1314 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1319HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1321 MVT VecTy = ty(VecV);
1322 unsigned HwLen = Subtarget.getVectorLength();
1330 unsigned Offset = Idx * BitBytes;
1332 SmallVector<int,128>
Mask;
1334 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1341 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1342 for (
unsigned j = 0;
j != Rep; ++
j)
1359 unsigned Rep = 8 / ResLen;
1362 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1364 for (
unsigned i = 0; i != ResLen; ++i) {
1365 for (
unsigned j = 0;
j != Rep; ++
j)
1377 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1378 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1383HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1385 MVT VecTy = ty(VecV);
1386 MVT SubTy = ty(SubV);
1387 unsigned HwLen = Subtarget.getVectorLength();
1391 bool IsPair = isHvxPairTy(VecTy);
1399 V0 = LoHalf(VecV, DAG);
1400 V1 = HiHalf(VecV, DAG);
1405 if (isHvxSingleTy(SubTy)) {
1407 unsigned Idx = CN->getZExtValue();
1409 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1432 if (!IdxN || !IdxN->isZero()) {
1440 unsigned RolBase = HwLen;
1455 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1470HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1472 MVT VecTy = ty(VecV);
1473 MVT SubTy = ty(SubV);
1474 assert(Subtarget.isHVXVectorType(VecTy,
true));
1479 unsigned HwLen = Subtarget.getVectorLength();
1480 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1483 unsigned BitBytes = HwLen / VecLen;
1484 unsigned BlockLen = HwLen / Scale;
1488 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1492 if (!IdxN || !IdxN->isZero()) {
1501 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1503 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1505 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1507 if (!IdxN || !IdxN->isZero()) {
1516HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1521 assert(Subtarget.isHVXVectorType(ResTy));
1528 SDValue False = getZero(dl, ResTy, DAG);
1529 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1533HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1541 unsigned HwLen = Subtarget.getVectorLength();
1543 MVT PredTy = ty(VecQ);
1545 assert(HwLen % PredLen == 0);
1552 for (
unsigned i = 0; i != HwLen/8; ++i) {
1553 for (
unsigned j = 0;
j != 8; ++
j)
1554 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1557 Align Alignment(HwLen);
1566 getZero(dl, VecTy, DAG));
1572 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1574 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1581 SmallVector<int,128>
Mask;
1582 for (
unsigned i = 0; i != HwLen; ++i)
1583 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1593 MVT InpTy = ty(VecV);
1601 return InpWidth < ResWidth
1602 ? DAG.
getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1609 if (InpWidth < ResWidth) {
1611 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1619HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1623 const SDLoc &dl(Vec);
1632 const SDLoc &dl(
Op);
1637 for (
unsigned i = 0; i !=
Size; ++i)
1638 Ops.push_back(
Op.getOperand(i));
1641 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1648 for (
unsigned i = 0; i !=
Size; i++)
1652 tyVector(VecTy, MVT::i16), NewOps);
1653 return DAG.
getBitcast(tyVector(VecTy, MVT::f16), T0);
1659 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1661 MVT SingleTy = typeSplit(VecTy).first;
1662 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1663 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1667 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1673 const SDLoc &dl(
Op);
1675 MVT ArgTy = ty(
Op.getOperand(0));
1677 if (ArgTy == MVT::f16) {
1695 const SDLoc &dl(
Op);
1712 MVT NTy = typeLegalize(Ty, DAG);
1716 V.getOperand(0),
V.getOperand(1)),
1721 switch (
V.getOpcode()) {
1729 V =
V.getOperand(0);
1740 unsigned HwLen = Subtarget.getVectorLength();
1747 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1755 MVT HalfTy = typeSplit(VecTy).first;
1757 Ops.take_front(NumOp/2));
1759 Ops.take_back(NumOp/2));
1768 for (
SDValue V :
Op.getNode()->op_values()) {
1769 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1773 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1776 SDValue Res = getZero(dl, ByteTy, DAG);
1777 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1790 const SDLoc &dl(
Op);
1792 if (ElemTy == MVT::i1)
1793 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1795 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1801 const SDLoc &dl(
Op);
1807 if (ElemTy == MVT::i1)
1808 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1810 if (ElemTy == MVT::f16) {
1812 tyVector(VecTy, MVT::i16),
1813 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1815 return DAG.
getBitcast(tyVector(VecTy, MVT::f16), T0);
1818 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1825 MVT SrcTy = ty(SrcV);
1831 const SDLoc &dl(
Op);
1834 if (ElemTy == MVT::i1)
1835 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1837 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1848 const SDLoc &dl(
Op);
1849 MVT VecTy = ty(VecV);
1851 if (ElemTy == MVT::i1)
1852 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1854 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1866 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1867 return LowerHvxSignExt(
Op, DAG);
1876 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1877 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1886 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1887 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1895 const SDLoc &dl(
Op);
1898 assert(ResTy == ty(InpV));
1923 const SDLoc &dl(
Op);
1930 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
1931 unsigned Opc =
Op.getOpcode();
1947 const SDLoc &dl(
Op);
1948 unsigned Opc =
Op.getOpcode();
1953 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
1965 if (Subtarget.useHVXV62Ops())
1966 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1971 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
1972 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
1978 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1985 MVT ValTy = ty(Val);
1986 const SDLoc &dl(
Op);
1989 unsigned HwLen = Subtarget.getVectorLength();
1991 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2006 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2008 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2013 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2014 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2027 if (ResTy == MVT::v32i1 &&
2028 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2029 Subtarget.useHVX128BOps()) {
2031 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2032 Val32 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Val);
2037 for (
unsigned i = 0; i < 32; ++i)
2048 unsigned HwLen = Subtarget.getVectorLength();
2060 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2064 for (
unsigned J = 0; J != 8; ++J) {
2072 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2096 const SDLoc &dl(
Op);
2097 unsigned HwLen = Subtarget.getVectorLength();
2099 assert(HwLen % VecLen == 0);
2100 unsigned ElemSize = HwLen / VecLen;
2112 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2118HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2120 unsigned Opc =
Op.getOpcode();
2132 const SDLoc &dl(
Op);
2138 bool UseShifts = ElemTy != MVT::i8;
2139 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2142 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2150 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2166 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2175 const SDLoc &dl(
Op);
2176 unsigned IntNo =
Op.getConstantOperandVal(0);
2184 case Intrinsic::hexagon_V6_pred_typecast:
2185 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2186 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2187 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2194 case Intrinsic::hexagon_V6_vmpyss_parts:
2195 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2198 case Intrinsic::hexagon_V6_vmpyuu_parts:
2199 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2202 case Intrinsic::hexagon_V6_vmpyus_parts:
2203 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2214 const SDLoc &dl(
Op);
2215 unsigned HwLen = Subtarget.getVectorLength();
2219 SDValue Chain = MaskN->getChain();
2223 unsigned Opc =
Op->getOpcode();
2226 if (
Opc == ISD::MLOAD) {
2240 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2244 if (MaskN->getAlign().value() % HwLen == 0) {
2253 SDValue Z = getZero(dl, ty(V), DAG);
2257 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2258 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2259 return std::make_pair(LoV, HiV);
2265 VectorPair Tmp = StoreAlign(MaskV,
Base);
2268 VectorPair ValueU = StoreAlign(
Value,
Base);
2272 getInstr(StoreOpc, dl, MVT::Other,
2273 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2275 getInstr(StoreOpc, dl, MVT::Other,
2276 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2286 assert(Subtarget.useHVXQFloatOps());
2288 assert(
Op->getOpcode() == ISD::FP_EXTEND);
2291 MVT ArgTy = ty(
Op.getOperand(0));
2292 const SDLoc &dl(
Op);
2293 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2302 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2304 MVT HalfTy = typeSplit(VecTy).first;
2305 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2307 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2309 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2312 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2325 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2328 if (Subtarget.useHVXIEEEFPOps()) {
2330 if (FpTy == MVT::f16) {
2332 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2334 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2340 return EqualizeFpIntConversion(
Op, DAG);
2342 return ExpandHvxFpToInt(
Op, DAG);
2358 MVT ResTy = ty(PredOp);
2359 const SDLoc &dl(PredOp);
2362 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2363 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2365 SDNode *PredTransfer =
2368 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2371 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2376 SDNode *IndexShift =
2382 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2407 MVT ResTy = ty(PredOp);
2408 const SDLoc &dl(PredOp);
2418 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2419 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2424 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, HiReg));
2427 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, LoReg));
2429 SDNode *PredTransfer =
2433 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2440 SDNode *IndexShift_hi =
2443 SDNode *IndexShift_lo =
2447 SDNode *MaskOff_hi =
2450 SDNode *MaskOff_lo =
2473 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2474 return LowerHvxPred32ToFp(
Op, DAG);
2475 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2476 return LowerHvxPred64ToFp(
Op, DAG);
2479 if (Subtarget.useHVXIEEEFPOps()) {
2481 if (FpTy == MVT::f16) {
2483 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2485 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2491 return EqualizeFpIntConversion(
Op, DAG);
2493 return ExpandHvxIntToFp(
Op, DAG);
2496HexagonTargetLowering::TypePair
2497HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2508 unsigned MaxWidth = std::max(Width0, Width1);
2510 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2517 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2518 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2522 return {WideETy0, WideETy1};
2533HexagonTargetLowering::TypePair
2534HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2544 unsigned MaxLen = std::max(Len0, Len1);
2557HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2558 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2567HexagonTargetLowering::VectorPair
2598HexagonTargetLowering::VectorPair
2599HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2604 const SDLoc &dl(Val);
2605 MVT ValTy = ty(Val);
2619 MVT IntTy = tyVector(ValTy, ElemTy);
2631 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2650 MVT
PairTy = typeJoin({VecTy, VecTy});
2676 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2678 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2686 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2688 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2691 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2692 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2693 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2704HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2705 bool SignedB,
const SDLoc &dl,
2708 MVT
PairTy = typeJoin({VecTy, VecTy});
2713 if (SignedA && !SignedB) {
2729 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2730 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2731 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2740 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2743 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2747 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2748 {HiHalf(P2, DAG), T3,
S16}, DAG);
2751 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2752 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2756 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2763 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2764 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2765 }
else if (SignedB) {
2771 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2773 assert(!SignedA && !SignedB);
2780HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2785 MVT
PairTy = typeJoin({VecTy, VecTy});
2788 if (SignedA && !SignedB) {
2797 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2802 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2814 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2815 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2816 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2817 }
else if (!SignedA) {
2827 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2845 unsigned Opc =
Op.getOpcode();
2850 MVT InpTy = ty(Inp);
2856 const SDLoc &dl(
Op);
2859 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2868 unsigned Opc =
Op.getOpcode();
2871 const SDLoc &dl(
Op);
2873 MVT InpTy = ty(Op0);
2953 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
2954 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
2997 unsigned Opc =
Op.getOpcode();
3000 const SDLoc &dl(
Op);
3002 MVT InpTy = ty(Op0);
3035 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3045 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3068 unsigned Opc =
Op.getOpcode();
3085 const SDLoc &dl(
Op);
3086 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3095 unsigned Opc =
Op.getConstantOperandVal(2);
3099HexagonTargetLowering::VectorPair
3103 const SDLoc &dl(
Op);
3105 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3106 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3108 return std::make_pair(TV, TV);
3113 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3115 switch (
Op.getOpcode()) {
3116 case ISD::SIGN_EXTEND_INREG:
3117 case HexagonISD::SSAT:
3118 case HexagonISD::USAT:
3119 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3120 std::tie(Lo, Hi) = SplitVTNode(N);
3128 MVT HalfTy = typeSplit(ResTy).first;
3138 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3139 if (!isHvxPairTy(MemTy))
3142 const SDLoc &dl(
Op);
3143 unsigned HwLen = Subtarget.getVectorLength();
3144 MVT SingleTy = typeSplit(MemTy).first;
3145 SDValue Chain = MemN->getChain();
3146 SDValue Base0 = MemN->getBasePtr();
3151 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3152 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3154 uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3161 if (MemOpc == ISD::LOAD) {
3170 if (MemOpc == ISD::STORE) {
3178 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3181 assert(MaskN->isUnindexed());
3182 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3185 if (MemOpc == ISD::MLOAD) {
3201 if (MemOpc == ISD::MSTORE) {
3204 Masks.first, SingleTy, MOp0,
3207 Masks.second, SingleTy, MOp1,
3212 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3218 const SDLoc &dl(
Op);
3220 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3221 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3222 "Not widening loads of i1 yet");
3224 SDValue Chain = LoadN->getChain();
3229 unsigned HwLen = Subtarget.getVectorLength();
3231 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3234 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3242 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3250 const SDLoc &dl(
Op);
3252 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3253 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3254 "Not widening stores of i1 yet");
3256 SDValue Chain = StoreN->getChain();
3260 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3261 MVT ValueTy = ty(
Value);
3263 unsigned HwLen = Subtarget.getVectorLength();
3266 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3268 Len = ty(
Value).getVectorNumElements();
3270 assert(ty(
Value).getVectorNumElements() == HwLen);
3272 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3274 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3277 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3284 const SDLoc &dl(
Op);
3285 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3287 unsigned HwLen = Subtarget.getVectorLength();
3292 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3295 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3296 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3300 {WideOp0, WideOp1,
Op.getOperand(2)});
3302 EVT RetTy = typeLegalize(ty(
Op), DAG);
3304 {SetCC, getZero(dl, MVT::i32, DAG)});
3309 unsigned Opc =
Op.getOpcode();
3310 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3312 return isHvxPairTy(ty(V));
3323 return SplitHvxMemOp(
Op, DAG);
3328 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3329 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3339 case ISD::FMINIMUMNUM:
3340 case ISD::FMAXIMUMNUM:
3359 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3364 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3365 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3380 case ISD::BITCAST:
return LowerHvxBitcast(
Op, DAG);
3388 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3390 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3400 case ISD::MSTORE:
return LowerHvxMaskedOp(
Op, DAG);
3402 case ISD::LOAD:
return SDValue();
3403 case ISD::FP_EXTEND:
return LowerHvxFpExtend(
Op, DAG);
3429 unsigned Opc =
Op.getOpcode();
3449 MVT InpTy = ty(Inp);
3454 assert(InpWidth != ResWidth);
3456 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3459 const SDLoc &dl(
Op);
3463 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3471 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3478 if (InpWidth < ResWidth) {
3480 while (InpWidth * 2 <= ResWidth)
3481 S = repeatOp(InpWidth *= 2, S);
3485 while (InpWidth / 2 >= ResWidth)
3486 S = repeatOp(InpWidth /= 2, S);
3494 MVT InpTy = ty(Inp0);
3498 unsigned Opc =
Op.getOpcode();
3500 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3505 auto [WInpTy, WResTy] =
3506 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3507 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3508 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3516 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3517 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3518 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3519 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3522 return RemoveTLWrapper(
Op, DAG);
3528HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3530 unsigned Opc =
N->getOpcode();
3533 if (
N->getNumOperands() > 0)
3534 Inp0 =
Op.getOperand(0);
3541 if (Subtarget.isHVXElementType(ty(
Op)) &&
3542 Subtarget.isHVXElementType(ty(Inp0))) {
3543 Results.push_back(CreateTLWrapper(
Op, DAG));
3547 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3560 if (isHvxPairTy(ty(
Op))) {
3568 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3577 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3578 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3586 Results.push_back(LegalizeHvxResize(
Op, DAG));
3594HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3596 unsigned Opc =
N->getOpcode();
3599 if (
N->getNumOperands() > 0)
3600 Inp0 =
Op.getOperand(0);
3607 if (Subtarget.isHVXElementType(ty(
Op)) &&
3608 Subtarget.isHVXElementType(ty(Inp0))) {
3609 Results.push_back(CreateTLWrapper(
Op, DAG));
3613 if (shouldWidenToHvx(ty(
Op), DAG)) {
3619 if (shouldWidenToHvx(ty(
Op), DAG)) {
3628 if (isHvxBoolTy(ty(Inp0))) {
3635 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3636 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3644 Results.push_back(LegalizeHvxResize(
Op, DAG));
3652HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3653 DAGCombinerInfo &DCI)
const {
3658 SelectionDAG &DAG = DCI.DAG;
3659 const SDLoc &dl(
Op);
3661 if (
Op.getOperand(0).getOpcode() == ISD::BITCAST)
3666 EVT TruncTy =
Op.getValueType();
3668 EVT SrcTy = Src.getValueType();
3675 if (2 * CastLen != SrcLen)
3678 SmallVector<int, 128>
Mask(SrcLen);
3679 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3681 Mask[i + CastLen] = 2 * i + 1;
3685 return opSplit(Deal, dl, DAG).first;
3689HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3690 SDValue Op, DAGCombinerInfo &DCI)
const {
3698 SelectionDAG &DAG = DCI.DAG;
3699 const SDLoc &dl(
Op);
3708 SetVector<SDValue> Order;
3714 if (Order.
size() > 2)
3723 SmallVector<int, 128> LongMask;
3724 auto AppendToMask = [&](
SDValue Shuffle) {
3726 ArrayRef<int>
Mask = SV->getMask();
3729 for (
int M : Mask) {
3734 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3735 if (
static_cast<unsigned>(M) >= InpLen)
3738 int OutOffset = Order[0] == Src ? 0 : InpLen;
3755HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3758 SelectionDAG &DAG = DCI.DAG;
3760 unsigned Opc =
Op.getOpcode();
3765 return combineTruncateBeforeLegal(
Op, DCI);
3767 return combineConcatVectorsBeforeLegal(
Op, DCI);
3769 if (DCI.isBeforeLegalizeOps())
3795 return getZero(dl, ty(
Op), DAG);
3798 if (isUndef(
Ops[1]))
3816HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3817 if (Subtarget.isHVXVectorType(Ty,
true))
3819 auto Action = getPreferredHvxVectorAction(Ty);
3821 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3826HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3827 if (Subtarget.isHVXVectorType(Ty,
true))
3829 auto Action = getPreferredHvxVectorAction(Ty);
3831 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3837 if (!Subtarget.useHVXOps())
3841 auto IsHvxTy = [
this](EVT Ty) {
3842 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
3845 return Op.getValueType().isSimple() &&
3846 Subtarget.isHVXVectorType(ty(
Op),
true);
3852 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3853 if (!
Op.getValueType().isSimple())
3856 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3859 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.
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.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI const fltSemantics & IEEEhalf() LLVM_READNONE
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.