21#include "llvm/IR/IntrinsicsHexagon.h"
32 cl::desc(
"Lower threshold (in bytes) for widening to HVX vectors"));
36 cl::desc(
"Enable FP fast conversion routine."));
38static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
39static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
40static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
41static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
46 switch (ElemTy.SimpleTy) {
48 return std::make_tuple(5, 15, 10);
50 return std::make_tuple(8, 127, 23);
52 return std::make_tuple(11, 1023, 52);
60HexagonTargetLowering::initializeHVXLowering() {
61 if (Subtarget.useHVX64BOps()) {
79 }
else if (Subtarget.useHVX128BOps()) {
89 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
95 if (Subtarget.useHVXV81Ops()) {
103 bool Use64b = Subtarget.useHVX64BOps();
106 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
107 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
108 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
110 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
128 if (Subtarget.useHVX128BOps()) {
132 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
133 Subtarget.useHVXFloatingPoint()) {
135 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
136 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
138 for (MVT
T : FloatV) {
173 if (Subtarget.useHVXV81Ops()) {
176 setPromoteTo(
ISD::SETCC, MVT::v64bf16, MVT::v64f32);
177 setPromoteTo(
ISD::FADD, MVT::v64bf16, MVT::v64f32);
178 setPromoteTo(
ISD::FSUB, MVT::v64bf16, MVT::v64f32);
179 setPromoteTo(
ISD::FMUL, MVT::v64bf16, MVT::v64f32);
180 setPromoteTo(ISD::FMINNUM, MVT::v64bf16, MVT::v64f32);
181 setPromoteTo(ISD::FMAXNUM, MVT::v64bf16, MVT::v64f32);
205 for (MVT
P : FloatW) {
227 if (Subtarget.useHVXQFloatOps()) {
230 }
else if (Subtarget.useHVXIEEEFPOps()) {
236 for (MVT
T : LegalV) {
263 if (
T.getScalarType() != MVT::i32) {
272 if (
T.getScalarType() != MVT::i32) {
300 if (Subtarget.useHVXFloatingPoint()) {
317 for (MVT
T : LegalW) {
372 if (
T.getScalarType() != MVT::i32) {
377 if (Subtarget.useHVXFloatingPoint()) {
424 for (MVT
T : LegalW) {
441 for (MVT
T : LegalV) {
456 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
459 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
464 unsigned HwLen = Subtarget.getVectorLength();
465 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
466 if (ElemTy == MVT::i1)
468 int ElemWidth = ElemTy.getFixedSizeInBits();
469 int MaxElems = (8*HwLen) / ElemWidth;
470 for (
int N = 2;
N < MaxElems;
N *= 2) {
481 if (Subtarget.useHVXFloatingPoint()) {
504HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
511 unsigned HwLen = Subtarget.getVectorLength();
514 if (ElemTy == MVT::i1 && VecLen > HwLen)
520 if (ElemTy == MVT::i1) {
535 unsigned HwWidth = 8*HwLen;
536 if (VecWidth > 2*HwWidth)
542 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
551HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
552 unsigned Opc =
Op.getOpcode();
572HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
573 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
577 Tys.second.getVectorNumElements());
580HexagonTargetLowering::TypePair
581HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
584 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
586 return { HalfTy, HalfTy };
590HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
597HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
604HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
613HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
619HexagonTargetLowering::VectorPair
620HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
622 TypePair Tys = typeSplit(ty(Vec));
625 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
629HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
630 return Subtarget.isHVXVectorType(Ty) &&
635HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
636 return Subtarget.isHVXVectorType(Ty) &&
641HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
642 return Subtarget.isHVXVectorType(Ty,
true) &&
646bool HexagonTargetLowering::allowsHvxMemoryAccess(
654 if (!Subtarget.isHVXVectorType(VecTy,
false))
661bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
663 if (!Subtarget.isHVXVectorType(VecTy))
671void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
673 unsigned Opc =
MI.getOpcode();
674 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
675 MachineBasicBlock &MB = *
MI.getParent();
679 auto At =
MI.getIterator();
682 case Hexagon::PS_vsplatib:
683 if (Subtarget.useHVXV62Ops()) {
686 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
688 .
add(
MI.getOperand(1));
690 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
695 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
696 const MachineOperand &InpOp =
MI.getOperand(1);
698 uint32_t
V = InpOp.
getImm() & 0xFF;
700 .
addImm(V << 24 | V << 16 | V << 8 | V);
706 case Hexagon::PS_vsplatrb:
707 if (Subtarget.useHVXV62Ops()) {
710 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
711 .
add(
MI.getOperand(1));
713 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
714 const MachineOperand &InpOp =
MI.getOperand(1);
715 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
718 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
723 case Hexagon::PS_vsplatih:
724 if (Subtarget.useHVXV62Ops()) {
727 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
729 .
add(
MI.getOperand(1));
731 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
736 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
737 const MachineOperand &InpOp =
MI.getOperand(1);
739 uint32_t
V = InpOp.
getImm() & 0xFFFF;
747 case Hexagon::PS_vsplatrh:
748 if (Subtarget.useHVXV62Ops()) {
751 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
752 .
add(
MI.getOperand(1));
756 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
757 const MachineOperand &InpOp =
MI.getOperand(1);
758 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
766 case Hexagon::PS_vsplatiw:
767 case Hexagon::PS_vsplatrw:
768 if (
Opc == Hexagon::PS_vsplatiw) {
770 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
772 .
add(
MI.getOperand(1));
773 MI.getOperand(1).ChangeToRegister(SplatV,
false);
776 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
782HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
792 const SDLoc &dl(ElemIdx);
798HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
801 assert(ElemWidth >= 8 && ElemWidth <= 32);
805 if (ty(Idx) != MVT::i32)
807 const SDLoc &dl(Idx);
814HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
821 if (ElemTy == MVT::i8)
825 MVT ResTy = tyVector(OpTy, MVT::i8);
828 SmallVector<int,128> ByteMask;
831 for (
unsigned I = 0;
I != ElemSize; ++
I)
834 int NewM =
M*ElemSize;
835 for (
unsigned I = 0;
I != ElemSize; ++
I)
841 opCastElem(Op1, MVT::i8, DAG), ByteMask);
848 unsigned VecLen = Values.
size();
852 unsigned HwLen = Subtarget.getVectorLength();
854 unsigned ElemSize = ElemWidth / 8;
855 assert(ElemSize*VecLen == HwLen);
859 !(Subtarget.useHVXFloatingPoint() &&
861 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
862 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
864 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
865 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
873 unsigned NumValues = Values.size();
876 for (
unsigned i = 0; i != NumValues; ++i) {
877 if (Values[i].isUndef())
880 if (!SplatV.getNode())
882 else if (SplatV != Values[i])
890 unsigned NumWords = Words.
size();
892 bool IsSplat =
isSplat(Words, SplatV);
893 if (IsSplat && isUndef(SplatV))
898 return getZero(dl, VecTy, DAG);
907 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
910 (Constant**)Consts.end());
912 Align Alignment(HwLen);
926 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
927 SmallVectorImpl<int> &SrcIdx) {
931 SrcIdx.push_back(-1);
944 int I =
C->getSExtValue();
945 assert(
I >= 0 &&
"Negative element index");
952 SmallVector<int,128> ExtIdx;
954 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
955 MVT ExtTy = ty(ExtVec);
957 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
961 SmallVector<int,128>
Mask;
962 BitVector
Used(ExtLen);
964 for (
int M : ExtIdx) {
974 for (
unsigned I = 0;
I != ExtLen; ++
I) {
975 if (
Mask.size() == ExtLen)
983 return ExtLen == VecLen ? S : LoHalf(S, DAG);
991 assert(4*Words.
size() == Subtarget.getVectorLength());
994 for (
unsigned i = 0; i != NumWords; ++i) {
996 if (Words[i].isUndef())
998 for (
unsigned j = i;
j != NumWords; ++
j)
999 if (Words[i] == Words[j])
1002 if (VecHist[i] > VecHist[n])
1006 SDValue HalfV = getZero(dl, VecTy, DAG);
1007 if (VecHist[n] > 1) {
1010 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1022 for (
unsigned i = 0; i != NumWords/2; ++i) {
1024 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1028 {HalfV0, Words[i]});
1031 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1035 {HalfV1, Words[i+NumWords/2]});
1058HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1059 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1060 MVT PredTy = ty(PredV);
1061 unsigned HwLen = Subtarget.getVectorLength();
1064 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1074 SmallVector<int,128>
Mask(HwLen);
1079 for (
unsigned i = 0; i != HwLen; ++i) {
1080 unsigned Num = i % Scale;
1081 unsigned Off = i / Scale;
1090 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1092 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1099 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1108 if (Bytes < BitBytes) {
1114 while (Bytes < BitBytes) {
1116 Words[IdxW].
clear();
1119 for (
const SDValue &W : Words[IdxW ^ 1]) {
1120 SDValue T = expandPredicate(W, dl, DAG);
1125 for (
const SDValue &W : Words[IdxW ^ 1]) {
1133 while (Bytes > BitBytes) {
1135 Words[IdxW].
clear();
1138 for (
const SDValue &W : Words[IdxW ^ 1]) {
1139 SDValue T = contractPredicate(W, dl, DAG);
1143 for (
const SDValue &W : Words[IdxW ^ 1]) {
1150 assert(Bytes == BitBytes);
1151 if (BitBytes == 1 && PredTy == MVT::v2i1)
1154 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1156 for (
const SDValue &W : Words[IdxW]) {
1170 unsigned VecLen = Values.
size();
1171 unsigned HwLen = Subtarget.getVectorLength();
1172 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1174 bool AllT =
true, AllF =
true;
1178 return !
N->isZero();
1187 if (VecLen <= HwLen) {
1191 assert(HwLen % VecLen == 0);
1192 unsigned BitBytes = HwLen / VecLen;
1199 for (
unsigned B = 0;
B != BitBytes; ++
B)
1206 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1209 for (;
B != 8; ++
B) {
1210 if (!Values[
I+
B].isUndef())
1223 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1233 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1238HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1243 assert(ElemWidth >= 8 && ElemWidth <= 32);
1246 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1249 if (ElemTy == MVT::i32)
1255 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1258 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1262HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1265 assert(ResTy == MVT::i1);
1267 unsigned HwLen = Subtarget.getVectorLength();
1271 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1275 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1277 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1281HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1286 assert(ElemWidth >= 8 && ElemWidth <= 32);
1291 MVT VecTy = ty(VecV);
1292 unsigned HwLen = Subtarget.getVectorLength();
1304 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1305 if (ElemTy == MVT::i32)
1306 return InsertWord(VecV, ValV, ByteIdx);
1312 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1317 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1318 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1320 ValV, SubIdx, dl, ElemTy, DAG);
1323 return InsertWord(VecV, Ins, ByteIdx);
1327HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1329 unsigned HwLen = Subtarget.getVectorLength();
1333 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1338 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1343HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1345 MVT VecTy = ty(VecV);
1346 unsigned HwLen = Subtarget.getVectorLength();
1354 if (isHvxPairTy(VecTy)) {
1355 unsigned SubIdx = Hexagon::vsub_lo;
1356 if (Idx * ElemWidth >= 8 * HwLen) {
1357 SubIdx = Hexagon::vsub_hi;
1361 VecTy = typeSplit(VecTy).first;
1371 MVT WordTy = tyVector(VecTy, MVT::i32);
1373 unsigned WordIdx = (Idx*ElemWidth) / 32;
1376 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1381 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1382 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1387HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1389 MVT VecTy = ty(VecV);
1390 unsigned HwLen = Subtarget.getVectorLength();
1398 unsigned Offset = Idx * BitBytes;
1400 SmallVector<int,128>
Mask;
1402 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1409 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1410 for (
unsigned j = 0;
j != Rep; ++
j)
1427 unsigned Rep = 8 / ResLen;
1430 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1432 for (
unsigned i = 0; i != ResLen; ++i) {
1433 for (
unsigned j = 0;
j != Rep; ++
j)
1445 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1446 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1451HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1453 MVT VecTy = ty(VecV);
1454 MVT SubTy = ty(SubV);
1455 unsigned HwLen = Subtarget.getVectorLength();
1459 bool IsPair = isHvxPairTy(VecTy);
1467 V0 = LoHalf(VecV, DAG);
1468 V1 = HiHalf(VecV, DAG);
1473 if (isHvxSingleTy(SubTy)) {
1475 unsigned Idx = CN->getZExtValue();
1477 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1500 if (!IdxN || !IdxN->isZero()) {
1508 unsigned RolBase = HwLen;
1523 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1538HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1540 MVT VecTy = ty(VecV);
1541 MVT SubTy = ty(SubV);
1542 assert(Subtarget.isHVXVectorType(VecTy,
true));
1547 unsigned HwLen = Subtarget.getVectorLength();
1548 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1551 unsigned BitBytes = HwLen / VecLen;
1552 unsigned BlockLen = HwLen / Scale;
1556 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1560 if (!IdxN || !IdxN->isZero()) {
1569 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1571 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1573 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1575 if (!IdxN || !IdxN->isZero()) {
1584HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1589 assert(Subtarget.isHVXVectorType(ResTy));
1596 SDValue False = getZero(dl, ResTy, DAG);
1597 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1601HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1609 unsigned HwLen = Subtarget.getVectorLength();
1611 MVT PredTy = ty(VecQ);
1613 assert(HwLen % PredLen == 0);
1620 for (
unsigned i = 0; i != HwLen/8; ++i) {
1621 for (
unsigned j = 0;
j != 8; ++
j)
1622 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1625 Align Alignment(HwLen);
1634 getZero(dl, VecTy, DAG));
1640 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1642 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1649 SmallVector<int,128>
Mask;
1650 for (
unsigned i = 0; i != HwLen; ++i)
1651 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1661 MVT InpTy = ty(VecV);
1669 return InpWidth < ResWidth
1670 ? DAG.
getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1677 if (InpWidth < ResWidth) {
1679 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1687HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1691 const SDLoc &dl(Vec);
1700 const SDLoc &dl(
Op);
1705 for (
unsigned i = 0; i !=
Size; ++i)
1706 Ops.push_back(
Op.getOperand(i));
1709 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1717 for (
unsigned i = 0; i !=
Size; i++)
1728 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1730 MVT SingleTy = typeSplit(VecTy).first;
1731 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1732 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1736 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1742 const SDLoc &dl(
Op);
1744 MVT ArgTy = ty(
Op.getOperand(0));
1746 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1764 const SDLoc &dl(
Op);
1781 MVT NTy = typeLegalize(Ty, DAG);
1785 V.getOperand(0),
V.getOperand(1)),
1790 switch (
V.getOpcode()) {
1798 V =
V.getOperand(0);
1809 unsigned HwLen = Subtarget.getVectorLength();
1816 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1824 MVT HalfTy = typeSplit(VecTy).first;
1826 Ops.take_front(NumOp/2));
1828 Ops.take_back(NumOp/2));
1837 for (
SDValue V :
Op.getNode()->op_values()) {
1838 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1842 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1845 SDValue Res = getZero(dl, ByteTy, DAG);
1846 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1859 const SDLoc &dl(
Op);
1861 if (ElemTy == MVT::i1)
1862 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1864 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1870 const SDLoc &dl(
Op);
1876 if (ElemTy == MVT::i1)
1877 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1879 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1881 tyVector(VecTy, MVT::i16),
1882 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1884 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1887 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1894 MVT SrcTy = ty(SrcV);
1900 const SDLoc &dl(
Op);
1903 if (ElemTy == MVT::i1)
1904 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1906 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1917 const SDLoc &dl(
Op);
1918 MVT VecTy = ty(VecV);
1920 if (ElemTy == MVT::i1)
1921 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1923 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1935 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1936 return LowerHvxSignExt(
Op, DAG);
1945 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1946 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1955 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1956 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1964 const SDLoc &dl(
Op);
1967 assert(ResTy == ty(InpV));
1992 const SDLoc &dl(
Op);
1999 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
2000 unsigned Opc =
Op.getOpcode();
2016 const SDLoc &dl(
Op);
2017 unsigned Opc =
Op.getOpcode();
2022 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2034 if (Subtarget.useHVXV62Ops())
2035 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2040 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2041 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2047 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2054 MVT ValTy = ty(Val);
2055 const SDLoc &dl(
Op);
2058 unsigned HwLen = Subtarget.getVectorLength();
2060 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2075 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2077 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2082 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2083 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2096 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2097 assert(Val32.getValueType().getSizeInBits() == 32 &&
2098 "Input must be 32 bits");
2102 for (
unsigned i = 0; i < 32; ++i)
2110 if (ResTy == MVT::v32i1 &&
2111 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2112 Subtarget.useHVX128BOps()) {
2114 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2115 Val32 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Val);
2116 return bitcastI32ToV32I1(Val32);
2119 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2137 unsigned HwLen = Subtarget.getVectorLength();
2149 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2153 for (
unsigned J = 0; J != 8; ++J) {
2161 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2185 const SDLoc &dl(
Op);
2186 unsigned HwLen = Subtarget.getVectorLength();
2188 assert(HwLen % VecLen == 0);
2189 unsigned ElemSize = HwLen / VecLen;
2201 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2207HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2209 unsigned Opc =
Op.getOpcode();
2221 const SDLoc &dl(
Op);
2227 bool UseShifts = ElemTy != MVT::i8;
2228 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2231 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2239 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2255 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2264 const SDLoc &dl(
Op);
2265 unsigned IntNo =
Op.getConstantOperandVal(0);
2273 case Intrinsic::hexagon_V6_pred_typecast:
2274 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2275 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2276 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2283 case Intrinsic::hexagon_V6_vmpyss_parts:
2284 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2287 case Intrinsic::hexagon_V6_vmpyuu_parts:
2288 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2291 case Intrinsic::hexagon_V6_vmpyus_parts:
2292 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2303 const SDLoc &dl(
Op);
2304 unsigned HwLen = Subtarget.getVectorLength();
2308 SDValue Chain = MaskN->getChain();
2312 unsigned Opc =
Op->getOpcode();
2315 if (
Opc == ISD::MLOAD) {
2329 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2333 if (MaskN->getAlign().value() % HwLen == 0) {
2342 SDValue Z = getZero(dl, ty(V), DAG);
2346 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2347 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2348 return std::make_pair(LoV, HiV);
2354 VectorPair Tmp = StoreAlign(MaskV,
Base);
2357 VectorPair ValueU = StoreAlign(
Value,
Base);
2361 getInstr(StoreOpc, dl, MVT::Other,
2362 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2364 getInstr(StoreOpc, dl, MVT::Other,
2365 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2375 assert(Subtarget.useHVXQFloatOps());
2377 assert(
Op->getOpcode() == ISD::FP_EXTEND);
2380 MVT ArgTy = ty(
Op.getOperand(0));
2381 const SDLoc &dl(
Op);
2383 if (ArgTy == MVT::v64bf16) {
2384 MVT HalfTy = typeSplit(VecTy).first;
2387 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2392 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2393 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2395 {VecPair.second, VecPair.first,
2401 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2410 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2412 MVT HalfTy = typeSplit(VecTy).first;
2413 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2415 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2417 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2420 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2433 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2436 if (Subtarget.useHVXIEEEFPOps()) {
2438 if (FpTy == MVT::f16) {
2440 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2442 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2448 return EqualizeFpIntConversion(
Op, DAG);
2450 return ExpandHvxFpToInt(
Op, DAG);
2466 MVT ResTy = ty(PredOp);
2467 const SDLoc &dl(PredOp);
2470 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2471 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2473 SDNode *PredTransfer =
2476 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2479 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2484 SDNode *IndexShift =
2490 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2515 MVT ResTy = ty(PredOp);
2516 const SDLoc &dl(PredOp);
2526 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2527 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2532 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, HiReg));
2535 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, LoReg));
2537 SDNode *PredTransfer =
2541 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2548 SDNode *IndexShift_hi =
2551 SDNode *IndexShift_lo =
2555 SDNode *MaskOff_hi =
2558 SDNode *MaskOff_lo =
2581 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2582 return LowerHvxPred32ToFp(
Op, DAG);
2583 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2584 return LowerHvxPred64ToFp(
Op, DAG);
2587 if (Subtarget.useHVXIEEEFPOps()) {
2589 if (FpTy == MVT::f16) {
2591 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2593 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2599 return EqualizeFpIntConversion(
Op, DAG);
2601 return ExpandHvxIntToFp(
Op, DAG);
2604HexagonTargetLowering::TypePair
2605HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2616 unsigned MaxWidth = std::max(Width0, Width1);
2618 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2625 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2626 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2630 return {WideETy0, WideETy1};
2641HexagonTargetLowering::TypePair
2642HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2652 unsigned MaxLen = std::max(Len0, Len1);
2665HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2666 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2675HexagonTargetLowering::VectorPair
2706HexagonTargetLowering::VectorPair
2707HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2712 const SDLoc &dl(Val);
2713 MVT ValTy = ty(Val);
2727 MVT IntTy = tyVector(ValTy, ElemTy);
2739 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2758 MVT
PairTy = typeJoin({VecTy, VecTy});
2784 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2786 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2794 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2796 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2799 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2800 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2801 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2812HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2813 bool SignedB,
const SDLoc &dl,
2816 MVT
PairTy = typeJoin({VecTy, VecTy});
2821 if (SignedA && !SignedB) {
2837 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2838 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2839 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2848 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2851 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2855 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2856 {HiHalf(P2, DAG), T3,
S16}, DAG);
2859 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2860 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2864 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2871 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2872 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2873 }
else if (SignedB) {
2879 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2881 assert(!SignedA && !SignedB);
2888HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2893 MVT
PairTy = typeJoin({VecTy, VecTy});
2896 if (SignedA && !SignedB) {
2905 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2910 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2922 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2923 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2924 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2925 }
else if (!SignedA) {
2935 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2953 unsigned Opc =
Op.getOpcode();
2958 MVT InpTy = ty(Inp);
2964 const SDLoc &dl(
Op);
2967 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2976 unsigned Opc =
Op.getOpcode();
2979 const SDLoc &dl(
Op);
2981 MVT InpTy = ty(Op0);
2994 if (InpTy == MVT::v64f16) {
2995 if (Subtarget.useHVXV81Ops()) {
2998 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3002 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3007 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3087 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3088 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3131 unsigned Opc =
Op.getOpcode();
3134 const SDLoc &dl(
Op);
3136 MVT InpTy = ty(Op0);
3169 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3179 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3202 unsigned Opc =
Op.getOpcode();
3219 const SDLoc &dl(
Op);
3220 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3229 unsigned Opc =
Op.getConstantOperandVal(2);
3233HexagonTargetLowering::VectorPair
3237 const SDLoc &dl(
Op);
3239 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3240 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3242 return std::make_pair(TV, TV);
3247 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3249 switch (
Op.getOpcode()) {
3250 case ISD::SIGN_EXTEND_INREG:
3251 case HexagonISD::SSAT:
3252 case HexagonISD::USAT:
3253 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3254 std::tie(Lo, Hi) = SplitVTNode(N);
3262 MVT HalfTy = typeSplit(ResTy).first;
3272 if (!MemN->getMemoryVT().isSimple())
3275 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3276 if (!isHvxPairTy(MemTy))
3279 const SDLoc &dl(
Op);
3280 unsigned HwLen = Subtarget.getVectorLength();
3281 MVT SingleTy = typeSplit(MemTy).first;
3282 SDValue Chain = MemN->getChain();
3283 SDValue Base0 = MemN->getBasePtr();
3288 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3289 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3291 uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3298 if (MemOpc == ISD::LOAD) {
3307 if (MemOpc == ISD::STORE) {
3315 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3318 assert(MaskN->isUnindexed());
3319 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3322 if (MemOpc == ISD::MLOAD) {
3338 if (MemOpc == ISD::MSTORE) {
3341 Masks.first, SingleTy, MOp0,
3344 Masks.second, SingleTy, MOp1,
3349 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3355 const SDLoc &dl(
Op);
3357 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3358 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3359 "Not widening loads of i1 yet");
3361 SDValue Chain = LoadN->getChain();
3366 unsigned HwLen = Subtarget.getVectorLength();
3368 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3371 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3379 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3387 const SDLoc &dl(
Op);
3389 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3390 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3391 "Not widening stores of i1 yet");
3393 SDValue Chain = StoreN->getChain();
3397 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3398 MVT ValueTy = ty(
Value);
3400 unsigned HwLen = Subtarget.getVectorLength();
3403 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3405 Len = ty(
Value).getVectorNumElements();
3407 assert(ty(
Value).getVectorNumElements() == HwLen);
3409 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3411 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3414 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3421 const SDLoc &dl(
Op);
3422 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3424 unsigned HwLen = Subtarget.getVectorLength();
3429 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3432 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3433 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3437 {WideOp0, WideOp1,
Op.getOperand(2)});
3439 EVT RetTy = typeLegalize(ty(
Op), DAG);
3441 {SetCC, getZero(dl, MVT::i32, DAG)});
3446 unsigned Opc =
Op.getOpcode();
3447 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3449 return isHvxPairTy(ty(V));
3460 return SplitHvxMemOp(
Op, DAG);
3465 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3466 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3476 case ISD::FMINIMUMNUM:
3477 case ISD::FMAXIMUMNUM:
3496 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3501 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3502 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3517 case ISD::BITCAST:
return LowerHvxBitcast(
Op, DAG);
3525 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3527 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3537 case ISD::MSTORE:
return LowerHvxMaskedOp(
Op, DAG);
3539 case ISD::LOAD:
return SDValue();
3540 case ISD::FP_EXTEND:
return LowerHvxFpExtend(
Op, DAG);
3566 unsigned Opc =
Op.getOpcode();
3586 MVT InpTy = ty(Inp);
3591 assert(InpWidth != ResWidth);
3593 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3596 const SDLoc &dl(
Op);
3600 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3608 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3615 if (InpWidth < ResWidth) {
3617 while (InpWidth * 2 <= ResWidth)
3618 S = repeatOp(InpWidth *= 2, S);
3622 while (InpWidth / 2 >= ResWidth)
3623 S = repeatOp(InpWidth /= 2, S);
3631 MVT InpTy = ty(Inp0);
3635 unsigned Opc =
Op.getOpcode();
3637 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3642 auto [WInpTy, WResTy] =
3643 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3644 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3645 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3653 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3654 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3655 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3656 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3659 return RemoveTLWrapper(
Op, DAG);
3665HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3667 unsigned Opc =
N->getOpcode();
3670 if (
N->getNumOperands() > 0)
3671 Inp0 =
Op.getOperand(0);
3678 if (Subtarget.isHVXElementType(ty(
Op)) &&
3679 Subtarget.isHVXElementType(ty(Inp0))) {
3680 Results.push_back(CreateTLWrapper(
Op, DAG));
3684 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3697 if (isHvxPairTy(ty(
Op))) {
3705 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3714 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3715 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3723 Results.push_back(LegalizeHvxResize(
Op, DAG));
3731HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3733 unsigned Opc =
N->getOpcode();
3736 if (
N->getNumOperands() > 0)
3737 Inp0 =
Op.getOperand(0);
3744 if (Subtarget.isHVXElementType(ty(
Op)) &&
3745 Subtarget.isHVXElementType(ty(Inp0))) {
3746 Results.push_back(CreateTLWrapper(
Op, DAG));
3750 if (shouldWidenToHvx(ty(
Op), DAG)) {
3756 if (shouldWidenToHvx(ty(
Op), DAG)) {
3765 if (isHvxBoolTy(ty(Inp0))) {
3772 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3773 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3781 Results.push_back(LegalizeHvxResize(
Op, DAG));
3789HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3790 DAGCombinerInfo &DCI)
const {
3795 SelectionDAG &DAG = DCI.DAG;
3796 const SDLoc &dl(
Op);
3798 if (
Op.getOperand(0).getOpcode() == ISD::BITCAST)
3803 EVT TruncTy =
Op.getValueType();
3805 EVT SrcTy = Src.getValueType();
3812 if (2 * CastLen != SrcLen)
3815 SmallVector<int, 128>
Mask(SrcLen);
3816 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3818 Mask[i + CastLen] = 2 * i + 1;
3822 return opSplit(Deal, dl, DAG).first;
3826HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3827 SDValue Op, DAGCombinerInfo &DCI)
const {
3835 SelectionDAG &DAG = DCI.DAG;
3836 const SDLoc &dl(
Op);
3845 SetVector<SDValue> Order;
3851 if (Order.
size() > 2)
3860 SmallVector<int, 128> LongMask;
3861 auto AppendToMask = [&](
SDValue Shuffle) {
3863 ArrayRef<int>
Mask = SV->getMask();
3866 for (
int M : Mask) {
3871 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3872 if (
static_cast<unsigned>(M) >= InpLen)
3875 int OutOffset = Order[0] == Src ? 0 : InpLen;
3892HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3895 SelectionDAG &DAG = DCI.DAG;
3897 unsigned Opc =
Op.getOpcode();
3902 return combineTruncateBeforeLegal(
Op, DCI);
3904 return combineConcatVectorsBeforeLegal(
Op, DCI);
3906 if (DCI.isBeforeLegalizeOps())
3932 return getZero(dl, ty(
Op), DAG);
3935 if (isUndef(
Ops[1]))
3953HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3954 if (Subtarget.isHVXVectorType(Ty,
true))
3956 auto Action = getPreferredHvxVectorAction(Ty);
3958 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3963HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3964 if (Subtarget.isHVXVectorType(Ty,
true))
3966 auto Action = getPreferredHvxVectorAction(Ty);
3968 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3974 if (!Subtarget.useHVXOps())
3978 auto IsHvxTy = [
this](EVT Ty) {
3979 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
3982 return Op.getValueType().isSimple() &&
3983 Subtarget.isHVXVectorType(ty(
Op),
true);
3989 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3990 if (!
Op.getValueType().isSimple())
3993 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3996 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static cl::opt< unsigned > HvxWidenThreshold("hexagon-hvx-widen", cl::Hidden, cl::init(16), cl::desc("Lower threshold (in bytes) for widening to HVX vectors"))
static cl::opt< bool > EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false), cl::desc("Enable FP fast conversion routine."))
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
const SmallVectorImpl< MachineOperand > & Cond
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
uint64_t getNumOperands() const
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
EVT getSetCCResultType(const DataLayout &, LLVMContext &C, EVT VT) const override
Return the ValueType of the result of SETCC operations.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
static MVT getFloatingPointVT(unsigned BitWidth)
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Flags
Flags values. These may be or'd together.
unsigned getSubReg() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
size_type size() const
Determine the number of elements in the SetVector.
const value_type & front() const
Return the first element of the SetVector.
const value_type & back() const
Return the last element of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
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.