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) {
473 if (Subtarget.useHVXFloatingPoint()) {
496HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
503 unsigned HwLen = Subtarget.getVectorLength();
506 if (ElemTy == MVT::i1 && VecLen > HwLen)
512 if (ElemTy == MVT::i1) {
527 unsigned HwWidth = 8*HwLen;
528 if (VecWidth > 2*HwWidth)
534 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
543HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
544 unsigned Opc =
Op.getOpcode();
564HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
565 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
569 Tys.second.getVectorNumElements());
572HexagonTargetLowering::TypePair
573HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
576 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
578 return { HalfTy, HalfTy };
582HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
589HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
596HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
605HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
611HexagonTargetLowering::VectorPair
612HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
614 TypePair Tys = typeSplit(ty(Vec));
617 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
621HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
622 return Subtarget.isHVXVectorType(Ty) &&
627HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
628 return Subtarget.isHVXVectorType(Ty) &&
633HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
634 return Subtarget.isHVXVectorType(Ty,
true) &&
638bool HexagonTargetLowering::allowsHvxMemoryAccess(
646 if (!Subtarget.isHVXVectorType(VecTy,
false))
653bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
655 if (!Subtarget.isHVXVectorType(VecTy))
663void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
665 unsigned Opc =
MI.getOpcode();
666 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
667 MachineBasicBlock &MB = *
MI.getParent();
671 auto At =
MI.getIterator();
674 case Hexagon::PS_vsplatib:
675 if (Subtarget.useHVXV62Ops()) {
678 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
680 .
add(
MI.getOperand(1));
687 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
688 const MachineOperand &InpOp =
MI.getOperand(1);
690 uint32_t
V = InpOp.
getImm() & 0xFF;
692 .
addImm(V << 24 | V << 16 | V << 8 | V);
698 case Hexagon::PS_vsplatrb:
699 if (Subtarget.useHVXV62Ops()) {
703 .
add(
MI.getOperand(1));
705 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
706 const MachineOperand &InpOp =
MI.getOperand(1);
715 case Hexagon::PS_vsplatih:
716 if (Subtarget.useHVXV62Ops()) {
719 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
721 .
add(
MI.getOperand(1));
728 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
729 const MachineOperand &InpOp =
MI.getOperand(1);
731 uint32_t
V = InpOp.
getImm() & 0xFFFF;
739 case Hexagon::PS_vsplatrh:
740 if (Subtarget.useHVXV62Ops()) {
744 .
add(
MI.getOperand(1));
748 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
749 const MachineOperand &InpOp =
MI.getOperand(1);
758 case Hexagon::PS_vsplatiw:
759 case Hexagon::PS_vsplatrw:
760 if (
Opc == Hexagon::PS_vsplatiw) {
762 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
764 .
add(
MI.getOperand(1));
765 MI.getOperand(1).ChangeToRegister(SplatV,
false);
768 MI.setDesc(
TII.
get(Hexagon::V6_lvsplatw));
774HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
784 const SDLoc &dl(ElemIdx);
790HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
793 assert(ElemWidth >= 8 && ElemWidth <= 32);
797 if (ty(Idx) != MVT::i32)
799 const SDLoc &dl(Idx);
806HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
813 if (ElemTy == MVT::i8)
817 MVT ResTy = tyVector(OpTy, MVT::i8);
820 SmallVector<int,128> ByteMask;
823 for (
unsigned I = 0;
I != ElemSize; ++
I)
826 int NewM =
M*ElemSize;
827 for (
unsigned I = 0;
I != ElemSize; ++
I)
833 opCastElem(Op1, MVT::i8, DAG), ByteMask);
840 unsigned VecLen = Values.
size();
844 unsigned HwLen = Subtarget.getVectorLength();
846 unsigned ElemSize = ElemWidth / 8;
847 assert(ElemSize*VecLen == HwLen);
851 !(Subtarget.useHVXFloatingPoint() &&
853 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
854 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
856 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
857 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
865 unsigned NumValues = Values.size();
868 for (
unsigned i = 0; i != NumValues; ++i) {
869 if (Values[i].isUndef())
872 if (!SplatV.getNode())
874 else if (SplatV != Values[i])
882 unsigned NumWords = Words.
size();
884 bool IsSplat =
isSplat(Words, SplatV);
885 if (IsSplat && isUndef(SplatV))
890 return getZero(dl, VecTy, DAG);
899 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
902 (Constant**)Consts.end());
904 Align Alignment(HwLen);
918 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
919 SmallVectorImpl<int> &SrcIdx) {
923 SrcIdx.push_back(-1);
936 int I =
C->getSExtValue();
937 assert(
I >= 0 &&
"Negative element index");
944 SmallVector<int,128> ExtIdx;
946 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
947 MVT ExtTy = ty(ExtVec);
949 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
953 SmallVector<int,128>
Mask;
954 BitVector
Used(ExtLen);
956 for (
int M : ExtIdx) {
966 for (
unsigned I = 0;
I != ExtLen; ++
I) {
967 if (
Mask.size() == ExtLen)
975 return ExtLen == VecLen ? S : LoHalf(S, DAG);
983 assert(4*Words.
size() == Subtarget.getVectorLength());
986 for (
unsigned i = 0; i != NumWords; ++i) {
988 if (Words[i].isUndef())
990 for (
unsigned j = i;
j != NumWords; ++
j)
991 if (Words[i] == Words[j])
994 if (VecHist[i] > VecHist[n])
998 SDValue HalfV = getZero(dl, VecTy, DAG);
999 if (VecHist[n] > 1) {
1002 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
1014 for (
unsigned i = 0; i != NumWords/2; ++i) {
1016 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1020 {HalfV0, Words[i]});
1023 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1027 {HalfV1, Words[i+NumWords/2]});
1050HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1051 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1052 MVT PredTy = ty(PredV);
1053 unsigned HwLen = Subtarget.getVectorLength();
1056 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1066 SmallVector<int,128>
Mask(HwLen);
1071 for (
unsigned i = 0; i != HwLen; ++i) {
1072 unsigned Num = i % Scale;
1073 unsigned Off = i / Scale;
1082 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1084 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1091 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1100 if (Bytes < BitBytes) {
1106 while (Bytes < BitBytes) {
1108 Words[IdxW].
clear();
1111 for (
const SDValue &W : Words[IdxW ^ 1]) {
1112 SDValue T = expandPredicate(W, dl, DAG);
1117 for (
const SDValue &W : Words[IdxW ^ 1]) {
1125 while (Bytes > BitBytes) {
1127 Words[IdxW].
clear();
1130 for (
const SDValue &W : Words[IdxW ^ 1]) {
1131 SDValue T = contractPredicate(W, dl, DAG);
1135 for (
const SDValue &W : Words[IdxW ^ 1]) {
1142 assert(Bytes == BitBytes);
1143 if (BitBytes == 1 && PredTy == MVT::v2i1)
1146 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1148 for (
const SDValue &W : Words[IdxW]) {
1162 unsigned VecLen = Values.
size();
1163 unsigned HwLen = Subtarget.getVectorLength();
1164 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1166 bool AllT =
true, AllF =
true;
1170 return !
N->isZero();
1179 if (VecLen <= HwLen) {
1183 assert(HwLen % VecLen == 0);
1184 unsigned BitBytes = HwLen / VecLen;
1191 for (
unsigned B = 0;
B != BitBytes; ++
B)
1198 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1201 for (;
B != 8; ++
B) {
1202 if (!Values[
I+
B].isUndef())
1215 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1225 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1230HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1235 assert(ElemWidth >= 8 && ElemWidth <= 32);
1238 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1241 if (ElemTy == MVT::i32)
1247 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1250 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1254HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1257 assert(ResTy == MVT::i1);
1259 unsigned HwLen = Subtarget.getVectorLength();
1263 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1267 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1269 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1273HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1278 assert(ElemWidth >= 8 && ElemWidth <= 32);
1283 MVT VecTy = ty(VecV);
1284 unsigned HwLen = Subtarget.getVectorLength();
1296 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1297 if (ElemTy == MVT::i32)
1298 return InsertWord(VecV, ValV, ByteIdx);
1304 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1309 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1310 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1312 ValV, SubIdx, dl, ElemTy, DAG);
1315 return InsertWord(VecV, Ins, ByteIdx);
1319HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1321 unsigned HwLen = Subtarget.getVectorLength();
1325 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1330 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1335HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1337 MVT VecTy = ty(VecV);
1338 unsigned HwLen = Subtarget.getVectorLength();
1346 if (isHvxPairTy(VecTy)) {
1347 unsigned SubIdx = Hexagon::vsub_lo;
1348 if (Idx * ElemWidth >= 8 * HwLen) {
1349 SubIdx = Hexagon::vsub_hi;
1353 VecTy = typeSplit(VecTy).first;
1363 MVT WordTy = tyVector(VecTy, MVT::i32);
1365 unsigned WordIdx = (Idx*ElemWidth) / 32;
1368 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1373 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1374 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1379HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1381 MVT VecTy = ty(VecV);
1382 unsigned HwLen = Subtarget.getVectorLength();
1390 unsigned Offset = Idx * BitBytes;
1392 SmallVector<int,128>
Mask;
1394 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1401 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1402 for (
unsigned j = 0;
j != Rep; ++
j)
1419 unsigned Rep = 8 / ResLen;
1422 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1424 for (
unsigned i = 0; i != ResLen; ++i) {
1425 for (
unsigned j = 0;
j != Rep; ++
j)
1437 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1438 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1443HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1445 MVT VecTy = ty(VecV);
1446 MVT SubTy = ty(SubV);
1447 unsigned HwLen = Subtarget.getVectorLength();
1451 bool IsPair = isHvxPairTy(VecTy);
1459 V0 = LoHalf(VecV, DAG);
1460 V1 = HiHalf(VecV, DAG);
1465 if (isHvxSingleTy(SubTy)) {
1467 unsigned Idx = CN->getZExtValue();
1469 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1492 if (!IdxN || !IdxN->isZero()) {
1500 unsigned RolBase = HwLen;
1515 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1530HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1532 MVT VecTy = ty(VecV);
1533 MVT SubTy = ty(SubV);
1534 assert(Subtarget.isHVXVectorType(VecTy,
true));
1539 unsigned HwLen = Subtarget.getVectorLength();
1540 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1543 unsigned BitBytes = HwLen / VecLen;
1544 unsigned BlockLen = HwLen / Scale;
1548 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1552 if (!IdxN || !IdxN->isZero()) {
1561 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1563 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1565 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1567 if (!IdxN || !IdxN->isZero()) {
1576HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1581 assert(Subtarget.isHVXVectorType(ResTy));
1588 SDValue False = getZero(dl, ResTy, DAG);
1589 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1593HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1601 unsigned HwLen = Subtarget.getVectorLength();
1603 MVT PredTy = ty(VecQ);
1605 assert(HwLen % PredLen == 0);
1612 for (
unsigned i = 0; i != HwLen/8; ++i) {
1613 for (
unsigned j = 0;
j != 8; ++
j)
1614 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1617 Align Alignment(HwLen);
1626 getZero(dl, VecTy, DAG));
1632 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1634 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1641 SmallVector<int,128>
Mask;
1642 for (
unsigned i = 0; i != HwLen; ++i)
1643 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1653 MVT InpTy = ty(VecV);
1661 return InpWidth < ResWidth
1662 ? DAG.
getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1669 if (InpWidth < ResWidth) {
1671 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1679HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1683 const SDLoc &dl(Vec);
1692 const SDLoc &dl(
Op);
1697 for (
unsigned i = 0; i !=
Size; ++i)
1698 Ops.push_back(
Op.getOperand(i));
1701 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1709 for (
unsigned i = 0; i !=
Size; i++)
1720 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1722 MVT SingleTy = typeSplit(VecTy).first;
1723 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1724 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1728 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1734 const SDLoc &dl(
Op);
1736 MVT ArgTy = ty(
Op.getOperand(0));
1738 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1756 const SDLoc &dl(
Op);
1773 MVT NTy = typeLegalize(Ty, DAG);
1777 V.getOperand(0),
V.getOperand(1)),
1782 switch (
V.getOpcode()) {
1790 V =
V.getOperand(0);
1801 unsigned HwLen = Subtarget.getVectorLength();
1808 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1816 MVT HalfTy = typeSplit(VecTy).first;
1818 Ops.take_front(NumOp/2));
1820 Ops.take_back(NumOp/2));
1829 for (
SDValue V :
Op.getNode()->op_values()) {
1830 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1834 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1837 SDValue Res = getZero(dl, ByteTy, DAG);
1838 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1851 const SDLoc &dl(
Op);
1853 if (ElemTy == MVT::i1)
1854 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1856 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1862 const SDLoc &dl(
Op);
1868 if (ElemTy == MVT::i1)
1869 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1871 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1873 tyVector(VecTy, MVT::i16),
1874 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1876 return DAG.
getBitcast(tyVector(VecTy, ElemTy), T0);
1879 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1886 MVT SrcTy = ty(SrcV);
1892 const SDLoc &dl(
Op);
1895 if (ElemTy == MVT::i1)
1896 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1898 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1909 const SDLoc &dl(
Op);
1910 MVT VecTy = ty(VecV);
1912 if (ElemTy == MVT::i1)
1913 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1915 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1927 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1928 return LowerHvxSignExt(
Op, DAG);
1937 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1938 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1947 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1948 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1956 const SDLoc &dl(
Op);
1959 assert(ResTy == ty(InpV));
1984 const SDLoc &dl(
Op);
1991 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
1992 unsigned Opc =
Op.getOpcode();
2008 const SDLoc &dl(
Op);
2009 unsigned Opc =
Op.getOpcode();
2014 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
2026 if (Subtarget.useHVXV62Ops())
2027 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2032 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
2033 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2039 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2046 MVT ValTy = ty(Val);
2047 const SDLoc &dl(
Op);
2050 unsigned HwLen = Subtarget.getVectorLength();
2052 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2067 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
2069 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2074 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2075 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2088 auto bitcastI32ToV32I1 = [&](
SDValue Val32) {
2089 assert(Val32.getValueType().getSizeInBits() == 32 &&
2090 "Input must be 32 bits");
2094 for (
unsigned i = 0; i < 32; ++i)
2102 if (ResTy == MVT::v32i1 &&
2103 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2104 Subtarget.useHVX128BOps()) {
2106 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2107 Val32 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Val);
2108 return bitcastI32ToV32I1(Val32);
2111 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2129 unsigned HwLen = Subtarget.getVectorLength();
2141 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2145 for (
unsigned J = 0; J != 8; ++J) {
2153 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2177 const SDLoc &dl(
Op);
2178 unsigned HwLen = Subtarget.getVectorLength();
2180 assert(HwLen % VecLen == 0);
2181 unsigned ElemSize = HwLen / VecLen;
2193 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2199HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2201 unsigned Opc =
Op.getOpcode();
2213 const SDLoc &dl(
Op);
2219 bool UseShifts = ElemTy != MVT::i8;
2220 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2223 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2231 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2247 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2256 const SDLoc &dl(
Op);
2257 unsigned IntNo =
Op.getConstantOperandVal(0);
2265 case Intrinsic::hexagon_V6_pred_typecast:
2266 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2267 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2268 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2275 case Intrinsic::hexagon_V6_vmpyss_parts:
2276 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2279 case Intrinsic::hexagon_V6_vmpyuu_parts:
2280 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2283 case Intrinsic::hexagon_V6_vmpyus_parts:
2284 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2295 const SDLoc &dl(
Op);
2296 unsigned HwLen = Subtarget.getVectorLength();
2300 SDValue Chain = MaskN->getChain();
2304 unsigned Opc =
Op->getOpcode();
2307 if (
Opc == ISD::MLOAD) {
2321 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2325 if (MaskN->getAlign().value() % HwLen == 0) {
2334 SDValue Z = getZero(dl, ty(V), DAG);
2338 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2339 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2340 return std::make_pair(LoV, HiV);
2346 VectorPair Tmp = StoreAlign(MaskV,
Base);
2349 VectorPair ValueU = StoreAlign(
Value,
Base);
2353 getInstr(StoreOpc, dl, MVT::Other,
2354 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2356 getInstr(StoreOpc, dl, MVT::Other,
2357 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2367 assert(Subtarget.useHVXQFloatOps());
2369 assert(
Op->getOpcode() == ISD::FP_EXTEND);
2372 MVT ArgTy = ty(
Op.getOperand(0));
2373 const SDLoc &dl(
Op);
2375 if (ArgTy == MVT::v64bf16) {
2376 MVT HalfTy = typeSplit(VecTy).first;
2379 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2384 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2385 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2387 {VecPair.second, VecPair.first,
2393 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2402 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2404 MVT HalfTy = typeSplit(VecTy).first;
2405 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2407 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2409 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2412 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2425 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2428 if (Subtarget.useHVXIEEEFPOps()) {
2430 if (FpTy == MVT::f16) {
2432 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2434 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2440 return EqualizeFpIntConversion(
Op, DAG);
2442 return ExpandHvxFpToInt(
Op, DAG);
2458 MVT ResTy = ty(PredOp);
2459 const SDLoc &dl(PredOp);
2462 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2463 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2465 SDNode *PredTransfer =
2468 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2471 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2476 SDNode *IndexShift =
2482 SDNode *Convert = DAG.
getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2507 MVT ResTy = ty(PredOp);
2508 const SDLoc &dl(PredOp);
2518 SDNode *RegConst = DAG.
getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2519 SDNode *SplatConst = DAG.
getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2524 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, HiReg));
2527 DAG.
getNode(ISD::BITCAST, dl, MVT::i32, LoReg));
2529 SDNode *PredTransfer =
2533 SDNode *PrefixSum = DAG.
getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2540 SDNode *IndexShift_hi =
2543 SDNode *IndexShift_lo =
2547 SDNode *MaskOff_hi =
2550 SDNode *MaskOff_lo =
2573 if (ResTy == MVT::v32f32 && ty(
Op.getOperand(0)) == MVT::v32i1)
2574 return LowerHvxPred32ToFp(
Op, DAG);
2575 if (ResTy == MVT::v64f16 && ty(
Op.getOperand(0)) == MVT::v64i1)
2576 return LowerHvxPred64ToFp(
Op, DAG);
2579 if (Subtarget.useHVXIEEEFPOps()) {
2581 if (FpTy == MVT::f16) {
2583 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2585 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2591 return EqualizeFpIntConversion(
Op, DAG);
2593 return ExpandHvxIntToFp(
Op, DAG);
2596HexagonTargetLowering::TypePair
2597HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2608 unsigned MaxWidth = std::max(Width0, Width1);
2610 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2617 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2618 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2622 return {WideETy0, WideETy1};
2633HexagonTargetLowering::TypePair
2634HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2644 unsigned MaxLen = std::max(Len0, Len1);
2657HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2658 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2667HexagonTargetLowering::VectorPair
2698HexagonTargetLowering::VectorPair
2699HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2704 const SDLoc &dl(Val);
2705 MVT ValTy = ty(Val);
2719 MVT IntTy = tyVector(ValTy, ElemTy);
2731 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2750 MVT
PairTy = typeJoin({VecTy, VecTy});
2776 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2778 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2786 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2788 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2791 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2792 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2793 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2804HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2805 bool SignedB,
const SDLoc &dl,
2808 MVT
PairTy = typeJoin({VecTy, VecTy});
2813 if (SignedA && !SignedB) {
2829 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2830 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2831 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2840 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2843 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2847 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2848 {HiHalf(P2, DAG), T3,
S16}, DAG);
2851 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2852 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2856 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2863 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2864 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2865 }
else if (SignedB) {
2871 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2873 assert(!SignedA && !SignedB);
2880HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2885 MVT
PairTy = typeJoin({VecTy, VecTy});
2888 if (SignedA && !SignedB) {
2897 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2902 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2914 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2915 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2916 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2917 }
else if (!SignedA) {
2927 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2945 unsigned Opc =
Op.getOpcode();
2950 MVT InpTy = ty(Inp);
2956 const SDLoc &dl(
Op);
2959 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2968 unsigned Opc =
Op.getOpcode();
2971 const SDLoc &dl(
Op);
2973 MVT InpTy = ty(Op0);
2986 if (InpTy == MVT::v64f16) {
2987 if (Subtarget.useHVXV81Ops()) {
2990 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
2994 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
2999 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3079 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3080 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3123 unsigned Opc =
Op.getOpcode();
3126 const SDLoc &dl(
Op);
3128 MVT InpTy = ty(Op0);
3161 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3171 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
3194 unsigned Opc =
Op.getOpcode();
3211 const SDLoc &dl(
Op);
3212 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
3221 unsigned Opc =
Op.getConstantOperandVal(2);
3225HexagonTargetLowering::VectorPair
3229 const SDLoc &dl(
Op);
3231 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
3232 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
3234 return std::make_pair(TV, TV);
3239 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
3241 switch (
Op.getOpcode()) {
3242 case ISD::SIGN_EXTEND_INREG:
3243 case HexagonISD::SSAT:
3244 case HexagonISD::USAT:
3245 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3246 std::tie(Lo, Hi) = SplitVTNode(N);
3254 MVT HalfTy = typeSplit(ResTy).first;
3264 if (!MemN->getMemoryVT().isSimple())
3267 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3268 if (!isHvxPairTy(MemTy))
3271 const SDLoc &dl(
Op);
3272 unsigned HwLen = Subtarget.getVectorLength();
3273 MVT SingleTy = typeSplit(MemTy).first;
3274 SDValue Chain = MemN->getChain();
3275 SDValue Base0 = MemN->getBasePtr();
3280 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3281 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3283 uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3290 if (MemOpc == ISD::LOAD) {
3299 if (MemOpc == ISD::STORE) {
3307 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3310 assert(MaskN->isUnindexed());
3311 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3314 if (MemOpc == ISD::MLOAD) {
3330 if (MemOpc == ISD::MSTORE) {
3333 Masks.first, SingleTy, MOp0,
3336 Masks.second, SingleTy, MOp1,
3341 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3347 const SDLoc &dl(
Op);
3349 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3350 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3351 "Not widening loads of i1 yet");
3353 SDValue Chain = LoadN->getChain();
3358 unsigned HwLen = Subtarget.getVectorLength();
3360 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3363 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3371 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3379 const SDLoc &dl(
Op);
3381 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3382 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3383 "Not widening stores of i1 yet");
3385 SDValue Chain = StoreN->getChain();
3389 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3390 MVT ValueTy = ty(
Value);
3392 unsigned HwLen = Subtarget.getVectorLength();
3395 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3397 Len = ty(
Value).getVectorNumElements();
3399 assert(ty(
Value).getVectorNumElements() == HwLen);
3401 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3403 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3406 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3413 const SDLoc &dl(
Op);
3414 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3416 unsigned HwLen = Subtarget.getVectorLength();
3421 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3424 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3425 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3429 {WideOp0, WideOp1,
Op.getOperand(2)});
3431 EVT RetTy = typeLegalize(ty(
Op), DAG);
3433 {SetCC, getZero(dl, MVT::i32, DAG)});
3438 unsigned Opc =
Op.getOpcode();
3439 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3441 return isHvxPairTy(ty(V));
3452 return SplitHvxMemOp(
Op, DAG);
3457 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3458 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3468 case ISD::FMINIMUMNUM:
3469 case ISD::FMAXIMUMNUM:
3488 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3493 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3494 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3509 case ISD::BITCAST:
return LowerHvxBitcast(
Op, DAG);
3517 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3519 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3529 case ISD::MSTORE:
return LowerHvxMaskedOp(
Op, DAG);
3531 case ISD::LOAD:
return SDValue();
3532 case ISD::FP_EXTEND:
return LowerHvxFpExtend(
Op, DAG);
3558 unsigned Opc =
Op.getOpcode();
3578 MVT InpTy = ty(Inp);
3583 assert(InpWidth != ResWidth);
3585 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3588 const SDLoc &dl(
Op);
3592 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3600 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3607 if (InpWidth < ResWidth) {
3609 while (InpWidth * 2 <= ResWidth)
3610 S = repeatOp(InpWidth *= 2, S);
3614 while (InpWidth / 2 >= ResWidth)
3615 S = repeatOp(InpWidth /= 2, S);
3623 MVT InpTy = ty(Inp0);
3627 unsigned Opc =
Op.getOpcode();
3629 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3634 auto [WInpTy, WResTy] =
3635 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3636 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3637 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3645 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3646 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3647 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3648 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3651 return RemoveTLWrapper(
Op, DAG);
3657HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3659 unsigned Opc =
N->getOpcode();
3662 if (
N->getNumOperands() > 0)
3663 Inp0 =
Op.getOperand(0);
3670 if (Subtarget.isHVXElementType(ty(
Op)) &&
3671 Subtarget.isHVXElementType(ty(Inp0))) {
3672 Results.push_back(CreateTLWrapper(
Op, DAG));
3676 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3689 if (isHvxPairTy(ty(
Op))) {
3697 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3706 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3707 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3715 Results.push_back(LegalizeHvxResize(
Op, DAG));
3723HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3725 unsigned Opc =
N->getOpcode();
3728 if (
N->getNumOperands() > 0)
3729 Inp0 =
Op.getOperand(0);
3736 if (Subtarget.isHVXElementType(ty(
Op)) &&
3737 Subtarget.isHVXElementType(ty(Inp0))) {
3738 Results.push_back(CreateTLWrapper(
Op, DAG));
3742 if (shouldWidenToHvx(ty(
Op), DAG)) {
3748 if (shouldWidenToHvx(ty(
Op), DAG)) {
3757 if (isHvxBoolTy(ty(Inp0))) {
3764 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3765 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3773 Results.push_back(LegalizeHvxResize(
Op, DAG));
3781HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3782 DAGCombinerInfo &DCI)
const {
3787 SelectionDAG &DAG = DCI.DAG;
3788 const SDLoc &dl(
Op);
3790 if (
Op.getOperand(0).getOpcode() == ISD::BITCAST)
3795 EVT TruncTy =
Op.getValueType();
3797 EVT SrcTy = Src.getValueType();
3804 if (2 * CastLen != SrcLen)
3807 SmallVector<int, 128>
Mask(SrcLen);
3808 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3810 Mask[i + CastLen] = 2 * i + 1;
3814 return opSplit(Deal, dl, DAG).first;
3818HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3819 SDValue Op, DAGCombinerInfo &DCI)
const {
3827 SelectionDAG &DAG = DCI.DAG;
3828 const SDLoc &dl(
Op);
3837 SetVector<SDValue> Order;
3843 if (Order.
size() > 2)
3852 SmallVector<int, 128> LongMask;
3853 auto AppendToMask = [&](
SDValue Shuffle) {
3855 ArrayRef<int>
Mask = SV->getMask();
3858 for (
int M : Mask) {
3863 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3864 if (
static_cast<unsigned>(M) >= InpLen)
3867 int OutOffset = Order[0] == Src ? 0 : InpLen;
3884HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3887 SelectionDAG &DAG = DCI.DAG;
3889 unsigned Opc =
Op.getOpcode();
3894 return combineTruncateBeforeLegal(
Op, DCI);
3896 return combineConcatVectorsBeforeLegal(
Op, DCI);
3898 if (DCI.isBeforeLegalizeOps())
3924 return getZero(dl, ty(
Op), DAG);
3927 if (isUndef(
Ops[1]))
3945HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3946 if (Subtarget.isHVXVectorType(Ty,
true))
3948 auto Action = getPreferredHvxVectorAction(Ty);
3950 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3955HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3956 if (Subtarget.isHVXVectorType(Ty,
true))
3958 auto Action = getPreferredHvxVectorAction(Ty);
3960 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3966 if (!Subtarget.useHVXOps())
3970 auto IsHvxTy = [
this](EVT Ty) {
3971 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
3974 return Op.getValueType().isSimple() &&
3975 Subtarget.isHVXVectorType(ty(
Op),
true);
3981 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3982 if (!
Op.getValueType().isSimple())
3985 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3988 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.