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);
197 for (MVT
P : FloatW) {
219 if (Subtarget.useHVXQFloatOps()) {
222 }
else if (Subtarget.useHVXIEEEFPOps()) {
228 for (MVT
T : LegalV) {
255 if (
T.getScalarType() != MVT::i32) {
264 if (
T.getScalarType() != MVT::i32) {
292 if (Subtarget.useHVXFloatingPoint()) {
309 for (MVT
T : LegalW) {
364 if (
T.getScalarType() != MVT::i32) {
369 if (Subtarget.useHVXFloatingPoint()) {
416 for (MVT
T : LegalW) {
433 for (MVT
T : LegalV) {
448 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
451 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
456 unsigned HwLen = Subtarget.getVectorLength();
457 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
458 if (ElemTy == MVT::i1)
460 int ElemWidth = ElemTy.getFixedSizeInBits();
461 int MaxElems = (8*HwLen) / ElemWidth;
462 for (
int N = 2;
N < MaxElems;
N *= 2) {
474 if (Subtarget.useHVXFloatingPoint()) {
497HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
504 unsigned HwLen = Subtarget.getVectorLength();
507 if (ElemTy == MVT::i1 && VecLen > HwLen)
513 if (ElemTy == MVT::i1) {
528 unsigned HwWidth = 8*HwLen;
529 if (VecWidth > 2*HwWidth)
535 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
544HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
545 unsigned Opc =
Op.getOpcode();
565HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
566 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
570 Tys.second.getVectorNumElements());
573HexagonTargetLowering::TypePair
574HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
577 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
579 return { HalfTy, HalfTy };
583HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
590HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
597HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
606HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
612HexagonTargetLowering::VectorPair
613HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
615 TypePair Tys = typeSplit(ty(Vec));
618 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
622HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
623 return Subtarget.isHVXVectorType(Ty) &&
628HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
629 return Subtarget.isHVXVectorType(Ty) &&
634HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
635 return Subtarget.isHVXVectorType(Ty,
true) &&
639bool HexagonTargetLowering::allowsHvxMemoryAccess(
647 if (!Subtarget.isHVXVectorType(VecTy,
false))
654bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
656 if (!Subtarget.isHVXVectorType(VecTy))
664void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
666 unsigned Opc =
MI.getOpcode();
667 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
668 MachineBasicBlock &MB = *
MI.getParent();
672 auto At =
MI.getIterator();
675 case Hexagon::PS_vsplatib:
676 if (Subtarget.useHVXV62Ops()) {
679 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
681 .
add(
MI.getOperand(1));
688 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
689 const MachineOperand &InpOp =
MI.getOperand(1);
691 uint32_t
V = InpOp.
getImm() & 0xFF;
693 .
addImm(V << 24 | V << 16 | V << 8 | V);
699 case Hexagon::PS_vsplatrb:
700 if (Subtarget.useHVXV62Ops()) {
704 .
add(
MI.getOperand(1));
706 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
707 const MachineOperand &InpOp =
MI.getOperand(1);
716 case Hexagon::PS_vsplatih:
717 if (Subtarget.useHVXV62Ops()) {
720 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
722 .
add(
MI.getOperand(1));
729 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
730 const MachineOperand &InpOp =
MI.getOperand(1);
732 uint32_t
V = InpOp.
getImm() & 0xFFFF;
740 case Hexagon::PS_vsplatrh:
741 if (Subtarget.useHVXV62Ops()) {
745 .
add(
MI.getOperand(1));
749 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
750 const MachineOperand &InpOp =
MI.getOperand(1);
759 case Hexagon::PS_vsplatiw:
760 case Hexagon::PS_vsplatrw:
761 if (
Opc == Hexagon::PS_vsplatiw) {
763 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
765 .
add(
MI.getOperand(1));
766 MI.getOperand(1).ChangeToRegister(SplatV,
false);
769 MI.setDesc(
TII.
get(Hexagon::V6_lvsplatw));
775HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
785 const SDLoc &dl(ElemIdx);
791HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
794 assert(ElemWidth >= 8 && ElemWidth <= 32);
798 if (ty(Idx) != MVT::i32)
800 const SDLoc &dl(Idx);
807HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
814 if (ElemTy == MVT::i8)
818 MVT ResTy = tyVector(OpTy, MVT::i8);
821 SmallVector<int,128> ByteMask;
824 for (
unsigned I = 0;
I != ElemSize; ++
I)
827 int NewM =
M*ElemSize;
828 for (
unsigned I = 0;
I != ElemSize; ++
I)
834 opCastElem(Op1, MVT::i8, DAG), ByteMask);
841 unsigned VecLen = Values.
size();
845 unsigned HwLen = Subtarget.getVectorLength();
847 unsigned ElemSize = ElemWidth / 8;
848 assert(ElemSize*VecLen == HwLen);
852 !(Subtarget.useHVXFloatingPoint() &&
854 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
855 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
857 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
858 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
866 unsigned NumValues = Values.size();
869 for (
unsigned i = 0; i != NumValues; ++i) {
870 if (Values[i].isUndef())
873 if (!SplatV.getNode())
875 else if (SplatV != Values[i])
883 unsigned NumWords = Words.
size();
885 bool IsSplat =
isSplat(Words, SplatV);
886 if (IsSplat && isUndef(SplatV))
891 return getZero(dl, VecTy, DAG);
900 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
903 (Constant**)Consts.end());
905 Align Alignment(HwLen);
919 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
920 SmallVectorImpl<int> &SrcIdx) {
924 SrcIdx.push_back(-1);
937 int I =
C->getSExtValue();
938 assert(
I >= 0 &&
"Negative element index");
945 SmallVector<int,128> ExtIdx;
947 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
948 MVT ExtTy = ty(ExtVec);
950 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
954 SmallVector<int,128>
Mask;
955 BitVector
Used(ExtLen);
957 for (
int M : ExtIdx) {
967 for (
unsigned I = 0;
I != ExtLen; ++
I) {
968 if (
Mask.size() == ExtLen)
976 return ExtLen == VecLen ? S : LoHalf(S, DAG);
984 assert(4*Words.
size() == Subtarget.getVectorLength());
987 for (
unsigned i = 0; i != NumWords; ++i) {
989 if (Words[i].isUndef())
991 for (
unsigned j = i;
j != NumWords; ++
j)
992 if (Words[i] == Words[j])
995 if (VecHist[i] > VecHist[n])
999 SDValue HalfV = getZero(dl, VecTy, DAG);
1000 if (VecHist[n] > 1) {
1003 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1015 for (
unsigned i = 0; i != NumWords/2; ++i) {
1017 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1021 {HalfV0, Words[i]});
1024 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1028 {HalfV1, Words[i+NumWords/2]});
1051HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1052 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1053 MVT PredTy = ty(PredV);
1054 unsigned HwLen = Subtarget.getVectorLength();
1057 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1067 SmallVector<int,128>
Mask(HwLen);
1072 for (
unsigned i = 0; i != HwLen; ++i) {
1073 unsigned Num = i % Scale;
1074 unsigned Off = i / Scale;
1083 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1085 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1092 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1101 if (Bytes < BitBytes) {
1107 while (Bytes < BitBytes) {
1109 Words[IdxW].
clear();
1112 for (
const SDValue &W : Words[IdxW ^ 1]) {
1113 SDValue T = expandPredicate(W, dl, DAG);
1118 for (
const SDValue &W : Words[IdxW ^ 1]) {
1126 while (Bytes > BitBytes) {
1128 Words[IdxW].
clear();
1131 for (
const SDValue &W : Words[IdxW ^ 1]) {
1132 SDValue T = contractPredicate(W, dl, DAG);
1136 for (
const SDValue &W : Words[IdxW ^ 1]) {
1143 assert(Bytes == BitBytes);
1144 if (BitBytes == 1 && PredTy == MVT::v2i1)
1147 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1149 for (
const SDValue &W : Words[IdxW]) {
1163 unsigned VecLen = Values.
size();
1164 unsigned HwLen = Subtarget.getVectorLength();
1165 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1167 bool AllT =
true, AllF =
true;
1171 return !
N->isZero();
1180 if (VecLen <= HwLen) {
1184 assert(HwLen % VecLen == 0);
1185 unsigned BitBytes = HwLen / VecLen;
1192 for (
unsigned B = 0;
B != BitBytes; ++
B)
1199 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1202 for (;
B != 8; ++
B) {
1203 if (!Values[
I+
B].isUndef())
1216 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1226 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1231HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1236 assert(ElemWidth >= 8 && ElemWidth <= 32);
1239 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1242 if (ElemTy == MVT::i32)
1248 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1251 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1255HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1258 assert(ResTy == MVT::i1);
1260 unsigned HwLen = Subtarget.getVectorLength();
1264 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1268 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1270 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1274HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1279 assert(ElemWidth >= 8 && ElemWidth <= 32);
1284 MVT VecTy = ty(VecV);
1285 unsigned HwLen = Subtarget.getVectorLength();
1297 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1298 if (ElemTy == MVT::i32)
1299 return InsertWord(VecV, ValV, ByteIdx);
1305 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1310 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1311 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1313 ValV, SubIdx, dl, ElemTy, DAG);
1316 return InsertWord(VecV, Ins, ByteIdx);
1320HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1322 unsigned HwLen = Subtarget.getVectorLength();
1326 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1331 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1336HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1338 MVT VecTy = ty(VecV);
1339 unsigned HwLen = Subtarget.getVectorLength();
1347 if (isHvxPairTy(VecTy)) {
1348 unsigned SubIdx = Hexagon::vsub_lo;
1349 if (Idx * ElemWidth >= 8 * HwLen) {
1350 SubIdx = Hexagon::vsub_hi;
1354 VecTy = typeSplit(VecTy).first;
1364 MVT WordTy = tyVector(VecTy, MVT::i32);
1366 unsigned WordIdx = (Idx*ElemWidth) / 32;
1369 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1374 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1375 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1380HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1382 MVT VecTy = ty(VecV);
1383 unsigned HwLen = Subtarget.getVectorLength();
1391 unsigned Offset = Idx * BitBytes;
1393 SmallVector<int,128>
Mask;
1395 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1402 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1403 for (
unsigned j = 0;
j != Rep; ++
j)
1420 unsigned Rep = 8 / ResLen;
1423 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1425 for (
unsigned i = 0; i != ResLen; ++i) {
1426 for (
unsigned j = 0;
j != Rep; ++
j)
1438 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1439 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1444HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1446 MVT VecTy = ty(VecV);
1447 MVT SubTy = ty(SubV);
1448 unsigned HwLen = Subtarget.getVectorLength();
1452 bool IsPair = isHvxPairTy(VecTy);
1460 V0 = LoHalf(VecV, DAG);
1461 V1 = HiHalf(VecV, DAG);
1466 if (isHvxSingleTy(SubTy)) {
1468 unsigned Idx = CN->getZExtValue();
1470 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1493 if (!IdxN || !IdxN->isZero()) {
1501 unsigned RolBase = HwLen;
1516 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1531HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1533 MVT VecTy = ty(VecV);
1534 MVT SubTy = ty(SubV);
1535 assert(Subtarget.isHVXVectorType(VecTy,
true));
1540 unsigned HwLen = Subtarget.getVectorLength();
1541 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1544 unsigned BitBytes = HwLen / VecLen;
1545 unsigned BlockLen = HwLen / Scale;
1549 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1553 if (!IdxN || !IdxN->isZero()) {
1562 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1564 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1566 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1568 if (!IdxN || !IdxN->isZero()) {
1577HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1582 assert(Subtarget.isHVXVectorType(ResTy));
1589 SDValue False = getZero(dl, ResTy, DAG);
1590 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1594HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1602 unsigned HwLen = Subtarget.getVectorLength();
1604 MVT PredTy = ty(VecQ);
1606 assert(HwLen % PredLen == 0);
1613 for (
unsigned i = 0; i != HwLen/8; ++i) {
1614 for (
unsigned j = 0;
j != 8; ++
j)
1615 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1618 Align Alignment(HwLen);
1627 getZero(dl, VecTy, DAG));
1633 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1635 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1642 SmallVector<int,128>
Mask;
1643 for (
unsigned i = 0; i != HwLen; ++i)
1644 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1654 MVT InpTy = ty(VecV);
1662 return InpWidth < ResWidth
1663 ? DAG.
getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1670 if (InpWidth < ResWidth) {
1672 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1680HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1684 const SDLoc &dl(Vec);
1693 const SDLoc &dl(
Op);
1698 for (
unsigned i = 0; i !=
Size; ++i)
1699 Ops.push_back(
Op.getOperand(i));
1702 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1710 for (
unsigned i = 0; i !=
Size; i++)
1721 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1723 MVT SingleTy = typeSplit(VecTy).first;
1724 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1725 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1729 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1735 const SDLoc &dl(
Op);
1737 MVT ArgTy = ty(
Op.getOperand(0));
1739 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1757 const SDLoc &dl(
Op);
1774 MVT NTy = typeLegalize(Ty, DAG);
1778 V.getOperand(0),
V.getOperand(1)),
1783 switch (
V.getOpcode()) {
1791 V =
V.getOperand(0);
1802 unsigned HwLen = Subtarget.getVectorLength();
1809 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1817 MVT HalfTy = typeSplit(VecTy).first;
1819 Ops.take_front(NumOp/2));
1821 Ops.take_back(NumOp/2));
1830 for (
SDValue V :
Op.getNode()->op_values()) {
1831 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1835 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1838 SDValue Res = getZero(dl, ByteTy, DAG);
1839 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1852 const SDLoc &dl(
Op);
1854 if (ElemTy == MVT::i1)
1855 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1857 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1863 const SDLoc &dl(
Op);
1869 if (ElemTy == MVT::i1)
1870 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1872 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1874 tyVector(VecTy, MVT::i16),
1875 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1877 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1880 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1887 MVT SrcTy = ty(SrcV);
1893 const SDLoc &dl(
Op);
1896 if (ElemTy == MVT::i1)
1897 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1899 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1910 const SDLoc &dl(
Op);
1911 MVT VecTy = ty(VecV);
1913 if (ElemTy == MVT::i1)
1914 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1916 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1928 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1929 return LowerHvxSignExt(
Op, DAG);
1938 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1939 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1948 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1949 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1957 const SDLoc &dl(
Op);
1960 assert(ResTy == ty(InpV));
1985 const SDLoc &dl(
Op);
1992 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
1993 unsigned Opc =
Op.getOpcode();
2009 const SDLoc &dl(
Op);
2010 unsigned Opc =
Op.getOpcode();
2015 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2027 if (Subtarget.useHVXV62Ops())
2028 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2033 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2034 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2040 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2047 MVT ValTy = ty(Val);
2048 const SDLoc &dl(
Op);
2051 unsigned HwLen = Subtarget.getVectorLength();
2053 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2068 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2070 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2075 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2076 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2089 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2090 assert(Val32.getValueType().getSizeInBits() == 32 &&
2091 "Input must be 32 bits");
2095 for (
unsigned i = 0; i < 32; ++i)
2103 if (ResTy == MVT::v32i1 &&
2104 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2105 Subtarget.useHVX128BOps()) {
2107 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2108 Val32 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Val);
2109 return bitcastI32ToV32I1(Val32);
2112 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2130 unsigned HwLen = Subtarget.getVectorLength();
2142 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2146 for (
unsigned J = 0; J != 8; ++J) {
2154 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2178 const SDLoc &dl(
Op);
2179 unsigned HwLen = Subtarget.getVectorLength();
2181 assert(HwLen % VecLen == 0);
2182 unsigned ElemSize = HwLen / VecLen;
2194 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2200HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2202 unsigned Opc =
Op.getOpcode();
2214 const SDLoc &dl(
Op);
2220 bool UseShifts = ElemTy != MVT::i8;
2221 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2224 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2232 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2248 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2257 const SDLoc &dl(
Op);
2258 unsigned IntNo =
Op.getConstantOperandVal(0);
2266 case Intrinsic::hexagon_V6_pred_typecast:
2267 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2268 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2269 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2276 case Intrinsic::hexagon_V6_vmpyss_parts:
2277 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2280 case Intrinsic::hexagon_V6_vmpyuu_parts:
2281 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2284 case Intrinsic::hexagon_V6_vmpyus_parts:
2285 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2296 const SDLoc &dl(
Op);
2297 unsigned HwLen = Subtarget.getVectorLength();
2301 SDValue Chain = MaskN->getChain();
2305 unsigned Opc =
Op->getOpcode();
2308 if (
Opc == ISD::MLOAD) {
2322 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2326 if (MaskN->getAlign().value() % HwLen == 0) {
2335 SDValue Z = getZero(dl, ty(V), DAG);
2339 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2340 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2341 return std::make_pair(LoV, HiV);
2347 VectorPair Tmp = StoreAlign(MaskV,
Base);
2350 VectorPair ValueU = StoreAlign(
Value,
Base);
2354 getInstr(StoreOpc, dl, MVT::Other,
2355 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2357 getInstr(StoreOpc, dl, MVT::Other,
2358 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2368 assert(Subtarget.useHVXQFloatOps());
2370 assert(
Op->getOpcode() == ISD::FP_EXTEND);
2373 MVT ArgTy = ty(
Op.getOperand(0));
2374 const SDLoc &dl(
Op);
2376 if (ArgTy == MVT::v64bf16) {
2377 MVT HalfTy = typeSplit(VecTy).first;
2380 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2385 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2386 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2388 {VecPair.second, VecPair.first,
2394 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2403 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2405 MVT HalfTy = typeSplit(VecTy).first;
2406 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2408 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2410 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2413 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2426 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2429 if (Subtarget.useHVXIEEEFPOps()) {
2431 if (FpTy == MVT::f16) {
2433 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2435 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2441 return EqualizeFpIntConversion(
Op, DAG);
2443 return ExpandHvxFpToInt(
Op, DAG);
2459 MVT ResTy = ty(PredOp);
2460 const SDLoc &dl(PredOp);
2463 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2464 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2466 SDNode *PredTransfer =
2469 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2472 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2477 SDNode *IndexShift =
2483 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2508 MVT ResTy = ty(PredOp);
2509 const SDLoc &dl(PredOp);
2519 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2520 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2525 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, HiReg));
2528 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, LoReg));
2530 SDNode *PredTransfer =
2534 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2541 SDNode *IndexShift_hi =
2544 SDNode *IndexShift_lo =
2548 SDNode *MaskOff_hi =
2551 SDNode *MaskOff_lo =
2574 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2575 return LowerHvxPred32ToFp(
Op, DAG);
2576 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2577 return LowerHvxPred64ToFp(
Op, DAG);
2580 if (Subtarget.useHVXIEEEFPOps()) {
2582 if (FpTy == MVT::f16) {
2584 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2586 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2592 return EqualizeFpIntConversion(
Op, DAG);
2594 return ExpandHvxIntToFp(
Op, DAG);
2597HexagonTargetLowering::TypePair
2598HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2609 unsigned MaxWidth = std::max(Width0, Width1);
2611 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2618 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2619 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2623 return {WideETy0, WideETy1};
2634HexagonTargetLowering::TypePair
2635HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2645 unsigned MaxLen = std::max(Len0, Len1);
2658HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2659 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2668HexagonTargetLowering::VectorPair
2699HexagonTargetLowering::VectorPair
2700HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2705 const SDLoc &dl(Val);
2706 MVT ValTy = ty(Val);
2720 MVT IntTy = tyVector(ValTy, ElemTy);
2732 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2751 MVT
PairTy = typeJoin({VecTy, VecTy});
2777 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2779 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2787 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2789 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2792 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2793 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2794 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2805HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2806 bool SignedB,
const SDLoc &dl,
2809 MVT
PairTy = typeJoin({VecTy, VecTy});
2814 if (SignedA && !SignedB) {
2830 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2831 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2832 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2841 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2844 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2848 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2849 {HiHalf(P2, DAG), T3,
S16}, DAG);
2852 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2853 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2857 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2864 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2865 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2866 }
else if (SignedB) {
2872 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2874 assert(!SignedA && !SignedB);
2881HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2886 MVT
PairTy = typeJoin({VecTy, VecTy});
2889 if (SignedA && !SignedB) {
2898 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2903 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2915 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2916 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2917 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2918 }
else if (!SignedA) {
2928 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2946 unsigned Opc =
Op.getOpcode();
2951 MVT InpTy = ty(Inp);
2957 const SDLoc &dl(
Op);
2960 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2969 unsigned Opc =
Op.getOpcode();
2972 const SDLoc &dl(
Op);
2974 MVT InpTy = ty(Op0);
2987 if (InpTy == MVT::v64f16) {
2988 if (Subtarget.useHVXV81Ops()) {
2991 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
2995 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3000 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3080 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3081 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3124 unsigned Opc =
Op.getOpcode();
3127 const SDLoc &dl(
Op);
3129 MVT InpTy = ty(Op0);
3162 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3172 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3195 unsigned Opc =
Op.getOpcode();
3212 const SDLoc &dl(
Op);
3213 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3222 unsigned Opc =
Op.getConstantOperandVal(2);
3226HexagonTargetLowering::VectorPair
3230 const SDLoc &dl(
Op);
3232 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3233 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3235 return std::make_pair(TV, TV);
3240 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3242 switch (
Op.getOpcode()) {
3243 case ISD::SIGN_EXTEND_INREG:
3244 case HexagonISD::SSAT:
3245 case HexagonISD::USAT:
3246 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3247 std::tie(Lo, Hi) = SplitVTNode(N);
3255 MVT HalfTy = typeSplit(ResTy).first;
3265 if (!MemN->getMemoryVT().isSimple())
3268 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3269 if (!isHvxPairTy(MemTy))
3272 const SDLoc &dl(
Op);
3273 unsigned HwLen = Subtarget.getVectorLength();
3274 MVT SingleTy = typeSplit(MemTy).first;
3275 SDValue Chain = MemN->getChain();
3276 SDValue Base0 = MemN->getBasePtr();
3281 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3282 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3284 uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3291 if (MemOpc == ISD::LOAD) {
3300 if (MemOpc == ISD::STORE) {
3308 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3311 assert(MaskN->isUnindexed());
3312 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3315 if (MemOpc == ISD::MLOAD) {
3331 if (MemOpc == ISD::MSTORE) {
3334 Masks.first, SingleTy, MOp0,
3337 Masks.second, SingleTy, MOp1,
3342 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3348 const SDLoc &dl(
Op);
3350 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3351 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3352 "Not widening loads of i1 yet");
3354 SDValue Chain = LoadN->getChain();
3359 unsigned HwLen = Subtarget.getVectorLength();
3361 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3364 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3372 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3380 const SDLoc &dl(
Op);
3382 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3383 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3384 "Not widening stores of i1 yet");
3386 SDValue Chain = StoreN->getChain();
3390 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3391 MVT ValueTy = ty(
Value);
3393 unsigned HwLen = Subtarget.getVectorLength();
3396 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3398 Len = ty(
Value).getVectorNumElements();
3400 assert(ty(
Value).getVectorNumElements() == HwLen);
3402 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3404 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3407 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3414 const SDLoc &dl(
Op);
3415 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3417 unsigned HwLen = Subtarget.getVectorLength();
3422 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3425 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3426 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3430 {WideOp0, WideOp1,
Op.getOperand(2)});
3432 EVT RetTy = typeLegalize(ty(
Op), DAG);
3434 {SetCC, getZero(dl, MVT::i32, DAG)});
3439 const SDLoc &dl(
Op);
3440 unsigned HwWidth = 8 * Subtarget.getVectorLength();
3441 bool IsResInterleaved =
false;
3447 if (!Subtarget.isHVXElementType(OpTy) || !Subtarget.isHVXElementType(ResTy))
3450 auto getFactor = [HwWidth](MVT Ty) {
3452 assert(HwWidth % Width == 0);
3453 return HwWidth / Width;
3456 auto getWideTy = [getFactor](MVT Ty) {
3463 SDValue WideOp1 = appendUndef(Op1, getWideTy(OpTy), DAG);
3468 WideOp2 = appendUndef(Op2, getWideTy(OpTy), DAG);
3470 unsigned WidenFactor = getFactor(OpTy);
3477 case Intrinsic::hexagon_vasrsat_su:
3478 case Intrinsic::hexagon_vasrsat_uu:
3479 case Intrinsic::hexagon_vasrsat_ss:
3481 DAG.
getConstant(IID, dl, MVT::i32), WideOp1, WideOp2,
3484 case Intrinsic::hexagon_vadd_su:
3485 case Intrinsic::hexagon_vadd_uu:
3486 case Intrinsic::hexagon_vadd_ss:
3487 case Intrinsic::hexagon_vadd_us:
3489 case Intrinsic::hexagon_vsub_su:
3490 case Intrinsic::hexagon_vsub_uu:
3491 case Intrinsic::hexagon_vsub_ss:
3492 case Intrinsic::hexagon_vsub_us:
3494 case Intrinsic::hexagon_vmpy_su:
3495 case Intrinsic::hexagon_vmpy_uu:
3496 case Intrinsic::hexagon_vmpy_ss:
3497 case Intrinsic::hexagon_vmpy_us:
3498 case Intrinsic::hexagon_vmpy_ub_ub:
3499 case Intrinsic::hexagon_vmpy_ub_b:
3500 case Intrinsic::hexagon_vmpy_uh_uh:
3501 case Intrinsic::hexagon_vmpy_h_h:
3502 IsResInterleaved =
true;
3504 DAG.
getConstant(IID, dl, MVT::i32), WideOp1, WideOp2);
3506 case Intrinsic::hexagon_vavgu:
3507 case Intrinsic::hexagon_vavgs:
3509 DAG.
getConstant(IID, dl, MVT::i32), WideOp1, WideOp2);
3513 assert(OrigLen % 2 == 0);
3514 unsigned HalfOrigLen = OrigLen / 2;
3515 unsigned SplitLen = WideLen / 2;
3516 if (IsResInterleaved) {
3521 SmallVector<int, 128> ShuffV;
3522 for (
unsigned j = 0;
j < WidenFactor;
j++) {
3523 for (
unsigned i = 0; i < HalfOrigLen; i++)
3525 for (
unsigned i = 0; i < HalfOrigLen; i++)
3526 ShuffV.
push_back(SplitLen + j * HalfOrigLen + i);
3532 {WideRes, getZero(dl, MVT::i32, DAG)});
3537 unsigned Opc =
Op.getOpcode();
3538 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3540 return isHvxPairTy(ty(V));
3551 return SplitHvxMemOp(
Op, DAG);
3556 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3557 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3567 case ISD::FMINIMUMNUM:
3568 case ISD::FMAXIMUMNUM:
3587 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3592 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3593 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3608 case ISD::BITCAST:
return LowerHvxBitcast(
Op, DAG);
3616 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3618 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3628 case ISD::MSTORE:
return LowerHvxMaskedOp(
Op, DAG);
3630 case ISD::LOAD:
return SDValue();
3631 case ISD::FP_EXTEND:
return LowerHvxFpExtend(
Op, DAG);
3657 unsigned Opc =
Op.getOpcode();
3677 MVT InpTy = ty(Inp);
3682 assert(InpWidth != ResWidth);
3684 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3687 const SDLoc &dl(
Op);
3691 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3699 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3706 if (InpWidth < ResWidth) {
3708 while (InpWidth * 2 <= ResWidth)
3709 S = repeatOp(InpWidth *= 2, S);
3713 while (InpWidth / 2 >= ResWidth)
3714 S = repeatOp(InpWidth /= 2, S);
3722 MVT InpTy = ty(Inp0);
3726 unsigned Opc =
Op.getOpcode();
3728 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3733 auto [WInpTy, WResTy] =
3734 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3735 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3736 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3744 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3745 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3746 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3747 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3750 return RemoveTLWrapper(
Op, DAG);
3756HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3758 unsigned Opc =
N->getOpcode();
3761 if (
N->getNumOperands() > 0)
3762 Inp0 =
Op.getOperand(0);
3769 if (Subtarget.isHVXElementType(ty(
Op)) &&
3770 Subtarget.isHVXElementType(ty(Inp0))) {
3771 Results.push_back(CreateTLWrapper(
Op, DAG));
3775 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3788 if (isHvxPairTy(ty(
Op))) {
3796 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3802 if (shouldWidenToHvx(ty(
Op.getOperand(1)), DAG)) {
3811 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3812 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3820 Results.push_back(LegalizeHvxResize(
Op, DAG));
3828HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3830 unsigned Opc =
N->getOpcode();
3833 if (
N->getNumOperands() > 0)
3834 Inp0 =
Op.getOperand(0);
3841 if (Subtarget.isHVXElementType(ty(
Op)) &&
3842 Subtarget.isHVXElementType(ty(Inp0))) {
3843 Results.push_back(CreateTLWrapper(
Op, DAG));
3847 if (shouldWidenToHvx(ty(
Op), DAG)) {
3853 if (shouldWidenToHvx(ty(
Op), DAG)) {
3862 if (isHvxBoolTy(ty(Inp0))) {
3868 assert(shouldWidenToHvx(ty(
N->getOperand(1)), DAG) &&
"Not widening?");
3874 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3875 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3883 Results.push_back(LegalizeHvxResize(
Op, DAG));
3891HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3892 DAGCombinerInfo &DCI)
const {
3897 SelectionDAG &DAG = DCI.DAG;
3898 const SDLoc &dl(
Op);
3900 if (
Op.getOperand(0).getOpcode() == ISD::BITCAST)
3905 EVT TruncTy =
Op.getValueType();
3907 EVT SrcTy = Src.getValueType();
3914 if (2 * CastLen != SrcLen)
3917 SmallVector<int, 128>
Mask(SrcLen);
3918 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3920 Mask[i + CastLen] = 2 * i + 1;
3924 return opSplit(Deal, dl, DAG).first;
3928HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3929 SDValue Op, DAGCombinerInfo &DCI)
const {
3937 SelectionDAG &DAG = DCI.DAG;
3938 const SDLoc &dl(
Op);
3947 SetVector<SDValue> Order;
3953 if (Order.
size() > 2)
3962 SmallVector<int, 128> LongMask;
3963 auto AppendToMask = [&](
SDValue Shuffle) {
3965 ArrayRef<int>
Mask = SV->getMask();
3968 for (
int M : Mask) {
3973 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3974 if (
static_cast<unsigned>(M) >= InpLen)
3977 int OutOffset = Order[0] == Src ? 0 : InpLen;
3994HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3997 SelectionDAG &DAG = DCI.DAG;
3999 unsigned Opc =
Op.getOpcode();
4004 return combineTruncateBeforeLegal(
Op, DCI);
4006 return combineConcatVectorsBeforeLegal(
Op, DCI);
4008 if (DCI.isBeforeLegalizeOps())
4034 return getZero(dl, ty(
Op), DAG);
4037 if (isUndef(
Ops[1]))
4055HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4056 if (Subtarget.isHVXVectorType(Ty,
true))
4058 auto Action = getPreferredHvxVectorAction(Ty);
4060 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4065HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
4066 if (Subtarget.isHVXVectorType(Ty,
true))
4068 auto Action = getPreferredHvxVectorAction(Ty);
4070 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
4076 if (!Subtarget.useHVXOps())
4080 auto IsHvxTy = [
this](EVT Ty) {
4081 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
4084 return Op.getValueType().isSimple() &&
4085 Subtarget.isHVXVectorType(ty(
Op),
true);
4091 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
4092 if (!
Op.getValueType().isSimple())
4095 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
4098 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
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")
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.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
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.