21#include "llvm/IR/IntrinsicsHexagon.h"
32 cl::desc(
"Lower threshold (in bytes) for widening to HVX vectors"));
34static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
35static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
36static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
37static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
42 switch (ElemTy.SimpleTy) {
44 return std::make_tuple(5, 15, 10);
46 return std::make_tuple(8, 127, 23);
48 return std::make_tuple(11, 1023, 52);
56HexagonTargetLowering::initializeHVXLowering() {
57 if (Subtarget.useHVX64BOps()) {
75 }
else if (Subtarget.useHVX128BOps()) {
85 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
95 bool Use64b = Subtarget.useHVX64BOps();
98 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
99 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
100 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
102 auto setPromoteTo = [
this] (
unsigned Opc, MVT FromTy, MVT ToTy) {
120 if (Subtarget.useHVX128BOps())
122 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
123 Subtarget.useHVXFloatingPoint()) {
125 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
126 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
128 for (MVT
T : FloatV) {
163 for (MVT
P : FloatW) {
185 if (Subtarget.useHVXQFloatOps()) {
188 }
else if (Subtarget.useHVXIEEEFPOps()) {
194 for (MVT
T : LegalV) {
219 if (
T.getScalarType() != MVT::i32) {
228 if (
T.getScalarType() != MVT::i32) {
256 if (Subtarget.useHVXFloatingPoint()) {
273 for (MVT
T : LegalW) {
326 if (
T.getScalarType() != MVT::i32) {
331 if (Subtarget.useHVXFloatingPoint()) {
374 for (MVT
T : LegalW) {
391 for (MVT
T : LegalV) {
406 for (MVT
T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
409 for (MVT
T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
414 unsigned HwLen = Subtarget.getVectorLength();
415 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
416 if (ElemTy == MVT::i1)
418 int ElemWidth = ElemTy.getFixedSizeInBits();
419 int MaxElems = (8*HwLen) / ElemWidth;
420 for (
int N = 2;
N < MaxElems;
N *= 2) {
431 if (Subtarget.useHVXFloatingPoint()) {
449HexagonTargetLowering::getPreferredHvxVectorAction(
MVT VecTy)
const {
452 unsigned HwLen = Subtarget.getVectorLength();
455 if (ElemTy == MVT::i1 && VecLen > HwLen)
461 if (ElemTy == MVT::i1) {
476 unsigned HwWidth = 8*HwLen;
477 if (VecWidth > 2*HwWidth)
483 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
492HexagonTargetLowering::getCustomHvxOperationAction(
SDNode &
Op)
const {
493 unsigned Opc =
Op.getOpcode();
513HexagonTargetLowering::typeJoin(
const TypePair &Tys)
const {
514 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
518 Tys.second.getVectorNumElements());
521HexagonTargetLowering::TypePair
522HexagonTargetLowering::typeSplit(
MVT VecTy)
const {
525 assert((NumElem % 2) == 0 &&
"Expecting even-sized vector type");
527 return { HalfTy, HalfTy };
531HexagonTargetLowering::typeExtElem(
MVT VecTy,
unsigned Factor)
const {
538HexagonTargetLowering::typeTruncElem(
MVT VecTy,
unsigned Factor)
const {
545HexagonTargetLowering::opCastElem(
SDValue Vec,
MVT ElemTy,
554HexagonTargetLowering::opJoin(
const VectorPair &
Ops,
const SDLoc &dl,
560HexagonTargetLowering::VectorPair
561HexagonTargetLowering::opSplit(
SDValue Vec,
const SDLoc &dl,
563 TypePair Tys = typeSplit(ty(Vec));
566 return DAG.
SplitVector(Vec, dl, Tys.first, Tys.second);
570HexagonTargetLowering::isHvxSingleTy(
MVT Ty)
const {
571 return Subtarget.isHVXVectorType(Ty) &&
576HexagonTargetLowering::isHvxPairTy(
MVT Ty)
const {
577 return Subtarget.isHVXVectorType(Ty) &&
582HexagonTargetLowering::isHvxBoolTy(
MVT Ty)
const {
583 return Subtarget.isHVXVectorType(Ty,
true) &&
587bool HexagonTargetLowering::allowsHvxMemoryAccess(
595 if (!Subtarget.isHVXVectorType(VecTy,
false))
602bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
604 if (!Subtarget.isHVXVectorType(VecTy))
612void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
614 unsigned Opc =
MI.getOpcode();
615 const TargetInstrInfo &
TII = *Subtarget.getInstrInfo();
616 MachineBasicBlock &MB = *
MI.getParent();
620 auto At =
MI.getIterator();
623 case Hexagon::PS_vsplatib:
624 if (Subtarget.useHVXV62Ops()) {
627 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
629 .
add(
MI.getOperand(1));
631 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
636 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
637 const MachineOperand &InpOp =
MI.getOperand(1);
639 uint32_t
V = InpOp.
getImm() & 0xFF;
641 .
addImm(V << 24 | V << 16 | V << 8 | V);
647 case Hexagon::PS_vsplatrb:
648 if (Subtarget.useHVXV62Ops()) {
651 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatb), OutV)
652 .
add(
MI.getOperand(1));
654 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
655 const MachineOperand &InpOp =
MI.getOperand(1);
656 BuildMI(MB, At,
DL,
TII.get(Hexagon::S2_vsplatrb), SplatV)
659 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplatw), OutV)
664 case Hexagon::PS_vsplatih:
665 if (Subtarget.useHVXV62Ops()) {
668 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
670 .
add(
MI.getOperand(1));
672 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
677 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
678 const MachineOperand &InpOp =
MI.getOperand(1);
680 uint32_t
V = InpOp.
getImm() & 0xFFFF;
688 case Hexagon::PS_vsplatrh:
689 if (Subtarget.useHVXV62Ops()) {
692 BuildMI(MB, At,
DL,
TII.get(Hexagon::V6_lvsplath), OutV)
693 .
add(
MI.getOperand(1));
697 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
698 const MachineOperand &InpOp =
MI.getOperand(1);
699 BuildMI(MB, At,
DL,
TII.get(Hexagon::A2_combine_ll), SplatV)
707 case Hexagon::PS_vsplatiw:
708 case Hexagon::PS_vsplatrw:
709 if (
Opc == Hexagon::PS_vsplatiw) {
711 Register SplatV =
MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
713 .
add(
MI.getOperand(1));
714 MI.getOperand(1).ChangeToRegister(SplatV,
false);
717 MI.setDesc(
TII.get(Hexagon::V6_lvsplatw));
723HexagonTargetLowering::convertToByteIndex(
SDValue ElemIdx,
MVT ElemTy,
733 const SDLoc &dl(ElemIdx);
739HexagonTargetLowering::getIndexInWord32(
SDValue Idx,
MVT ElemTy,
742 assert(ElemWidth >= 8 && ElemWidth <= 32);
746 if (ty(Idx) != MVT::i32)
748 const SDLoc &dl(Idx);
755HexagonTargetLowering::getByteShuffle(
const SDLoc &dl,
SDValue Op0,
762 if (ElemTy == MVT::i8)
766 MVT ResTy = tyVector(OpTy, MVT::i8);
769 SmallVector<int,128> ByteMask;
772 for (
unsigned I = 0;
I != ElemSize; ++
I)
775 int NewM =
M*ElemSize;
776 for (
unsigned I = 0;
I != ElemSize; ++
I)
782 opCastElem(Op1, MVT::i8, DAG), ByteMask);
789 unsigned VecLen = Values.
size();
793 unsigned HwLen = Subtarget.getVectorLength();
795 unsigned ElemSize = ElemWidth / 8;
796 assert(ElemSize*VecLen == HwLen);
800 !(Subtarget.useHVXFloatingPoint() &&
802 assert((ElemSize == 1 || ElemSize == 2) &&
"Invalid element size");
803 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
805 for (
unsigned i = 0; i != VecLen; i += OpsPerWord) {
806 SDValue W = buildVector32(Values.
slice(i, OpsPerWord), dl, PartVT, DAG);
814 unsigned NumValues = Values.size();
817 for (
unsigned i = 0; i != NumValues; ++i) {
818 if (Values[i].isUndef())
821 if (!SplatV.getNode())
823 else if (SplatV != Values[i])
831 unsigned NumWords = Words.
size();
833 bool IsSplat =
isSplat(Words, SplatV);
834 if (IsSplat && isUndef(SplatV))
839 return getZero(dl, VecTy, DAG);
848 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
851 (Constant**)Consts.end());
853 Align Alignment(HwLen);
867 auto IsBuildFromExtracts = [
this,&Values] (
SDValue &SrcVec,
868 SmallVectorImpl<int> &SrcIdx) {
872 SrcIdx.push_back(-1);
885 int I =
C->getSExtValue();
886 assert(
I >= 0 &&
"Negative element index");
893 SmallVector<int,128> ExtIdx;
895 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
896 MVT ExtTy = ty(ExtVec);
898 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
902 SmallVector<int,128>
Mask;
903 BitVector
Used(ExtLen);
905 for (
int M : ExtIdx) {
915 for (
unsigned I = 0;
I != ExtLen; ++
I) {
916 if (
Mask.size() == ExtLen)
924 return ExtLen == VecLen ? S : LoHalf(S, DAG);
932 assert(4*Words.
size() == Subtarget.getVectorLength());
935 for (
unsigned i = 0; i != NumWords; ++i) {
937 if (Words[i].isUndef())
939 for (
unsigned j = i;
j != NumWords; ++
j)
940 if (Words[i] == Words[j])
943 if (VecHist[i] > VecHist[n])
947 SDValue HalfV = getZero(dl, VecTy, DAG);
948 if (VecHist[n] > 1) {
951 {HalfV, SplatV, DAG.
getConstant(HwLen/2, dl, MVT::i32)});
963 for (
unsigned i = 0; i != NumWords/2; ++i) {
965 if (Words[i] != Words[n] || VecHist[n] <= 1) {
972 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
976 {HalfV1, Words[i+NumWords/2]});
999HexagonTargetLowering::createHvxPrefixPred(
SDValue PredV,
const SDLoc &dl,
1000 unsigned BitBytes,
bool ZeroFill,
SelectionDAG &DAG)
const {
1001 MVT PredTy = ty(PredV);
1002 unsigned HwLen = Subtarget.getVectorLength();
1005 if (Subtarget.isHVXVectorType(PredTy,
true)) {
1015 SmallVector<int,128>
Mask(HwLen);
1020 for (
unsigned i = 0; i != HwLen; ++i) {
1021 unsigned Num = i % Scale;
1022 unsigned Off = i / Scale;
1031 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1033 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1040 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1052 while (Bytes < BitBytes) {
1054 Words[IdxW].
clear();
1057 for (
const SDValue &W : Words[IdxW ^ 1]) {
1058 SDValue T = expandPredicate(W, dl, DAG);
1063 for (
const SDValue &W : Words[IdxW ^ 1]) {
1071 assert(Bytes == BitBytes);
1073 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1075 for (
const SDValue &W : Words[IdxW]) {
1089 unsigned VecLen = Values.
size();
1090 unsigned HwLen = Subtarget.getVectorLength();
1091 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1093 bool AllT =
true, AllF =
true;
1097 return !
N->isZero();
1106 if (VecLen <= HwLen) {
1110 assert(HwLen % VecLen == 0);
1111 unsigned BitBytes = HwLen / VecLen;
1118 for (
unsigned B = 0;
B != BitBytes; ++
B)
1125 for (
unsigned I = 0;
I != VecLen;
I += 8) {
1128 for (;
B != 8; ++
B) {
1129 if (!Values[
I+
B].isUndef())
1142 assert(Values[
I+
B].isUndef() || Values[
I+
B] ==
F);
1152 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1157HexagonTargetLowering::extractHvxElementReg(
SDValue VecV,
SDValue IdxV,
1162 assert(ElemWidth >= 8 && ElemWidth <= 32);
1165 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1168 if (ElemTy == MVT::i32)
1174 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1177 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1181HexagonTargetLowering::extractHvxElementPred(
SDValue VecV,
SDValue IdxV,
1184 assert(ResTy == MVT::i1);
1186 unsigned HwLen = Subtarget.getVectorLength();
1190 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1194 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1196 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB,
Zero}, DAG);
1200HexagonTargetLowering::insertHvxElementReg(
SDValue VecV,
SDValue IdxV,
1205 assert(ElemWidth >= 8 && ElemWidth <= 32);
1210 MVT VecTy = ty(VecV);
1211 unsigned HwLen = Subtarget.getVectorLength();
1223 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1224 if (ElemTy == MVT::i32)
1225 return InsertWord(VecV, ValV, ByteIdx);
1231 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1236 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1237 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1239 ValV, SubIdx, dl, ElemTy, DAG);
1242 return InsertWord(VecV, Ins, ByteIdx);
1246HexagonTargetLowering::insertHvxElementPred(
SDValue VecV,
SDValue IdxV,
1248 unsigned HwLen = Subtarget.getVectorLength();
1252 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1257 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1262HexagonTargetLowering::extractHvxSubvectorReg(
SDValue OrigOp,
SDValue VecV,
1264 MVT VecTy = ty(VecV);
1265 unsigned HwLen = Subtarget.getVectorLength();
1273 if (isHvxPairTy(VecTy)) {
1274 unsigned SubIdx = Hexagon::vsub_lo;
1275 if (Idx * ElemWidth >= 8 * HwLen) {
1276 SubIdx = Hexagon::vsub_hi;
1280 VecTy = typeSplit(VecTy).first;
1290 MVT WordTy = tyVector(VecTy, MVT::i32);
1292 unsigned WordIdx = (Idx*ElemWidth) / 32;
1295 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1300 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1301 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1306HexagonTargetLowering::extractHvxSubvectorPred(
SDValue VecV,
SDValue IdxV,
1308 MVT VecTy = ty(VecV);
1309 unsigned HwLen = Subtarget.getVectorLength();
1317 unsigned Offset = Idx * BitBytes;
1319 SmallVector<int,128>
Mask;
1321 if (Subtarget.isHVXVectorType(ResTy,
true)) {
1328 for (
unsigned i = 0; i != HwLen/Rep; ++i) {
1329 for (
unsigned j = 0;
j != Rep; ++
j)
1346 unsigned Rep = 8 / ResLen;
1349 for (
unsigned r = 0; r != HwLen/ResLen; ++r) {
1351 for (
unsigned i = 0; i != ResLen; ++i) {
1352 for (
unsigned j = 0;
j != Rep; ++
j)
1364 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1365 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1370HexagonTargetLowering::insertHvxSubvectorReg(
SDValue VecV,
SDValue SubV,
1372 MVT VecTy = ty(VecV);
1373 MVT SubTy = ty(SubV);
1374 unsigned HwLen = Subtarget.getVectorLength();
1378 bool IsPair = isHvxPairTy(VecTy);
1386 V0 = LoHalf(VecV, DAG);
1387 V1 = HiHalf(VecV, DAG);
1392 if (isHvxSingleTy(SubTy)) {
1394 unsigned Idx = CN->getZExtValue();
1396 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1419 if (!IdxN || !IdxN->isZero()) {
1427 unsigned RolBase = HwLen;
1442 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1457HexagonTargetLowering::insertHvxSubvectorPred(
SDValue VecV,
SDValue SubV,
1459 MVT VecTy = ty(VecV);
1460 MVT SubTy = ty(SubV);
1461 assert(Subtarget.isHVXVectorType(VecTy,
true));
1466 unsigned HwLen = Subtarget.getVectorLength();
1467 assert(HwLen % VecLen == 0 &&
"Unexpected vector type");
1470 unsigned BitBytes = HwLen / VecLen;
1471 unsigned BlockLen = HwLen / Scale;
1475 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes,
false, DAG);
1479 if (!IdxN || !IdxN->isZero()) {
1488 assert(BlockLen < HwLen &&
"vsetq(v1) prerequisite");
1490 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1492 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1494 if (!IdxN || !IdxN->isZero()) {
1503HexagonTargetLowering::extendHvxVectorPred(
SDValue VecV,
const SDLoc &dl,
1508 assert(Subtarget.isHVXVectorType(ResTy));
1515 SDValue False = getZero(dl, ResTy, DAG);
1516 return DAG.
getSelect(dl, ResTy, VecV, True, False);
1520HexagonTargetLowering::compressHvxPred(
SDValue VecQ,
const SDLoc &dl,
1528 unsigned HwLen = Subtarget.getVectorLength();
1530 MVT PredTy = ty(VecQ);
1532 assert(HwLen % PredLen == 0);
1539 for (
unsigned i = 0; i != HwLen/8; ++i) {
1540 for (
unsigned j = 0;
j != 8; ++
j)
1541 Tmp.
push_back(ConstantInt::get(Int8Ty, 1ull << j));
1544 Align Alignment(HwLen);
1553 getZero(dl, VecTy, DAG));
1559 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1561 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1568 SmallVector<int,128>
Mask;
1569 for (
unsigned i = 0; i != HwLen; ++i)
1570 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1580 MVT InpTy = ty(VecV);
1588 return InpWidth < ResWidth
1589 ? DAG.
getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1596 if (InpWidth < ResWidth) {
1598 return DAG.
getNode(ExtOpc, dl, ResTy, VecV);
1606HexagonTargetLowering::extractSubvector(
SDValue Vec,
MVT SubTy,
unsigned SubIdx,
1610 const SDLoc &dl(Vec);
1619 const SDLoc &dl(
Op);
1624 for (
unsigned i = 0; i !=
Size; ++i)
1625 Ops.push_back(
Op.getOperand(i));
1628 return buildHvxVectorPred(
Ops, dl, VecTy, DAG);
1635 for (
unsigned i = 0; i !=
Size; i++)
1639 tyVector(VecTy, MVT::i16), NewOps);
1640 return DAG.
getBitcast(tyVector(VecTy, MVT::f16), T0);
1646 if (VecTy.
getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1648 MVT SingleTy = typeSplit(VecTy).first;
1649 SDValue V0 = buildHvxVectorReg(
A.take_front(
Size / 2), dl, SingleTy, DAG);
1650 SDValue V1 = buildHvxVectorReg(
A.drop_front(
Size / 2), dl, SingleTy, DAG);
1654 return buildHvxVectorReg(
Ops, dl, VecTy, DAG);
1660 const SDLoc &dl(
Op);
1662 MVT ArgTy = ty(
Op.getOperand(0));
1664 if (ArgTy == MVT::f16) {
1682 const SDLoc &dl(
Op);
1699 MVT NTy = typeLegalize(Ty, DAG);
1703 V.getOperand(0),
V.getOperand(1)),
1708 switch (
V.getOpcode()) {
1716 V =
V.getOperand(0);
1727 unsigned HwLen = Subtarget.getVectorLength();
1734 if (Subtarget.isHVXVectorType(ty(Op0),
true)) {
1742 MVT HalfTy = typeSplit(VecTy).first;
1744 Ops.take_front(NumOp/2));
1746 Ops.take_back(NumOp/2));
1755 for (
SDValue V :
Op.getNode()->op_values()) {
1756 SDValue P = createHvxPrefixPred(V, dl, BitBytes,
true, DAG);
1760 unsigned InpLen = ty(
Op.getOperand(0)).getVectorNumElements();
1763 SDValue Res = getZero(dl, ByteTy, DAG);
1764 for (
unsigned i = 0, e = Prefixes.
size(); i != e; ++i) {
1777 const SDLoc &dl(
Op);
1779 if (ElemTy == MVT::i1)
1780 return extractHvxElementPred(VecV, IdxV, dl, ty(
Op), DAG);
1782 return extractHvxElementReg(VecV, IdxV, dl, ty(
Op), DAG);
1788 const SDLoc &dl(
Op);
1794 if (ElemTy == MVT::i1)
1795 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1797 if (ElemTy == MVT::f16) {
1799 tyVector(VecTy, MVT::i16),
1800 DAG.
getBitcast(tyVector(VecTy, MVT::i16), VecV),
1802 return DAG.
getBitcast(tyVector(VecTy, MVT::f16), T0);
1805 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1812 MVT SrcTy = ty(SrcV);
1818 const SDLoc &dl(
Op);
1821 if (ElemTy == MVT::i1)
1822 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1824 return extractHvxSubvectorReg(
Op, SrcV, IdxV, dl, DstTy, DAG);
1835 const SDLoc &dl(
Op);
1836 MVT VecTy = ty(VecV);
1838 if (ElemTy == MVT::i1)
1839 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
1841 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
1853 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1854 return LowerHvxSignExt(
Op, DAG);
1863 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1864 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
false, DAG);
1873 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
1874 return extendHvxVectorPred(InpV, SDLoc(
Op), ty(
Op),
true, DAG);
1882 const SDLoc &dl(
Op);
1885 assert(ResTy == ty(InpV));
1910 const SDLoc &dl(
Op);
1917 SDVTList ResTys = DAG.
getVTList(ResTy, ResTy);
1918 unsigned Opc =
Op.getOpcode();
1934 const SDLoc &dl(
Op);
1935 unsigned Opc =
Op.getOpcode();
1940 if (
auto HiVal =
Op.getValue(1); HiVal.use_empty()) {
1952 if (Subtarget.useHVXV62Ops())
1953 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1958 if (
auto LoVal =
Op.getValue(0); LoVal.use_empty()) {
1959 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
1965 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
1972 MVT ValTy = ty(Val);
1973 const SDLoc &dl(
Op);
1976 unsigned HwLen = Subtarget.getVectorLength();
1978 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
1993 for (
unsigned i = 0; i !=
BitWidth/32; ++i) {
1995 VQ, DAG.
getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2000 for (
unsigned i = 0, e = Words.
size(); i < e; i += 2) {
2001 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2014 if (ResTy == MVT::v32i1 &&
2015 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2016 Subtarget.useHVX128BOps()) {
2018 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2019 Val32 = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Val);
2024 for (
unsigned i = 0; i < 32; ++i)
2035 unsigned HwLen = Subtarget.getVectorLength();
2047 for (
unsigned I = 0;
I != HwLen / 8; ++
I) {
2051 for (
unsigned J = 0; J != 8; ++J) {
2059 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2083 const SDLoc &dl(
Op);
2084 unsigned HwLen = Subtarget.getVectorLength();
2086 assert(HwLen % VecLen == 0);
2087 unsigned ElemSize = HwLen / VecLen;
2099 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2105HexagonTargetLowering::LowerHvxFunnelShift(
SDValue Op,
2107 unsigned Opc =
Op.getOpcode();
2119 const SDLoc &dl(
Op);
2125 bool UseShifts = ElemTy != MVT::i8;
2126 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2129 if (
SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2137 {DAG.
getConstant(ElemWidth, dl, MVT::i32), ModS});
2153 InpTy, dl, DAG.
getConstant(ElemWidth - 1, dl, ElemTy));
2162 const SDLoc &dl(
Op);
2163 unsigned IntNo =
Op.getConstantOperandVal(0);
2171 case Intrinsic::hexagon_V6_pred_typecast:
2172 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2173 MVT ResTy = ty(
Op), InpTy = ty(
Ops[1]);
2174 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2181 case Intrinsic::hexagon_V6_vmpyss_parts:
2182 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2185 case Intrinsic::hexagon_V6_vmpyuu_parts:
2186 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2189 case Intrinsic::hexagon_V6_vmpyus_parts:
2190 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2201 const SDLoc &dl(
Op);
2202 unsigned HwLen = Subtarget.getVectorLength();
2206 SDValue Chain = MaskN->getChain();
2210 unsigned Opc =
Op->getOpcode();
2213 if (
Opc == ISD::MLOAD) {
2227 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2231 if (MaskN->getAlign().value() % HwLen == 0) {
2240 SDValue Z = getZero(dl, ty(V), DAG);
2244 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
V,
Z,
A}, DAG);
2245 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {
Z,
V,
A}, DAG);
2246 return std::make_pair(LoV, HiV);
2252 VectorPair Tmp = StoreAlign(MaskV,
Base);
2255 VectorPair ValueU = StoreAlign(
Value,
Base);
2259 getInstr(StoreOpc, dl, MVT::Other,
2260 {MaskU.first,
Base, Offset0, ValueU.first, Chain}, DAG);
2262 getInstr(StoreOpc, dl, MVT::Other,
2263 {MaskU.second,
Base, Offset1, ValueU.second, Chain}, DAG);
2273 assert(Subtarget.useHVXQFloatOps());
2275 assert(
Op->getOpcode() == ISD::FP_EXTEND);
2278 MVT ArgTy = ty(
Op.getOperand(0));
2279 const SDLoc &dl(
Op);
2280 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2289 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2291 MVT HalfTy = typeSplit(VecTy).first;
2292 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2294 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2296 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2299 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2312 MVT FpTy = ty(
Op.getOperand(0)).getVectorElementType();
2315 if (Subtarget.useHVXIEEEFPOps()) {
2317 if (FpTy == MVT::f16) {
2319 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2321 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2327 return EqualizeFpIntConversion(
Op, DAG);
2329 return ExpandHvxFpToInt(
Op, DAG);
2342 if (Subtarget.useHVXIEEEFPOps()) {
2344 if (FpTy == MVT::f16) {
2346 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2348 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2354 return EqualizeFpIntConversion(
Op, DAG);
2356 return ExpandHvxIntToFp(
Op, DAG);
2359HexagonTargetLowering::TypePair
2360HexagonTargetLowering::typeExtendToWider(
MVT Ty0,
MVT Ty1)
const {
2371 unsigned MaxWidth = std::max(Width0, Width1);
2373 auto getScalarWithWidth = [](MVT ScalarTy,
unsigned Width) {
2380 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2381 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2385 return {WideETy0, WideETy1};
2396HexagonTargetLowering::TypePair
2397HexagonTargetLowering::typeWidenToWider(
MVT Ty0,
MVT Ty1)
const {
2407 unsigned MaxLen = std::max(Len0, Len1);
2420HexagonTargetLowering::typeWidenToHvx(
MVT Ty)
const {
2421 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2430HexagonTargetLowering::VectorPair
2461HexagonTargetLowering::VectorPair
2462HexagonTargetLowering::emitHvxShiftRightRnd(
SDValue Val,
unsigned Amt,
2467 const SDLoc &dl(Val);
2468 MVT ValTy = ty(Val);
2482 MVT IntTy = tyVector(ValTy, ElemTy);
2494 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl,
Signed, DAG);
2513 MVT
PairTy = typeJoin({VecTy, VecTy});
2539 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {
B,
A}, DAG);
2541 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
A,
S16}, DAG);
2549 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl,
PairTy, {T0, T2}, DAG);
2551 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl,
PairTy, {T0, T2}, DAG);
2554 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2555 {HiHalf(P2, DAG), LoHalf(P1, DAG),
S16}, DAG);
2556 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {
B,
S16}, DAG);
2567HexagonTargetLowering::emitHvxMulLoHiV60(
SDValue A,
bool SignedA,
SDValue B,
2568 bool SignedB,
const SDLoc &dl,
2571 MVT
PairTy = typeJoin({VecTy, VecTy});
2576 if (SignedA && !SignedB) {
2592 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
2593 {DAG.
getConstant(0x02020202, dl, MVT::i32)}, DAG);
2594 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {
B, T0}, DAG);
2603 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
2606 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG),
S16}, DAG);
2610 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
2611 {HiHalf(P2, DAG), T3,
S16}, DAG);
2614 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
2615 {LoHalf(P0, DAG), LoHalf(P2, DAG),
S16}, DAG);
2619 assert(SignedB &&
"Signed A and unsigned B should have been inverted");
2626 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0,
A}, DAG);
2627 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {
Hi, X1}, DAG);
2628 }
else if (SignedB) {
2634 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1,
Hi,
A}, DAG);
2636 assert(!SignedA && !SignedB);
2643HexagonTargetLowering::emitHvxMulLoHiV62(
SDValue A,
bool SignedA,
2648 MVT
PairTy = typeJoin({VecTy, VecTy});
2651 if (SignedA && !SignedB) {
2660 getInstr(Hexagon::V6_vmpyowh_64_acc, dl,
PairTy, {
P0,
A,
B}, DAG);
2665 assert(!SignedA &&
"Signed A and unsigned B should have been inverted");
2677 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0,
B}, DAG);
2678 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0,
A}, DAG);
2679 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {
Hi,
T1}, DAG);
2680 }
else if (!SignedA) {
2690 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0,
Hi,
B}, DAG);
2708 unsigned Opc =
Op.getOpcode();
2713 MVT InpTy = ty(Inp);
2719 const SDLoc &dl(
Op);
2722 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
2731 unsigned Opc =
Op.getOpcode();
2734 const SDLoc &dl(
Op);
2736 MVT InpTy = ty(Op0);
2816 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
2817 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
2860 unsigned Opc =
Op.getOpcode();
2863 const SDLoc &dl(
Op);
2865 MVT InpTy = ty(Op0);
2898 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
2908 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1,
false, DAG);
2931 unsigned Opc =
Op.getOpcode();
2948 const SDLoc &dl(
Op);
2949 return DAG.
getNode(TLOpc, dl, ty(
Op),
Op.getOperand(0),
2958 unsigned Opc =
Op.getConstantOperandVal(2);
2962HexagonTargetLowering::VectorPair
2966 const SDLoc &dl(
Op);
2968 auto SplitVTNode = [&DAG,
this](
const VTSDNode *
N) {
2969 MVT Ty = typeSplit(
N->getVT().getSimpleVT()).first;
2971 return std::make_pair(TV, TV);
2976 ty(
A).isVector() ? opSplit(
A, dl, DAG) : std::make_pair(
A,
A);
2978 switch (
Op.getOpcode()) {
2979 case ISD::SIGN_EXTEND_INREG:
2980 case HexagonISD::SSAT:
2981 case HexagonISD::USAT:
2982 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
2983 std::tie(Lo, Hi) = SplitVTNode(N);
2991 MVT HalfTy = typeSplit(ResTy).first;
3001 MVT MemTy = MemN->getMemoryVT().getSimpleVT();
3002 if (!isHvxPairTy(MemTy))
3005 const SDLoc &dl(
Op);
3006 unsigned HwLen = Subtarget.getVectorLength();
3007 MVT SingleTy = typeSplit(MemTy).first;
3008 SDValue Chain = MemN->getChain();
3009 SDValue Base0 = MemN->getBasePtr();
3014 MachineMemOperand *MOp0 =
nullptr, *MOp1 =
nullptr;
3015 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3017 uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3024 if (MemOpc == ISD::LOAD) {
3033 if (MemOpc == ISD::STORE) {
3041 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3044 assert(MaskN->isUnindexed());
3045 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3048 if (MemOpc == ISD::MLOAD) {
3064 if (MemOpc == ISD::MSTORE) {
3067 Masks.first, SingleTy, MOp0,
3070 Masks.second, SingleTy, MOp1,
3075 std::string
Name =
"Unexpected operation: " +
Op->getOperationName(&DAG);
3081 const SDLoc &dl(
Op);
3083 assert(LoadN->isUnindexed() &&
"Not widening indexed loads yet");
3084 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3085 "Not widening loads of i1 yet");
3087 SDValue Chain = LoadN->getChain();
3092 unsigned HwLen = Subtarget.getVectorLength();
3094 assert(ResLen < HwLen &&
"vsetq(v1) prerequisite");
3097 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3105 DAG.
getUNDEF(LoadTy), LoadTy, MemOp,
3113 const SDLoc &dl(
Op);
3115 assert(StoreN->isUnindexed() &&
"Not widening indexed stores yet");
3116 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3117 "Not widening stores of i1 yet");
3119 SDValue Chain = StoreN->getChain();
3123 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3124 MVT ValueTy = ty(
Value);
3126 unsigned HwLen = Subtarget.getVectorLength();
3129 for (
unsigned Len = ValueLen;
Len < HwLen; ) {
3131 Len = ty(
Value).getVectorNumElements();
3133 assert(ty(
Value).getVectorNumElements() == HwLen);
3135 assert(ValueLen < HwLen &&
"vsetq(v1) prerequisite");
3137 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3140 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3147 const SDLoc &dl(
Op);
3148 SDValue Op0 =
Op.getOperand(0), Op1 =
Op.getOperand(1);
3150 unsigned HwLen = Subtarget.getVectorLength();
3155 if (!Subtarget.isHVXVectorType(WideOpTy,
true))
3158 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3159 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3163 {WideOp0, WideOp1,
Op.getOperand(2)});
3165 EVT RetTy = typeLegalize(ty(
Op), DAG);
3167 {SetCC, getZero(dl, MVT::i32, DAG)});
3172 unsigned Opc =
Op.getOpcode();
3173 bool IsPairOp = isHvxPairTy(ty(
Op)) ||
3175 return isHvxPairTy(ty(V));
3186 return SplitHvxMemOp(
Op, DAG);
3191 if (ty(
Op).getSizeInBits() == ty(
Op.getOperand(0)).getSizeInBits())
3192 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3202 case ISD::FMINIMUMNUM:
3203 case ISD::FMAXIMUMNUM:
3222 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3227 if (ty(
Op.getOperand(0)).getVectorElementType() == MVT::i1)
3228 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3243 case ISD::BITCAST:
return LowerHvxBitcast(
Op, DAG);
3251 case ISD::SRL:
return LowerHvxShift(
Op, DAG);
3253 case ISD::FSHR:
return LowerHvxFunnelShift(
Op, DAG);
3263 case ISD::MSTORE:
return LowerHvxMaskedOp(
Op, DAG);
3265 case ISD::LOAD:
return SDValue();
3266 case ISD::FP_EXTEND:
return LowerHvxFpExtend(
Op, DAG);
3292 unsigned Opc =
Op.getOpcode();
3312 MVT InpTy = ty(Inp);
3317 assert(InpWidth != ResWidth);
3319 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3322 const SDLoc &dl(
Op);
3326 auto repeatOp = [&](
unsigned NewWidth,
SDValue Arg) {
3334 return DAG.
getNode(
Opc, dl, Ty, {Arg,
Op.getOperand(1),
Op.getOperand(2)});
3341 if (InpWidth < ResWidth) {
3343 while (InpWidth * 2 <= ResWidth)
3344 S = repeatOp(InpWidth *= 2, S);
3348 while (InpWidth / 2 >= ResWidth)
3349 S = repeatOp(InpWidth /= 2, S);
3357 MVT InpTy = ty(Inp0);
3361 unsigned Opc =
Op.getOpcode();
3363 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3368 auto [WInpTy, WResTy] =
3369 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3370 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3371 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3379 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3380 return extractSubvector(
T, typeLegalize(ResTy, DAG), 0, DAG);
3381 }
else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3382 return opJoin(SplitVectorOp(
Op, DAG), SDLoc(
Op), DAG);
3385 return RemoveTLWrapper(
Op, DAG);
3391HexagonTargetLowering::LowerHvxOperationWrapper(
SDNode *
N,
3393 unsigned Opc =
N->getOpcode();
3396 if (
N->getNumOperands() > 0)
3397 Inp0 =
Op.getOperand(0);
3404 if (Subtarget.isHVXElementType(ty(
Op)) &&
3405 Subtarget.isHVXElementType(ty(Inp0))) {
3406 Results.push_back(CreateTLWrapper(
Op, DAG));
3410 if (shouldWidenToHvx(ty(Inp0), DAG)) {
3423 if (isHvxPairTy(ty(
Op))) {
3431 if (isHvxPairTy(ty(
Op->getOperand(1)))) {
3440 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3441 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3449 Results.push_back(LegalizeHvxResize(
Op, DAG));
3457HexagonTargetLowering::ReplaceHvxNodeResults(
SDNode *
N,
3459 unsigned Opc =
N->getOpcode();
3462 if (
N->getNumOperands() > 0)
3463 Inp0 =
Op.getOperand(0);
3470 if (Subtarget.isHVXElementType(ty(
Op)) &&
3471 Subtarget.isHVXElementType(ty(Inp0))) {
3472 Results.push_back(CreateTLWrapper(
Op, DAG));
3476 if (shouldWidenToHvx(ty(
Op), DAG)) {
3482 if (shouldWidenToHvx(ty(
Op), DAG)) {
3491 if (isHvxBoolTy(ty(Inp0))) {
3498 if (ty(
Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
3499 SDValue T = EqualizeFpIntConversion(
Op, DAG);
3507 Results.push_back(LegalizeHvxResize(
Op, DAG));
3515HexagonTargetLowering::combineTruncateBeforeLegal(
SDValue Op,
3516 DAGCombinerInfo &DCI)
const {
3521 SelectionDAG &DAG = DCI.DAG;
3522 const SDLoc &dl(
Op);
3524 if (
Op.getOperand(0).getOpcode() == ISD::BITCAST)
3529 EVT TruncTy =
Op.getValueType();
3531 EVT SrcTy = Src.getValueType();
3538 if (2 * CastLen != SrcLen)
3541 SmallVector<int, 128>
Mask(SrcLen);
3542 for (
int i = 0; i !=
static_cast<int>(CastLen); ++i) {
3544 Mask[i + CastLen] = 2 * i + 1;
3548 return opSplit(Deal, dl, DAG).first;
3552HexagonTargetLowering::combineConcatVectorsBeforeLegal(
3553 SDValue Op, DAGCombinerInfo &DCI)
const {
3561 SelectionDAG &DAG = DCI.DAG;
3562 const SDLoc &dl(
Op);
3571 SetVector<SDValue> Order;
3577 if (Order.
size() > 2)
3586 SmallVector<int, 128> LongMask;
3587 auto AppendToMask = [&](
SDValue Shuffle) {
3589 ArrayRef<int>
Mask = SV->getMask();
3592 for (
int M : Mask) {
3597 SDValue Src =
static_cast<unsigned>(
M) < InpLen ?
X :
Y;
3598 if (
static_cast<unsigned>(M) >= InpLen)
3601 int OutOffset = Order[0] == Src ? 0 : InpLen;
3618HexagonTargetLowering::PerformHvxDAGCombine(
SDNode *
N, DAGCombinerInfo &DCI)
3621 SelectionDAG &DAG = DCI.DAG;
3623 unsigned Opc =
Op.getOpcode();
3628 return combineTruncateBeforeLegal(
Op, DCI);
3630 return combineConcatVectorsBeforeLegal(
Op, DCI);
3632 if (DCI.isBeforeLegalizeOps())
3658 return getZero(dl, ty(
Op), DAG);
3661 if (isUndef(
Ops[1]))
3679HexagonTargetLowering::shouldSplitToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3680 if (Subtarget.isHVXVectorType(Ty,
true))
3682 auto Action = getPreferredHvxVectorAction(Ty);
3684 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3689HexagonTargetLowering::shouldWidenToHvx(
MVT Ty,
SelectionDAG &DAG)
const {
3690 if (Subtarget.isHVXVectorType(Ty,
true))
3692 auto Action = getPreferredHvxVectorAction(Ty);
3694 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG),
true);
3700 if (!Subtarget.useHVXOps())
3704 auto IsHvxTy = [
this](EVT Ty) {
3705 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(),
true);
3708 return Op.getValueType().isSimple() &&
3709 Subtarget.isHVXVectorType(ty(
Op),
true);
3715 auto IsWidenedToHvx = [
this, &DAG](
SDValue Op) {
3716 if (!
Op.getValueType().isSimple())
3719 return ValTy.
isVector() && shouldWidenToHvx(ValTy, DAG);
3722 for (
int i = 0, e =
N->getNumValues(); i != e; ++i) {
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static cl::opt< unsigned > HvxWidenThreshold("hexagon-hvx-widen", cl::Hidden, cl::init(16), cl::desc("Lower threshold (in bytes) for widening to HVX vectors"))
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
const SmallVectorImpl< MachineOperand > & Cond
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
uint64_t getNumOperands() const
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
EVT getSetCCResultType(const DataLayout &, LLVMContext &C, EVT VT) const override
Return the ValueType of the result of SETCC operations.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
static MVT getFloatingPointVT(unsigned BitWidth)
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Flags
Flags values. These may be or'd together.
unsigned getSubReg() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI 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.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
@ Undef
Value of the register doesn't matter.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI const fltSemantics & IEEEhalf() LLVM_READNONE
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.