69#include "llvm/IR/IntrinsicsPowerPC.h"
103#define DEBUG_TYPE "ppc-lowering"
106 "disable-p10-store-forward",
130 cl::desc(
"disable vector permute decomposition"),
134 "disable-auto-paired-vec-st",
135 cl::desc(
"disable automatically generated 32byte paired vector stores"),
140 cl::desc(
"Set minimum number of entries to use a jump table on PPC"));
144 cl::desc(
"Set minimum of largest number of comparisons to use bit test for "
149 cl::desc(
"max depth when checking alias info in GatherAllAliases()"));
153 cl::desc(
"Set inclusive limit count of TLS local-dynamic access(es) in a "
154 "function to use initial-exec"));
159 "Number of shuffles lowered to a VPERM or XXPERM");
160STATISTIC(NumDynamicAllocaProbed,
"Number of dynamic stack allocation probed");
181 initializeAddrModeMap();
184 bool isPPC64 = Subtarget.isPPC64();
186 const MVT RegVT = Subtarget.getScalarIntVT();
194 if (!Subtarget.hasEFPU2())
211 if (!Subtarget.hasP10Vector()) {
240 if (Subtarget.isISA3_0()) {
273 if (!Subtarget.hasSPE()) {
280 if (Subtarget.useCRBits()) {
283 if (isPPC64 || Subtarget.hasFPCVT()) {
349 if (Subtarget.isISA3_0()) {
384 if (!Subtarget.hasSPE()) {
389 if (Subtarget.hasVSX()) {
394 if (Subtarget.hasFSQRT()) {
399 if (Subtarget.hasFPRND()) {
440 if (Subtarget.hasSPE()) {
450 if (Subtarget.hasSPE())
454 if (!Subtarget.hasFSQRT() && !(Subtarget.hasFRSQRTE() && Subtarget.hasFRE()))
457 if (!Subtarget.hasFSQRT() &&
458 !(Subtarget.hasFRSQRTES() && Subtarget.hasFRES()))
461 if (Subtarget.hasFCPSGN()) {
469 if (Subtarget.hasFPRND()) {
483 if (Subtarget.isISA3_1()) {
489 (Subtarget.hasP9Vector() && isPPC64) ?
Custom :
Expand);
493 if (Subtarget.isISA3_0()) {
513 if (!Subtarget.useCRBits()) {
526 if (!Subtarget.useCRBits())
529 if (Subtarget.hasFPU()) {
540 if (!Subtarget.useCRBits())
545 if (Subtarget.hasSPE()) {
569 if (Subtarget.hasDirectMove() && isPPC64) {
629 if (Subtarget.is64BitELFABI()) {
640 }
else if (Subtarget.is32BitELFABI()) {
648 if (Subtarget.is32BitELFABI())
664 if (Subtarget.isISA3_0() && isPPC64) {
692 if (Subtarget.hasSPE()) {
714 if (Subtarget.has64BitSupport()) {
729 if (Subtarget.hasLFIWAX() || isPPC64) {
735 if (Subtarget.hasSPE()) {
745 if (Subtarget.hasFPCVT()) {
746 if (Subtarget.has64BitSupport()) {
767 if (Subtarget.use64BitRegs()) {
785 if (Subtarget.has64BitSupport()) {
792 if (Subtarget.hasVSX()) {
805 if (Subtarget.hasAltivec()) {
806 for (
MVT VT : { MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
823 if (VT.getSizeInBits() <= 128 && VT.getScalarSizeInBits() <= 64) {
836 if (Subtarget.hasVSX()) {
845 if (Subtarget.hasP8Altivec() && (VT.SimpleTy != MVT::v1i128)) {
855 if (Subtarget.hasP9Altivec() && (VT.SimpleTy != MVT::v1i128))
929 if (!Subtarget.hasP8Vector()) {
971 if (Subtarget.hasAltivec())
972 for (
auto VT : {MVT::v4i32, MVT::v8i16, MVT::v16i8})
975 if (Subtarget.hasP8Altivec())
986 if (Subtarget.hasVSX()) {
992 if (Subtarget.hasP8Altivec())
997 if (Subtarget.isISA3_1()) {
1043 if (Subtarget.hasVSX()) {
1046 if (Subtarget.hasP8Vector()) {
1050 if (Subtarget.hasDirectMove() && isPPC64) {
1099 if (Subtarget.hasP8Vector())
1108 if (Subtarget.hasP8Altivec()) {
1135 if (Subtarget.isISA3_1())
1238 if (Subtarget.hasP8Altivec()) {
1243 if (Subtarget.hasP9Vector()) {
1248 if (Subtarget.useCRBits()) {
1308 }
else if (Subtarget.hasVSX()) {
1333 for (
MVT VT : {MVT::f32, MVT::f64}) {
1352 if (Subtarget.hasP9Altivec()) {
1353 if (Subtarget.isISA3_1()) {
1376 if (Subtarget.hasP10Vector()) {
1381 if (Subtarget.pairedVectorMemops()) {
1386 if (Subtarget.hasMMA()) {
1387 if (Subtarget.isISAFuture()) {
1403 if (Subtarget.has64BitSupport())
1406 if (Subtarget.isISA3_1())
1424 if (Subtarget.hasAltivec()) {
1441 if (Subtarget.hasFPCVT())
1444 if (Subtarget.useCRBits())
1453 if (Subtarget.useCRBits()) {
1459 if (Subtarget.useCRBits()) {
1475 auto CPUDirective = Subtarget.getCPUDirective();
1476 switch (CPUDirective) {
1499 if (Subtarget.enableMachineScheduler())
1573void PPCTargetLowering::initializeAddrModeMap() {
1624 if (MaxAlign == MaxMaxAlign)
1627 if (MaxMaxAlign >= 32 &&
1628 VTy->getPrimitiveSizeInBits().getFixedValue() >= 256)
1629 MaxAlign =
Align(32);
1630 else if (VTy->getPrimitiveSizeInBits().getFixedValue() >= 128 &&
1632 MaxAlign =
Align(16);
1636 if (EltAlign > MaxAlign)
1637 MaxAlign = EltAlign;
1639 for (
auto *EltTy : STy->elements()) {
1642 if (EltAlign > MaxAlign)
1643 MaxAlign = EltAlign;
1644 if (MaxAlign == MaxMaxAlign)
1657 if (Subtarget.hasAltivec())
1663 return Subtarget.useSoftFloat();
1667 return Subtarget.hasSPE();
1675 Type *VectorTy,
unsigned ElemSizeInBits,
unsigned &Index)
const {
1676 if (!Subtarget.isPPC64() || !Subtarget.hasVSX())
1680 if (VTy->getScalarType()->isIntegerTy()) {
1682 if (ElemSizeInBits == 32) {
1683 Index = Subtarget.isLittleEndian() ? 2 : 1;
1686 if (ElemSizeInBits == 64) {
1687 Index = Subtarget.isLittleEndian() ? 1 : 0;
1698 return Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
1715 return CFP->getValueAPF().isZero();
1720 return CFP->getValueAPF().isZero();
1728 return Op < 0 ||
Op == Val;
1740 if (ShuffleKind == 0) {
1743 for (
unsigned i = 0; i != 16; ++i)
1746 }
else if (ShuffleKind == 2) {
1749 for (
unsigned i = 0; i != 16; ++i)
1752 }
else if (ShuffleKind == 1) {
1753 unsigned j = IsLE ? 0 : 1;
1754 for (
unsigned i = 0; i != 8; ++i)
1771 if (ShuffleKind == 0) {
1774 for (
unsigned i = 0; i != 16; i += 2)
1778 }
else if (ShuffleKind == 2) {
1781 for (
unsigned i = 0; i != 16; i += 2)
1785 }
else if (ShuffleKind == 1) {
1786 unsigned j = IsLE ? 0 : 2;
1787 for (
unsigned i = 0; i != 8; i += 2)
1808 if (!Subtarget.hasP8Vector())
1812 if (ShuffleKind == 0) {
1815 for (
unsigned i = 0; i != 16; i += 4)
1821 }
else if (ShuffleKind == 2) {
1824 for (
unsigned i = 0; i != 16; i += 4)
1830 }
else if (ShuffleKind == 1) {
1831 unsigned j = IsLE ? 0 : 4;
1832 for (
unsigned i = 0; i != 8; i += 4)
1849 unsigned LHSStart,
unsigned RHSStart) {
1850 if (
N->getValueType(0) != MVT::v16i8)
1852 assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) &&
1853 "Unsupported merge size!");
1855 for (
unsigned i = 0; i != 8/UnitSize; ++i)
1856 for (
unsigned j = 0; j != UnitSize; ++j) {
1858 LHSStart+j+i*UnitSize) ||
1860 RHSStart+j+i*UnitSize))
1875 if (ShuffleKind == 1)
1877 else if (ShuffleKind == 2)
1882 if (ShuffleKind == 1)
1884 else if (ShuffleKind == 0)
1900 if (ShuffleKind == 1)
1902 else if (ShuffleKind == 2)
1907 if (ShuffleKind == 1)
1909 else if (ShuffleKind == 0)
1959 unsigned RHSStartValue) {
1960 if (
N->getValueType(0) != MVT::v16i8)
1963 for (
unsigned i = 0; i < 2; ++i)
1964 for (
unsigned j = 0; j < 4; ++j)
1966 i*RHSStartValue+j+IndexOffset) ||
1968 i*RHSStartValue+j+IndexOffset+8))
1990 unsigned indexOffset = CheckEven ? 4 : 0;
1991 if (ShuffleKind == 1)
1993 else if (ShuffleKind == 2)
1999 unsigned indexOffset = CheckEven ? 0 : 4;
2000 if (ShuffleKind == 1)
2002 else if (ShuffleKind == 0)
2018 if (
N->getValueType(0) != MVT::v16i8)
2025 for (i = 0; i != 16 && SVOp->
getMaskElt(i) < 0; ++i)
2028 if (i == 16)
return -1;
2033 if (ShiftAmt < i)
return -1;
2038 if ((ShuffleKind == 0 && !isLE) || (ShuffleKind == 2 && isLE)) {
2040 for (++i; i != 16; ++i)
2043 }
else if (ShuffleKind == 1) {
2045 for (++i; i != 16; ++i)
2052 ShiftAmt = 16 - ShiftAmt;
2061 EVT VT =
N->getValueType(0);
2062 if (VT == MVT::v2i64 || VT == MVT::v2f64)
2063 return EltSize == 8 &&
N->getMaskElt(0) ==
N->getMaskElt(1);
2066 EltSize <= 8 &&
"Can only handle 1,2,4,8 byte element sizes");
2070 if (
N->getMaskElt(0) % EltSize != 0)
2075 unsigned ElementBase =
N->getMaskElt(0);
2078 if (ElementBase >= 16)
2083 for (
unsigned i = 1; i != EltSize; ++i)
2084 if (
N->getMaskElt(i) < 0 ||
N->getMaskElt(i) != (
int)(i+ElementBase))
2087 for (
unsigned i = EltSize, e = 16; i != e; i += EltSize) {
2089 if (
N->getMaskElt(i) < 0) {
2090 for (
unsigned j = 1; j != EltSize; ++j)
2091 if (
N->getMaskElt(i + j) >= 0)
2094 for (
unsigned j = 0; j != EltSize; ++j)
2095 if (
N->getMaskElt(i + j) !=
N->getMaskElt(j))
2112 assert((Width == 2 || Width == 4 || Width == 8 || Width == 16) &&
2113 "Unexpected element width.");
2114 assert((StepLen == 1 || StepLen == -1) &&
"Unexpected element width.");
2116 unsigned NumOfElem = 16 / Width;
2117 unsigned MaskVal[16];
2118 for (
unsigned i = 0; i < NumOfElem; ++i) {
2119 MaskVal[0] =
N->getMaskElt(i * Width);
2120 if ((StepLen == 1) && (MaskVal[0] % Width)) {
2122 }
else if ((StepLen == -1) && ((MaskVal[0] + 1) % Width)) {
2126 for (
unsigned int j = 1; j < Width; ++j) {
2127 MaskVal[j] =
N->getMaskElt(i * Width + j);
2128 if (MaskVal[j] != MaskVal[j-1] + StepLen) {
2138 unsigned &InsertAtByte,
bool &Swap,
bool IsLE) {
2143 unsigned M0 =
N->getMaskElt(0) / 4;
2144 unsigned M1 =
N->getMaskElt(4) / 4;
2145 unsigned M2 =
N->getMaskElt(8) / 4;
2146 unsigned M3 =
N->getMaskElt(12) / 4;
2147 unsigned LittleEndianShifts[] = { 2, 1, 0, 3 };
2148 unsigned BigEndianShifts[] = { 3, 0, 1, 2 };
2153 if ((
M0 > 3 &&
M1 == 1 && M2 == 2 && M3 == 3) ||
2154 (
M0 < 4 &&
M1 == 5 && M2 == 6 && M3 == 7)) {
2155 ShiftElts = IsLE ? LittleEndianShifts[
M0 & 0x3] : BigEndianShifts[
M0 & 0x3];
2156 InsertAtByte = IsLE ? 12 : 0;
2161 if ((
M1 > 3 &&
M0 == 0 && M2 == 2 && M3 == 3) ||
2162 (
M1 < 4 &&
M0 == 4 && M2 == 6 && M3 == 7)) {
2163 ShiftElts = IsLE ? LittleEndianShifts[
M1 & 0x3] : BigEndianShifts[
M1 & 0x3];
2164 InsertAtByte = IsLE ? 8 : 4;
2169 if ((M2 > 3 &&
M0 == 0 &&
M1 == 1 && M3 == 3) ||
2170 (M2 < 4 &&
M0 == 4 &&
M1 == 5 && M3 == 7)) {
2171 ShiftElts = IsLE ? LittleEndianShifts[M2 & 0x3] : BigEndianShifts[M2 & 0x3];
2172 InsertAtByte = IsLE ? 4 : 8;
2177 if ((M3 > 3 &&
M0 == 0 &&
M1 == 1 && M2 == 2) ||
2178 (M3 < 4 &&
M0 == 4 &&
M1 == 5 && M2 == 6)) {
2179 ShiftElts = IsLE ? LittleEndianShifts[M3 & 0x3] : BigEndianShifts[M3 & 0x3];
2180 InsertAtByte = IsLE ? 0 : 12;
2187 if (
N->getOperand(1).isUndef()) {
2190 unsigned XXINSERTWSrcElem = IsLE ? 2 : 1;
2191 if (
M0 == XXINSERTWSrcElem &&
M1 == 1 && M2 == 2 && M3 == 3) {
2192 InsertAtByte = IsLE ? 12 : 0;
2195 if (
M0 == 0 &&
M1 == XXINSERTWSrcElem && M2 == 2 && M3 == 3) {
2196 InsertAtByte = IsLE ? 8 : 4;
2199 if (
M0 == 0 &&
M1 == 1 && M2 == XXINSERTWSrcElem && M3 == 3) {
2200 InsertAtByte = IsLE ? 4 : 8;
2203 if (
M0 == 0 &&
M1 == 1 && M2 == 2 && M3 == XXINSERTWSrcElem) {
2204 InsertAtByte = IsLE ? 0 : 12;
2213 bool &Swap,
bool IsLE) {
2214 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2220 unsigned M0 =
N->getMaskElt(0) / 4;
2221 unsigned M1 =
N->getMaskElt(4) / 4;
2222 unsigned M2 =
N->getMaskElt(8) / 4;
2223 unsigned M3 =
N->getMaskElt(12) / 4;
2227 if (
N->getOperand(1).isUndef()) {
2228 assert(
M0 < 4 &&
"Indexing into an undef vector?");
2229 if (
M1 != (
M0 + 1) % 4 || M2 != (
M1 + 1) % 4 || M3 != (M2 + 1) % 4)
2232 ShiftElts = IsLE ? (4 -
M0) % 4 :
M0;
2238 if (
M1 != (
M0 + 1) % 8 || M2 != (
M1 + 1) % 8 || M3 != (M2 + 1) % 8)
2242 if (
M0 == 0 ||
M0 == 7 ||
M0 == 6 ||
M0 == 5) {
2247 ShiftElts = (8 -
M0) % 8;
2248 }
else if (
M0 == 4 ||
M0 == 3 ||
M0 == 2 ||
M0 == 1) {
2253 ShiftElts = (4 -
M0) % 4;
2258 if (
M0 == 0 ||
M0 == 1 ||
M0 == 2 ||
M0 == 3) {
2263 }
else if (
M0 == 4 ||
M0 == 5 ||
M0 == 6 ||
M0 == 7) {
2275 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2280 for (
int i = 0; i < 16; i += Width)
2281 if (
N->getMaskElt(i) != i + Width - 1)
2312 bool &Swap,
bool IsLE) {
2313 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2319 unsigned M0 =
N->getMaskElt(0) / 8;
2320 unsigned M1 =
N->getMaskElt(8) / 8;
2321 assert(((
M0 |
M1) < 4) &&
"A mask element out of bounds?");
2325 if (
N->getOperand(1).isUndef()) {
2326 if ((
M0 |
M1) < 2) {
2327 DM = IsLE ? (((
~M1) & 1) << 1) + ((~
M0) & 1) : (
M0 << 1) + (
M1 & 1);
2335 if (
M0 > 1 &&
M1 < 2) {
2345 DM = (((
~M1) & 1) << 1) + ((~
M0) & 1);
2350 }
else if (
M0 > 1 &&
M1 < 2) {
2358 DM = (
M0 << 1) + (
M1 & 1);
2373 if (VT == MVT::v2i64 || VT == MVT::v2f64)
2378 return (16 / EltSize) - 1 - (SVOp->
getMaskElt(0) / EltSize);
2394 unsigned EltSize = 16/
N->getNumOperands();
2395 if (EltSize < ByteSize) {
2396 unsigned Multiple = ByteSize/EltSize;
2398 assert(Multiple > 1 && Multiple <= 4 &&
"How can this happen?");
2401 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
2402 if (
N->getOperand(i).isUndef())
continue;
2406 if (!UniquedVals[i&(Multiple-1)].
getNode())
2407 UniquedVals[i&(Multiple-1)] =
N->getOperand(i);
2408 else if (UniquedVals[i&(Multiple-1)] !=
N->getOperand(i))
2418 bool LeadingZero =
true;
2419 bool LeadingOnes =
true;
2420 for (
unsigned i = 0; i != Multiple-1; ++i) {
2421 if (!UniquedVals[i].
getNode())
continue;
2428 if (!UniquedVals[Multiple-1].
getNode())
2435 if (!UniquedVals[Multiple-1].
getNode())
2446 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
2447 if (
N->getOperand(i).isUndef())
continue;
2449 OpVal =
N->getOperand(i);
2450 else if (OpVal !=
N->getOperand(i))
2456 unsigned ValSizeInBytes = EltSize;
2459 Value = CN->getZExtValue();
2461 assert(CN->getValueType(0) == MVT::f32 &&
"Only one legal FP vector type!");
2468 if (ValSizeInBytes < ByteSize)
return SDValue();
2479 if (MaskVal == 0)
return SDValue();
2499 Imm = (int16_t)
N->getAsZExtVal();
2500 if (
N->getValueType(0) == MVT::i32)
2501 return Imm == (int32_t)
N->getAsZExtVal();
2503 return Imm == (int64_t)
N->getAsZExtVal();
2521 return (~(LHSKnown.
Zero | RHSKnown.
Zero) == 0);
2529 for (
SDNode *U :
N->users()) {
2531 if (Memop->getMemoryVT() == MVT::f64) {
2532 Base =
N.getOperand(0);
2533 Index =
N.getOperand(1);
2576 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm)))
2578 if (
N.getOperand(1).getOpcode() == PPCISD::Lo)
2581 Base =
N.getOperand(0);
2582 Index =
N.getOperand(1);
2584 }
else if (
N.getOpcode() ==
ISD::OR) {
2586 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm)))
2598 if (~(LHSKnown.
Zero | RHSKnown.
Zero) == 0) {
2599 Base =
N.getOperand(0);
2600 Index =
N.getOperand(1);
2670 (!EncodingAlignment ||
isAligned(*EncodingAlignment, imm))) {
2676 Base =
N.getOperand(0);
2679 }
else if (
N.getOperand(1).getOpcode() == PPCISD::Lo) {
2681 assert(!
N.getOperand(1).getConstantOperandVal(1) &&
2682 "Cannot handle constant offsets yet!");
2683 Disp =
N.getOperand(1).getOperand(0);
2688 Base =
N.getOperand(0);
2691 }
else if (
N.getOpcode() ==
ISD::OR) {
2694 (!EncodingAlignment ||
isAligned(*EncodingAlignment, imm))) {
2708 Base =
N.getOperand(0);
2721 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm))) {
2724 CN->getValueType(0));
2729 if ((CN->getValueType(0) == MVT::i32 ||
2730 (int64_t)CN->getZExtValue() == (
int)CN->getZExtValue()) &&
2731 (!EncodingAlignment ||
2732 isAligned(*EncodingAlignment, CN->getZExtValue()))) {
2733 int Addr = (int)CN->getZExtValue();
2740 unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8;
2761 if (
N.getValueType() != MVT::i64)
2774 Base =
N.getOperand(0);
2790 Base =
N.getOperand(0);
2823 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
2824 Base =
N.getOperand(0);
2825 Index =
N.getOperand(1);
2847 if (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR)
2868 EVT MemVT = LD->getMemoryVT();
2875 if (!ST.hasP8Vector())
2880 if (!ST.hasP9Vector())
2892 if (
Use.getResNo() == 0 &&
2894 Use.
getUser()->getOpcode() != PPCISD::SCALAR_TO_VECTOR_PERMUTED)
2914 Ptr = LD->getBasePtr();
2915 VT = LD->getMemoryVT();
2916 Alignment = LD->getAlign();
2918 Ptr = ST->getBasePtr();
2919 VT = ST->getMemoryVT();
2920 Alignment = ST->getAlign();
2959 if (VT != MVT::i64) {
2964 if (Alignment <
Align(4))
2974 if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 &&
2991 unsigned &HiOpFlags,
unsigned &LoOpFlags,
3033 EVT VT = Subtarget.getScalarIntVT();
3035 : Subtarget.isAIXABI()
3040 PPCISD::TOC_ENTRY, dl, DAG.
getVTList(VT, MVT::Other),
Ops, VT,
3047 EVT PtrVT =
Op.getValueType();
3053 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3054 if (Subtarget.isUsingPCRelativeCalls()) {
3059 return DAG.
getNode(PPCISD::MAT_PCREL_ADDR,
DL, Ty, ConstPool);
3063 return getTOCEntry(DAG, SDLoc(CP), GA);
3066 unsigned MOHiFlag, MOLoFlag;
3070 if (IsPIC && Subtarget.isSVR4ABI()) {
3073 return getTOCEntry(DAG, SDLoc(CP), GA);
3096 if (Subtarget.isPPC64() || Subtarget.isAIXABI())
3103 if (!Subtarget.isPPC64() || Subtarget.isAIXABI())
3120 if (!Subtarget.isPPC64() || Subtarget.isAIXABI())
3133 EVT PtrVT =
Op.getValueType();
3151 return getTOCEntry(DAG,
SDLoc(JT), GA);
3154 unsigned MOHiFlag, MOLoFlag;
3158 if (IsPIC && Subtarget.isSVR4ABI()) {
3161 return getTOCEntry(DAG, SDLoc(GA), GA);
3171 EVT PtrVT =
Op.getValueType();
3176 if (Subtarget.isUsingPCRelativeCalls()) {
3187 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3190 return getTOCEntry(DAG, SDLoc(BASDN), GA);
3199 unsigned MOHiFlag, MOLoFlag;
3209 if (Subtarget.isAIXABI())
3210 return LowerGlobalTLSAddressAIX(
Op, DAG);
3212 return LowerGlobalTLSAddressLinux(
Op, DAG);
3234 if (
I.getOpcode() == Instruction::Call)
3236 if (
Function *CF = CI->getCalledFunction())
3237 if (CF->isDeclaration() &&
3238 CF->getIntrinsicID() == Intrinsic::threadlocal_address)
3246 unsigned TLSGVCnt = TLSGV.
size();
3256 <<
" function is using the TLS-IE model for TLS-LD access.\n");
3269 const GlobalValue *GV = GA->
getGlobal();
3271 bool Is64Bit = Subtarget.isPPC64();
3275 if (Subtarget.hasAIXShLibTLSModelOpt())
3285 bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS();
3286 bool HasAIXSmallTLSGlobalAttr =
false;
3289 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3293 if (GVar->hasAttribute(
"aix-small-tls"))
3294 HasAIXSmallTLSGlobalAttr =
true;
3313 if ((HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr) &&
3314 IsTLSLocalExecModel) {
3319 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA, TLSReg);
3329 TLSReg = DAG.
getNode(PPCISD::GET_TPOINTER, dl, PtrVT);
3334 if (HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr)
3336 "currently only supported on AIX (64-bit mode).");
3338 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
3342 bool HasAIXSmallLocalDynamicTLS = Subtarget.hasAIXSmallLocalDynamicTLS();
3346 if (!Is64Bit && HasAIXSmallLocalDynamicTLS)
3348 "currently only supported on AIX (64-bit mode).");
3356 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3359 GlobalVariable *TLSGV =
3363 assert(TLSGV &&
"Not able to create GV for _$TLSML.");
3366 SDValue ModuleHandleTOC = getTOCEntry(DAG, dl, ModuleHandleTGA);
3368 DAG.
getNode(PPCISD::TLSLD_AIX, dl, PtrVT, ModuleHandleTOC);
3377 if (HasAIXSmallLocalDynamicTLS) {
3382 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA,
3386 return DAG.
getNode(
ISD::ADD, dl, PtrVT, ModuleHandle, VariableOffset);
3399 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3400 SDValue RegionHandle = getTOCEntry(DAG, dl, RegionHandleTGA);
3401 return DAG.
getNode(PPCISD::TLSGD_AIX, dl, PtrVT, VariableOffset,
3416 const GlobalValue *GV = GA->
getGlobal();
3418 bool is64bit = Subtarget.isPPC64();
3426 if (Subtarget.isUsingPCRelativeCalls()) {
3431 DAG.
getNode(PPCISD::TLS_LOCAL_EXEC_MAT_ADDR, dl, PtrVT, TGA);
3432 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, MatAddr);
3443 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, TGALo,
Hi);
3447 bool IsPCRel = Subtarget.isUsingPCRelativeCalls();
3454 SDValue MatPCRel = DAG.
getNode(PPCISD::MAT_PCREL_ADDR, dl, PtrVT, TGA);
3456 MachinePointerInfo());
3463 DAG.
getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl, PtrVT, GOTReg, TGA);
3465 if (!TM.isPositionIndependent())
3466 GOTPtr = DAG.
getNode(PPCISD::PPC32_GOT, dl, PtrVT);
3472 TPOffset = DAG.
getNode(PPCISD::LD_GOT_TPREL_L, dl, PtrVT, TGA, GOTPtr);
3474 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TPOffset, TGATLS);
3478 if (Subtarget.isUsingPCRelativeCalls()) {
3481 return DAG.
getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3489 GOTPtr = DAG.
getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT,
3497 return DAG.
getNode(PPCISD::ADDI_TLSGD_L_ADDR, dl, PtrVT,
3502 if (Subtarget.isUsingPCRelativeCalls()) {
3506 DAG.
getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3507 return DAG.
getNode(PPCISD::PADDI_DTPREL, dl, PtrVT, MatPCRel, TGA);
3515 GOTPtr = DAG.
getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT,
3524 PtrVT, GOTPtr, TGA, TGA);
3526 PtrVT, TLSAddr, TGA);
3527 return DAG.
getNode(PPCISD::ADDI_DTPREL_L, dl, PtrVT, DtvOffsetHi, TGA);
3535 EVT PtrVT =
Op.getValueType();
3538 const GlobalValue *GV = GSDN->
getGlobal();
3542 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3543 if (Subtarget.isUsingPCRelativeCalls()) {
3550 MachinePointerInfo());
3555 return DAG.
getNode(PPCISD::MAT_PCREL_ADDR,
DL, Ty, GA);
3560 return getTOCEntry(DAG,
DL, GA);
3563 unsigned MOHiFlag, MOLoFlag;
3567 if (IsPIC && Subtarget.isSVR4ABI()) {
3571 return getTOCEntry(DAG,
DL, GA);
3583 bool IsStrict =
Op->isStrictFPOpcode();
3589 EVT LHSVT =
LHS.getValueType();
3593 if (LHSVT == MVT::f128) {
3594 assert(!Subtarget.hasP9Vector() &&
3595 "SETCC for f128 is already legal under Power9!");
3606 assert(!IsStrict &&
"Don't know how to handle STRICT_FSETCC!");
3608 if (
Op.getValueType() == MVT::v2i64) {
3611 if (
LHS.getValueType() == MVT::v2i64) {
3619 int ShuffV[] = {1, 0, 3, 2};
3624 dl, MVT::v4i32, Shuff, SetCC32));
3641 if (
C->isAllOnes() ||
C->isZero())
3651 EVT VT =
Op.getValueType();
3659 SDNode *
Node =
Op.getNode();
3660 EVT VT =
Node->getValueType(0);
3667 assert(!Subtarget.isPPC64() &&
"LowerVAARG is PPC32 only");
3671 VAListPtr, MachinePointerInfo(SV), MVT::i8);
3674 if (VT == MVT::i64) {
3693 FprPtr, MachinePointerInfo(SV), MVT::i8);
3704 DAG.
getLoad(MVT::i32, dl, InChain, OverflowAreaPtr, MachinePointerInfo());
3705 InChain = OverflowArea.
getValue(1);
3708 DAG.
getLoad(MVT::i32, dl, InChain, RegSaveAreaPtr, MachinePointerInfo());
3738 MachinePointerInfo(SV), MVT::i8);
3751 InChain = DAG.
getTruncStore(InChain, dl, OverflowArea, OverflowAreaPtr,
3752 MachinePointerInfo(), MVT::i32);
3754 return DAG.
getLoad(VT, dl, InChain, Result, MachinePointerInfo());
3758 assert(!Subtarget.isPPC64() &&
"LowerVACOPY is PPC32 only");
3764 false,
true,
nullptr, std::nullopt,
3765 MachinePointerInfo(), MachinePointerInfo());
3770 return Op.getOperand(0);
3775 PPCFunctionInfo &MFI = *MF.
getInfo<PPCFunctionInfo>();
3779 "Expecting Inline ASM node.");
3789 if (
Op.getOperand(
NumOps - 1).getValueType() == MVT::Glue)
3794 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(i));
3795 unsigned NumVals =
Flags.getNumOperandRegisters();
3798 switch (
Flags.getKind()) {
3809 for (; NumVals; --NumVals, ++i) {
3811 if (
Reg != PPC::LR &&
Reg != PPC::LR8)
3834 if (Subtarget.isAIXABI()) {
3838 uint64_t
PointerSize = Subtarget.isPPC64() ? 8 : 4;
3839 MaybeAlign PointerAlign(PointerSize);
3840 auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
3843 : MachineMemOperand::MONone;
3850 const Value *TrampolineAddr =
3860 DAG.
getLoad(PtrVT, dl, Chain, FPtr, MachinePointerInfo(Func, 0),
3861 PointerAlign, MMOFlags);
3863 OutChains[0] = DAG.
getStore(EPLoadChain, dl, LoadEntryPoint, Trmp,
3864 MachinePointerInfo(TrampolineAddr, 0));
3868 SDValue TOCFromDescriptorPtr =
3870 SDValue TOCReg = DAG.
getLoad(PtrVT, dl, Chain, TOCFromDescriptorPtr,
3871 MachinePointerInfo(Func, TOCPointerOffset),
3872 PointerAlign, MMOFlags);
3873 SDValue TrampolineTOCPointer =
3877 DAG.
getStore(TOCLoadChain, dl, TOCReg, TrampolineTOCPointer,
3878 MachinePointerInfo(TrampolineAddr, TOCPointerOffset));
3884 DAG.
getStore(Chain, dl, Nest, EnvPointer,
3885 MachinePointerInfo(TrampolineAddr, EnvPointerOffset));
3892 bool isPPC64 = (PtrVT == MVT::i64);
3896 Args.emplace_back(Trmp, IntPtrTy);
3899 DAG.
getConstant(isPPC64 ? 48 : 40, dl, Subtarget.getScalarIntVT()),
3901 Args.emplace_back(FPtr, IntPtrTy);
3902 Args.emplace_back(Nest, IntPtrTy);
3905 TargetLowering::CallLoweringInfo CLI(DAG);
3906 CLI.setDebugLoc(dl).setChain(Chain).setLibCallee(
3910 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3911 return CallResult.second;
3916 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
3921 if (Subtarget.isPPC64() || Subtarget.isAIXABI()) {
3926 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
3927 MachinePointerInfo(SV));
3961 uint64_t FrameOffset = PtrVT.getSizeInBits()/8;
3964 uint64_t StackOffset = PtrVT.getSizeInBits()/8 - 1;
3967 uint64_t FPROffset = 1;
3975 MachinePointerInfo(SV), MVT::i8);
3976 uint64_t nextOffset = FPROffset;
3983 MachinePointerInfo(SV, nextOffset), MVT::i8);
3984 nextOffset += StackOffset;
3985 nextPtr = DAG.
getNode(
ISD::ADD, dl, PtrVT, nextPtr, ConstStackOffset);
3988 SDValue thirdStore = DAG.
getStore(secondStore, dl, StackOffsetFI, nextPtr,
3989 MachinePointerInfo(SV, nextOffset));
3990 nextOffset += FrameOffset;
3991 nextPtr = DAG.
getNode(
ISD::ADD, dl, PtrVT, nextPtr, ConstFrameOffset);
3994 return DAG.
getStore(thirdStore, dl, FR, nextPtr,
3995 MachinePointerInfo(SV, nextOffset));
4000static const MCPhysReg FPR[] = {PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5,
4001 PPC::F6, PPC::F7, PPC::F8, PPC::F9, PPC::F10,
4002 PPC::F11, PPC::F12, PPC::F13};
4007 unsigned PtrByteSize) {
4009 if (Flags.isByVal())
4010 ArgSize = Flags.getByValSize();
4014 if (!Flags.isInConsecutiveRegs())
4015 ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4024 unsigned PtrByteSize) {
4025 Align Alignment(PtrByteSize);
4028 if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 ||
4029 ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 ||
4030 ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 ||
4031 ArgVT == MVT::v1i128 || ArgVT == MVT::f128)
4032 Alignment =
Align(16);
4035 if (Flags.isByVal()) {
4036 auto BVAlign = Flags.getNonZeroByValAlign();
4037 if (BVAlign > PtrByteSize) {
4038 if (BVAlign.value() % PtrByteSize != 0)
4040 "ByVal alignment is not a multiple of the pointer size");
4042 Alignment = BVAlign;
4047 if (Flags.isInConsecutiveRegs()) {
4051 if (Flags.isSplit() && OrigVT != MVT::ppcf128)
4065 unsigned PtrByteSize,
unsigned LinkageSize,
4066 unsigned ParamAreaSize,
unsigned &ArgOffset,
4067 unsigned &AvailableFPRs,
4068 unsigned &AvailableVRs) {
4069 bool UseMemory =
false;
4074 ArgOffset =
alignTo(ArgOffset, Alignment);
4077 if (ArgOffset >= LinkageSize + ParamAreaSize)
4082 if (Flags.isInConsecutiveRegsLast())
4083 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4086 if (ArgOffset > LinkageSize + ParamAreaSize)
4091 if (!Flags.isByVal()) {
4092 if (ArgVT == MVT::f32 || ArgVT == MVT::f64)
4093 if (AvailableFPRs > 0) {
4097 if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 ||
4098 ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 ||
4099 ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 ||
4100 ArgVT == MVT::v1i128 || ArgVT == MVT::f128)
4101 if (AvailableVRs > 0) {
4113 unsigned NumBytes) {
4117SDValue PPCTargetLowering::LowerFormalArguments(
4121 if (Subtarget.isAIXABI())
4122 return LowerFormalArguments_AIX(Chain, CallConv, isVarArg, Ins, dl, DAG,
4124 if (Subtarget.is64BitELFABI())
4125 return LowerFormalArguments_64SVR4(Chain, CallConv, isVarArg, Ins, dl, DAG,
4127 assert(Subtarget.is32BitELFABI());
4128 return LowerFormalArguments_32SVR4(Chain, CallConv, isVarArg, Ins, dl, DAG,
4132SDValue PPCTargetLowering::LowerFormalArguments_32SVR4(
4168 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
4174 const Align PtrAlign(4);
4182 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
4183 CCInfo.AllocateStack(LinkageSize, PtrAlign);
4186 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4187 CCValAssign &VA = ArgLocs[i];
4191 const TargetRegisterClass *RC;
4199 RC = &PPC::GPRCRegClass;
4202 if (Subtarget.hasP8Vector())
4203 RC = &PPC::VSSRCRegClass;
4204 else if (Subtarget.hasSPE())
4205 RC = &PPC::GPRCRegClass;
4207 RC = &PPC::F4RCRegClass;
4210 if (Subtarget.hasVSX())
4211 RC = &PPC::VSFRCRegClass;
4212 else if (Subtarget.hasSPE())
4214 RC = &PPC::GPRCRegClass;
4216 RC = &PPC::F8RCRegClass;
4221 RC = &PPC::VRRCRegClass;
4224 RC = &PPC::VRRCRegClass;
4228 RC = &PPC::VRRCRegClass;
4235 if (VA.
getLocVT() == MVT::f64 && Subtarget.hasSPE()) {
4236 assert(i + 1 < e &&
"No second half of double precision argument");
4241 if (!Subtarget.isLittleEndian())
4243 ArgValue = DAG.
getNode(PPCISD::BUILD_SPE64, dl, MVT::f64, ArgValueLo,
4248 ValVT == MVT::i1 ? MVT::i32 : ValVT);
4249 if (ValVT == MVT::i1)
4264 ArgOffset += ArgSize - ObjSize;
4282 CCByValInfo.AllocateStack(CCInfo.getStackSize(), PtrAlign);
4287 unsigned MinReservedArea = CCByValInfo.getStackSize();
4288 MinReservedArea = std::max(MinReservedArea, LinkageSize);
4304 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
4305 PPC::R7, PPC::R8, PPC::R9, PPC::R10,
4307 const unsigned NumGPArgRegs = std::size(GPArgRegs);
4310 PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
4313 unsigned NumFPArgRegs = std::size(FPArgRegs);
4322 int Depth = NumGPArgRegs * PtrVT.getSizeInBits()/8 +
4323 NumFPArgRegs * MVT(MVT::f64).getSizeInBits()/8;
4326 PtrVT.getSizeInBits() / 8, CCInfo.getStackSize(),
true));
4339 VReg = MF.
addLiveIn(GPArgReg, &PPC::GPRCRegClass);
4354 for (
unsigned FPRIndex = 0; FPRIndex != NumFPArgRegs; ++FPRIndex) {
4358 VReg = MF.
addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass);
4371 if (!MemOps.
empty())
4382 const SDLoc &dl)
const {
4386 else if (
Flags.isZExt())
4393SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
4399 bool isELFv2ABI = Subtarget.isELFv2ABI();
4400 bool isLittleEndian = Subtarget.isLittleEndian();
4403 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
4406 "fastcc not supported on varargs functions");
4412 unsigned PtrByteSize = 8;
4413 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
4416 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
4417 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
4420 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
4421 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
4424 const unsigned Num_GPR_Regs = std::size(GPR);
4426 const unsigned Num_VR_Regs = std::size(VR);
4434 bool HasParameterArea = !isELFv2ABI || isVarArg;
4435 unsigned ParamAreaSize = Num_GPR_Regs * PtrByteSize;
4436 unsigned NumBytes = LinkageSize;
4437 unsigned AvailableFPRs = Num_FPR_Regs;
4438 unsigned AvailableVRs = Num_VR_Regs;
4439 for (
const ISD::InputArg &In : Ins) {
4440 if (
In.Flags.isNest())
4444 LinkageSize, ParamAreaSize, NumBytes,
4445 AvailableFPRs, AvailableVRs))
4446 HasParameterArea =
true;
4453 unsigned ArgOffset = LinkageSize;
4454 unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
4457 unsigned CurArgIdx = 0;
4458 for (
unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
4460 bool needsLoad =
false;
4461 EVT ObjectVT = Ins[ArgNo].VT;
4462 EVT OrigVT = Ins[ArgNo].ArgVT;
4464 unsigned ArgSize = ObjSize;
4465 ISD::ArgFlagsTy
Flags = Ins[ArgNo].Flags;
4466 if (Ins[ArgNo].isOrigArg()) {
4467 std::advance(FuncArg, Ins[ArgNo].getOrigArgIndex() - CurArgIdx);
4468 CurArgIdx = Ins[ArgNo].getOrigArgIndex();
4473 unsigned CurArgOffset;
4475 auto ComputeArgOffset = [&]() {
4479 ArgOffset =
alignTo(ArgOffset, Alignment);
4480 CurArgOffset = ArgOffset;
4487 GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
4488 GPR_idx = std::min(GPR_idx, Num_GPR_Regs);
4493 if (
Flags.isByVal()) {
4494 assert(Ins[ArgNo].isOrigArg() &&
"Byval arguments cannot be implicit");
4500 ObjSize =
Flags.getByValSize();
4501 ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4523 if (HasParameterArea ||
4524 ArgSize + ArgOffset > LinkageSize + Num_GPR_Regs * PtrByteSize)
4531 if (ObjSize < PtrByteSize) {
4535 if (!isLittleEndian) {
4541 if (GPR_idx != Num_GPR_Regs) {
4548 MachinePointerInfo(&*FuncArg), ObjType);
4553 ArgOffset += PtrByteSize;
4562 for (
unsigned j = 0;
j < ArgSize;
j += PtrByteSize) {
4563 if (GPR_idx == Num_GPR_Regs)
4574 unsigned StoreSizeInBits = std::min(PtrByteSize, (ObjSize - j)) * 8;
4578 MachinePointerInfo(&*FuncArg, j), ObjType);
4582 ArgOffset += ArgSize;
4591 if (
Flags.isNest()) {
4596 if (ObjectVT == MVT::i32 || ObjectVT == MVT::i1)
4597 ArgVal = extendArgForPPC64(Flags, ObjectVT, DAG, ArgVal, dl);
4605 if (GPR_idx != Num_GPR_Regs) {
4610 if (ObjectVT == MVT::i32 || ObjectVT == MVT::i1)
4613 ArgVal = extendArgForPPC64(Flags, ObjectVT, DAG, ArgVal, dl);
4619 ArgSize = PtrByteSize;
4630 if (FPR_idx != Num_FPR_Regs) {
4633 if (ObjectVT == MVT::f32)
4635 Subtarget.hasP8Vector()
4636 ? &PPC::VSSRCRegClass
4637 : &PPC::F4RCRegClass);
4640 ? &PPC::VSFRCRegClass
4641 : &PPC::F8RCRegClass);
4656 if (ObjectVT == MVT::f32) {
4657 if ((ArgOffset % PtrByteSize) == (isLittleEndian ? 4 : 0))
4675 ArgSize =
Flags.isInConsecutiveRegs() ? ObjSize : PtrByteSize;
4676 ArgOffset += ArgSize;
4677 if (
Flags.isInConsecutiveRegsLast())
4678 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4692 if (VR_idx != Num_VR_Regs) {
4709 if (ObjSize < ArgSize && !isLittleEndian)
4710 CurArgOffset += ArgSize - ObjSize;
4713 ArgVal = DAG.
getLoad(ObjectVT, dl, Chain, FIN, MachinePointerInfo());
4720 unsigned MinReservedArea;
4721 if (HasParameterArea)
4722 MinReservedArea = std::max(ArgOffset, LinkageSize + 8 * PtrByteSize);
4724 MinReservedArea = LinkageSize;
4741 int Depth = ArgOffset;
4750 for (GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
4751 GPR_idx < Num_GPR_Regs; ++GPR_idx) {
4763 if (!MemOps.
empty())
4772 unsigned ParamSize) {
4774 if (!isTailCall)
return 0;
4778 int SPDiff = (int)CallerMinReservedArea - (
int)ParamSize;
4780 if (SPDiff < FI->getTailCallSPDelta())
4796 "PC Relative callers do not have a TOC and cannot share a TOC Base");
4855 Caller->hasComdat() || CalleeGV->
getSection() != Caller->getSection())
4858 if (
F->getSectionPrefix() != Caller->getSectionPrefix())
4870 const unsigned PtrByteSize = 8;
4874 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
4875 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
4878 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
4879 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
4882 const unsigned NumGPRs = std::size(GPR);
4883 const unsigned NumFPRs = 13;
4884 const unsigned NumVRs = std::size(VR);
4885 const unsigned ParamAreaSize = NumGPRs * PtrByteSize;
4887 unsigned NumBytes = LinkageSize;
4888 unsigned AvailableFPRs = NumFPRs;
4889 unsigned AvailableVRs = NumVRs;
4892 if (Param.Flags.isNest())
continue;
4895 LinkageSize, ParamAreaSize, NumBytes,
4896 AvailableFPRs, AvailableVRs))
4907 auto CalleeArgEnd = CB.
arg_end();
4910 for (; CalleeArgIter != CalleeArgEnd; ++CalleeArgIter, ++CallerArgIter) {
4911 const Value* CalleeArg = *CalleeArgIter;
4912 const Value* CallerArg = &(*CallerArgIter);
4913 if (CalleeArg == CallerArg)
4939 if (!isTailCallableCC(CallerCC) || !isTailCallableCC(CalleeCC))
4949bool PPCTargetLowering::IsEligibleForTailCallOptimization_64SVR4(
4954 bool isCalleeExternalSymbol)
const {
4957 if (
DisableSCO && !TailCallOpt)
return false;
4960 if (isVarArg)
return false;
4967 if (
any_of(Ins, [](
const ISD::InputArg &IA) {
return IA.Flags.isByVal(); }))
5003 if (!Subtarget.isUsingPCRelativeCalls() &&
5008 if (!Subtarget.isUsingPCRelativeCalls() &&
5036bool PPCTargetLowering::IsEligibleForTailCallOptimization(
5049 if (
any_of(Ins, [](
const ISD::InputArg &IA) {
return IA.Flags.isByVal(); }))
5070 if (!
C)
return nullptr;
5072 int Addr =
C->getZExtValue();
5073 if ((Addr & 3) != 0 ||
5079 (
int)
C->getZExtValue() >> 2,
SDLoc(
Op),
5086struct TailCallArgumentInfo {
5091 TailCallArgumentInfo() =
default;
5101 for (
unsigned i = 0, e = TailCallArgs.
size(); i != e; ++i) {
5102 SDValue Arg = TailCallArgs[i].Arg;
5103 SDValue FIN = TailCallArgs[i].FrameIdxOp;
5104 int FI = TailCallArgs[i].FrameIdx;
5107 Chain, dl, Arg, FIN,
5116 int SPDiff,
const SDLoc &dl) {
5122 int SlotSize = Subtarget.isPPC64() ? 8 : 4;
5123 int NewRetAddrLoc = SPDiff + FL->getReturnSaveOffset();
5125 NewRetAddrLoc,
true);
5128 Chain = DAG.
getStore(Chain, dl, OldRetAddr, NewRetAddrFrIdx,
5138 int SPDiff,
unsigned ArgOffset,
5140 int Offset = ArgOffset + SPDiff;
5143 EVT VT = IsPPC64 ? MVT::i64 : MVT::i32;
5145 TailCallArgumentInfo Info;
5147 Info.FrameIdxOp = FIN;
5155SDValue PPCTargetLowering::EmitTailCallLoadFPAndRetAddr(
5160 LROpOut = getReturnAddrFrameIndex(DAG);
5161 LROpOut = DAG.
getLoad(Subtarget.getScalarIntVT(), dl, Chain, LROpOut,
5162 MachinePointerInfo());
5179 Chain, dl, Dst, Src, SizeNode, Flags.getNonZeroByValAlign(),
false,
false,
5187 SDValue PtrOff,
int SPDiff,
unsigned ArgOffset,
bool isPPC64,
5211 const SDLoc &dl,
int SPDiff,
unsigned NumBytes,
SDValue LROp,
5221 if (!MemOpChains2.
empty())
5245SDValue PPCTargetLowering::LowerCallResult(
5253 CCRetInfo.AnalyzeCallResult(
5259 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
5260 CCValAssign &VA = RVLocs[i];
5265 if (Subtarget.hasSPE() && VA.
getLocVT() == MVT::f64) {
5275 if (!Subtarget.isLittleEndian())
5277 Val = DAG.
getNode(PPCISD::BUILD_SPE64, dl, MVT::f64,
Lo,
Hi);
5343 bool IsStrictFPCall =
false) {
5345 return PPCISD::TC_RETURN;
5347 unsigned RetOpc = 0;
5362 RetOpc = PPCISD::CALL_NOTOC;
5377 RetOpc = PPCISD::CALL;
5378 if (IsStrictFPCall) {
5382 case PPCISD::BCTRL_LOAD_TOC:
5383 RetOpc = PPCISD::BCTRL_LOAD_TOC_RM;
5386 RetOpc = PPCISD::BCTRL_RM;
5388 case PPCISD::CALL_NOTOC:
5389 RetOpc = PPCISD::CALL_NOTOC_RM;
5392 RetOpc = PPCISD::CALL_RM;
5394 case PPCISD::CALL_NOP:
5395 RetOpc = PPCISD::CALL_NOP_RM;
5409 auto isLocalCallee = [&]() {
5425 const auto getAIXFuncEntryPointSymbolSDNode = [&](
const GlobalValue *GV) {
5442 return getAIXFuncEntryPointSymbolSDNode(GV);
5449 const char *SymName = S->getSymbol();
5456 return getAIXFuncEntryPointSymbolSDNode(
F);
5462 const auto getExternalFunctionEntryPointSymbol = [&](
StringRef SymName) {
5470 SymName = getExternalFunctionEntryPointSymbol(SymName)->getName().data();
5477 assert(Callee.getNode() &&
"What no callee?");
5483 "Expected a CALLSEQ_STARTSDNode.");
5500 SDValue MTCTROps[] = {Chain, Callee, Glue};
5501 EVT ReturnTypes[] = {MVT::Other, MVT::Glue};
5502 Chain = DAG.
getNode(PPCISD::MTCTR, dl, ReturnTypes,
5542 auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
5561 SDValue LoadFuncPtr = DAG.
getLoad(RegVT, dl, LDChain, Callee, MPI,
5562 Alignment, MMOFlags);
5569 DAG.
getLoad(RegVT, dl, LDChain, AddTOC,
5576 DAG.
getLoad(RegVT, dl, LDChain, AddPtr,
5588 "Nest parameter is not supported on AIX.");
5604 SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass,
5607 const bool IsPPC64 = Subtarget.isPPC64();
5612 Ops.push_back(Chain);
5616 Ops.push_back(Callee);
5636 Ops.push_back(AddTOC);
5647 Ops.push_back(DAG.
getRegister(IsPPC64 ? PPC::CTR8 : PPC::CTR, RegVT));
5656 for (
const auto &[
Reg,
N] : RegsToPass)
5674 assert(Mask &&
"Missing call preserved mask for calling convention");
5679 Ops.push_back(Glue);
5682SDValue PPCTargetLowering::FinishCall(
5689 if ((Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls()) ||
5690 Subtarget.isAIXABI())
5697 if (!CFlags.IsIndirect)
5699 else if (Subtarget.usesFunctionDescriptors())
5701 dl, CFlags.HasNest, Subtarget);
5711 if (CFlags.IsTailCall) {
5719 (CFlags.IsIndirect && Subtarget.isUsingPCRelativeCalls())) &&
5720 "Expecting a global address, external symbol, absolute value, "
5721 "register or an indirect tail call when PC Relative calls are "
5724 assert(CallOpc == PPCISD::TC_RETURN &&
5725 "Unexpected call opcode for a tail call.");
5732 std::array<EVT, 2> ReturnTypes = {{MVT::Other, MVT::Glue}};
5733 Chain = DAG.
getNode(CallOpc, dl, ReturnTypes,
Ops);
5745 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, BytesCalleePops, Glue, dl);
5748 return LowerCallResult(Chain, Glue, CFlags.CallConv, CFlags.IsVarArg, Ins, dl,
5768 return isEligibleForTCO(CalleeGV, CalleeCC, CallerCC, CB,
5769 CalleeFunc->
isVarArg(), Outs, Ins, CallerFunc,
5773bool PPCTargetLowering::isEligibleForTCO(
5778 bool isCalleeExternalSymbol)
const {
5782 if (Subtarget.
isSVR4ABI() && Subtarget.isPPC64())
5783 return IsEligibleForTailCallOptimization_64SVR4(
5784 CalleeGV, CalleeCC, CallerCC, CB, isVarArg, Outs, Ins, CallerFunc,
5785 isCalleeExternalSymbol);
5787 return IsEligibleForTailCallOptimization(CalleeGV, CalleeCC, CallerCC,
5815 isEligibleForTCO(GV, CallConv, CallerCC, CB, isVarArg, Outs, Ins,
5830 "Callee should be an llvm::Function object.");
5833 <<
"\nTCO callee: ");
5840 "site marked musttail");
5847 Callee = LowerGlobalAddress(Callee, DAG);
5850 CallConv, isTailCall, isVarArg, isPatchPoint,
5853 Subtarget.is64BitELFABI() &&
5857 if (Subtarget.isAIXABI())
5858 return LowerCall_AIX(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5861 assert(Subtarget.isSVR4ABI());
5862 if (Subtarget.isPPC64())
5863 return LowerCall_64SVR4(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5865 return LowerCall_32SVR4(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5869SDValue PPCTargetLowering::LowerCall_32SVR4(
5880 const bool IsVarArg = CFlags.IsVarArg;
5881 const bool IsTailCall = CFlags.IsTailCall;
5887 const Align PtrAlign(4);
5898 MF.
getInfo<PPCFunctionInfo>()->setHasFastCall();
5906 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.
getContext());
5909 CCInfo.AllocateStack(Subtarget.getFrameLowering()->getLinkageSize(),
5916 unsigned NumArgs = Outs.
size();
5918 for (
unsigned i = 0; i != NumArgs; ++i) {
5919 MVT ArgVT = Outs[i].VT;
5920 ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
5925 Outs[i].OrigTy, CCInfo);
5928 ArgFlags, Outs[i].OrigTy, CCInfo);
5933 errs() <<
"Call operand #" << i <<
" has unhandled type "
5946 CCState CCByValInfo(CallConv, IsVarArg, MF, ByValArgLocs, *DAG.
getContext());
5949 CCByValInfo.AllocateStack(CCInfo.getStackSize(), PtrAlign);
5956 unsigned NumBytes = CCByValInfo.getStackSize();
5970 Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, dl);
5981 bool seenFloatArg =
false;
5986 for (
unsigned i = 0, RealArgIdx = 0, j = 0, e = ArgLocs.
size();
5988 ++i, ++RealArgIdx) {
5989 CCValAssign &VA = ArgLocs[i];
5990 SDValue Arg = OutVals[RealArgIdx];
5991 ISD::ArgFlagsTy
Flags = Outs[RealArgIdx].Flags;
5993 if (
Flags.isByVal()) {
5998 assert((j < ByValArgLocs.
size()) &&
"Index out of bounds!");
5999 CCValAssign &ByValVA = ByValArgLocs[
j++];
6021 Chain = CallSeqStart = NewCallSeqStart;
6040 if (Subtarget.hasSPE() && Arg.
getValueType() == MVT::f64) {
6041 bool IsLE = Subtarget.isLittleEndian();
6042 SDValue SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
6045 SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
6047 RegsToPass.
push_back(std::make_pair(ArgLocs[++i].getLocReg(),
6062 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
6071 if (!MemOpChains.
empty())
6077 for (
const auto &[
Reg,
N] : RegsToPass) {
6085 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
6088 Chain = DAG.
getNode(seenFloatArg ? PPCISD::CR6SET : PPCISD::CR6UNSET, dl,
6098 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
6099 Callee, SPDiff, NumBytes, Ins, InVals, CB);
6104SDValue PPCTargetLowering::createMemcpyOutsideCallSeq(
6116 return NewCallSeqStart;
6119SDValue PPCTargetLowering::LowerCall_64SVR4(
6126 bool isELFv2ABI = Subtarget.isELFv2ABI();
6127 bool isLittleEndian = Subtarget.isLittleEndian();
6129 bool IsSibCall =
false;
6133 unsigned PtrByteSize = 8;
6146 MF.
getInfo<PPCFunctionInfo>()->setHasFastCall();
6148 assert(!(IsFastCall && CFlags.IsVarArg) &&
6149 "fastcc not supported on varargs functions");
6155 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
6156 unsigned NumBytes = LinkageSize;
6157 unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
6160 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6161 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
6164 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
6165 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
6168 const unsigned NumGPRs = std::size(GPR);
6170 const unsigned NumVRs = std::size(VR);
6176 bool HasParameterArea = !isELFv2ABI || CFlags.IsVarArg || IsFastCall;
6177 if (!HasParameterArea) {
6178 unsigned ParamAreaSize = NumGPRs * PtrByteSize;
6179 unsigned AvailableFPRs = NumFPRs;
6180 unsigned AvailableVRs = NumVRs;
6181 unsigned NumBytesTmp = NumBytes;
6182 for (
unsigned i = 0; i !=
NumOps; ++i) {
6183 if (Outs[i].
Flags.isNest())
continue;
6185 PtrByteSize, LinkageSize, ParamAreaSize,
6186 NumBytesTmp, AvailableFPRs, AvailableVRs))
6187 HasParameterArea =
true;
6193 unsigned NumGPRsUsed = 0, NumFPRsUsed = 0, NumVRsUsed = 0;
6198 HasParameterArea =
false;
6201 for (
unsigned i = 0; i !=
NumOps; ++i) {
6202 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
6203 EVT ArgVT = Outs[i].VT;
6204 EVT OrigVT = Outs[i].ArgVT;
6210 if (
Flags.isByVal()) {
6211 NumGPRsUsed += (
Flags.getByValSize()+7)/8;
6212 if (NumGPRsUsed > NumGPRs)
6213 HasParameterArea =
true;
6220 if (++NumGPRsUsed <= NumGPRs)
6230 if (++NumVRsUsed <= NumVRs)
6234 if (++NumVRsUsed <= NumVRs)
6239 if (++NumFPRsUsed <= NumFPRs)
6243 HasParameterArea =
true;
6250 NumBytes =
alignTo(NumBytes, Alignement);
6253 if (
Flags.isInConsecutiveRegsLast())
6254 NumBytes = ((NumBytes + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
6257 unsigned NumBytesActuallyUsed = NumBytes;
6267 if (HasParameterArea)
6268 NumBytes = std::max(NumBytes, LinkageSize + 8 * PtrByteSize);
6270 NumBytes = LinkageSize;
6285 if (CFlags.IsTailCall)
6297 Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, dl);
6308 unsigned ArgOffset = LinkageSize;
6314 for (
unsigned i = 0; i !=
NumOps; ++i) {
6316 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
6317 EVT ArgVT = Outs[i].VT;
6318 EVT OrigVT = Outs[i].ArgVT;
6327 auto ComputePtrOff = [&]() {
6331 ArgOffset =
alignTo(ArgOffset, Alignment);
6342 GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
6343 GPR_idx = std::min(GPR_idx, NumGPRs);
6350 Arg = DAG.
getNode(ExtOp, dl, MVT::i64, Arg);
6356 if (
Flags.isByVal()) {
6374 EVT VT = (
Size==1) ? MVT::i8 : ((
Size==2) ? MVT::i16 : MVT::i32);
6375 if (GPR_idx != NumGPRs) {
6377 MachinePointerInfo(), VT);
6379 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6381 ArgOffset += PtrByteSize;
6386 if (GPR_idx == NumGPRs &&
Size < 8) {
6388 if (!isLittleEndian) {
6393 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, AddPtr,
6396 ArgOffset += PtrByteSize;
6405 if ((NumGPRs - GPR_idx) * PtrByteSize <
Size)
6406 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, PtrOff,
6411 if (
Size < 8 && GPR_idx != NumGPRs) {
6421 if (!isLittleEndian) {
6425 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, AddPtr,
6431 DAG.
getLoad(PtrVT, dl, Chain, PtrOff, MachinePointerInfo());
6433 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6436 ArgOffset += PtrByteSize;
6442 for (
unsigned j=0;
j<
Size;
j+=PtrByteSize) {
6445 if (GPR_idx != NumGPRs) {
6446 unsigned LoadSizeInBits = std::min(PtrByteSize, (
Size - j)) * 8;
6449 MachinePointerInfo(), ObjType);
6452 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6453 ArgOffset += PtrByteSize;
6455 ArgOffset += ((
Size -
j + PtrByteSize-1)/PtrByteSize)*PtrByteSize;
6467 if (
Flags.isNest()) {
6469 RegsToPass.
push_back(std::make_pair(PPC::X11, Arg));
6476 if (GPR_idx != NumGPRs) {
6477 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Arg));
6482 assert(HasParameterArea &&
6483 "Parameter area must exist to pass an argument in memory.");
6485 true, CFlags.IsTailCall,
false, MemOpChains,
6486 TailCallArguments, dl);
6488 ArgOffset += PtrByteSize;
6491 ArgOffset += PtrByteSize;
6504 bool NeedGPROrStack = CFlags.IsVarArg || FPR_idx == NumFPRs;
6505 bool NeededLoad =
false;
6508 if (FPR_idx != NumFPRs)
6509 RegsToPass.
push_back(std::make_pair(
FPR[FPR_idx++], Arg));
6512 if (!NeedGPROrStack)
6514 else if (GPR_idx != NumGPRs && !IsFastCall) {
6528 }
else if (!
Flags.isInConsecutiveRegs()) {
6534 }
else if (ArgOffset % PtrByteSize != 0) {
6538 if (!isLittleEndian)
6543 }
else if (
Flags.isInConsecutiveRegsLast()) {
6546 if (!isLittleEndian)
6556 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], ArgVal));
6564 !isLittleEndian && !
Flags.isInConsecutiveRegs()) {
6569 assert(HasParameterArea &&
6570 "Parameter area must exist to pass an argument in memory.");
6572 true, CFlags.IsTailCall,
false, MemOpChains,
6573 TailCallArguments, dl);
6580 if (!IsFastCall || NeededLoad) {
6582 Flags.isInConsecutiveRegs()) ? 4 : 8;
6583 if (
Flags.isInConsecutiveRegsLast())
6584 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
6604 if (CFlags.IsVarArg) {
6605 assert(HasParameterArea &&
6606 "Parameter area must exist if we have a varargs call.");
6610 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
6612 if (VR_idx != NumVRs) {
6614 DAG.
getLoad(MVT::v4f32, dl, Store, PtrOff, MachinePointerInfo());
6616 RegsToPass.
push_back(std::make_pair(VR[VR_idx++], Load));
6619 for (
unsigned i=0; i<16; i+=PtrByteSize) {
6620 if (GPR_idx == NumGPRs)
6625 DAG.
getLoad(PtrVT, dl, Store, Ix, MachinePointerInfo());
6627 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6633 if (VR_idx != NumVRs) {
6634 RegsToPass.
push_back(std::make_pair(VR[VR_idx++], Arg));
6639 assert(HasParameterArea &&
6640 "Parameter area must exist to pass an argument in memory.");
6642 true, CFlags.IsTailCall,
true, MemOpChains,
6643 TailCallArguments, dl);
6654 assert((!HasParameterArea || NumBytesActuallyUsed == ArgOffset) &&
6655 "mismatch in size of parameter area");
6656 (void)NumBytesActuallyUsed;
6658 if (!MemOpChains.
empty())
6664 if (CFlags.IsIndirect) {
6668 assert(!CFlags.IsTailCall &&
"Indirect tails calls not supported");
6673 unsigned TOCSaveOffset = Subtarget.getFrameLowering()->getTOCSaveOffset();
6683 if (isELFv2ABI && !CFlags.IsPatchPoint)
6684 RegsToPass.
push_back(std::make_pair((
unsigned)PPC::X12, Callee));
6690 for (
const auto &[
Reg,
N] : RegsToPass) {
6695 if (CFlags.IsTailCall && !IsSibCall)
6699 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
6700 Callee, SPDiff, NumBytes, Ins, InVals, CB);
6707 "Required alignment greater than stack alignment.");
6727 return RequiredAlign <= 8;
6732 return RequiredAlign <= 4;
6740 State.getMachineFunction().getSubtarget());
6741 const bool IsPPC64 = Subtarget.isPPC64();
6742 const unsigned PtrSize = IsPPC64 ? 8 : 4;
6743 const Align PtrAlign(PtrSize);
6744 const Align StackAlign(16);
6747 if (ValVT == MVT::f128)
6751 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
6752 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
6754 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6755 PPC::X7, PPC::X8, PPC::X9, PPC::X10};
6758 PPC::V2, PPC::V3, PPC::V4, PPC::V5,
6759 PPC::V6, PPC::V7, PPC::V8, PPC::V9,
6760 PPC::V10, PPC::V11, PPC::V12, PPC::V13};
6765 MCRegister EnvReg = State.AllocateReg(IsPPC64 ? PPC::X11 : PPC::R11);
6774 if (ByValAlign > StackAlign)
6776 "16 are not supported.");
6779 const Align ObjAlign = ByValAlign > PtrAlign ? ByValAlign : PtrAlign;
6783 if (ByValSize == 0) {
6785 State.getStackSize(), RegVT, LocInfo));
6790 unsigned NextReg = State.getFirstUnallocated(GPRs);
6791 while (NextReg != GPRs.
size() &&
6796 State.AllocateStack(PtrSize, PtrAlign);
6797 assert(
Reg &&
"Alocating register unexpectedly failed.");
6799 NextReg = State.getFirstUnallocated(GPRs);
6802 const unsigned StackSize =
alignTo(ByValSize, ObjAlign);
6803 unsigned Offset = State.AllocateStack(StackSize, ObjAlign);
6823 assert(IsPPC64 &&
"PPC32 should have split i64 values.");
6827 const unsigned Offset = State.AllocateStack(PtrSize, PtrAlign);
6846 State.AllocateStack(IsPPC64 ? 8 : StoreSize,
Align(4));
6852 for (
unsigned I = 0;
I < StoreSize;
I += PtrSize) {
6854 assert(FReg &&
"An FPR should be available when a GPR is reserved.");
6855 if (State.isVarArg()) {
6887 const unsigned VecSize = 16;
6888 const Align VecAlign(VecSize);
6890 if (!State.isVarArg()) {
6893 if (
MCRegister VReg = State.AllocateReg(VR)) {
6900 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6905 unsigned NextRegIndex = State.getFirstUnallocated(GPRs);
6908 while (NextRegIndex != GPRs.
size() &&
6912 State.AllocateStack(PtrSize, PtrAlign);
6913 assert(
Reg &&
"Allocating register unexpectedly failed.");
6915 NextRegIndex = State.getFirstUnallocated(GPRs);
6923 if (
MCRegister VReg = State.AllocateReg(VR)) {
6926 for (
unsigned I = 0;
I != VecSize;
I += PtrSize)
6927 State.AllocateReg(GPRs);
6928 State.AllocateStack(VecSize, VecAlign);
6932 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6938 if (NextRegIndex == GPRs.
size()) {
6939 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6947 if (GPRs[NextRegIndex] == PPC::R9) {
6948 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6952 const MCRegister FirstReg = State.AllocateReg(PPC::R9);
6953 const MCRegister SecondReg = State.AllocateReg(PPC::R10);
6954 assert(FirstReg && SecondReg &&
6955 "Allocating R9 or R10 unexpectedly failed.");
6966 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6969 for (
unsigned I = 0;
I != VecSize;
I += PtrSize) {
6971 assert(
Reg &&
"Failed to allocated register for vararg vector argument");
6986 assert((IsPPC64 || SVT != MVT::i64) &&
6987 "i64 should have been split for 32-bit codegen.");
6995 return IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
6997 return HasP8Vector ? &PPC::VSSRCRegClass : &PPC::F4RCRegClass;
6999 return HasVSX ? &PPC::VSFRCRegClass : &PPC::F8RCRegClass;
7007 return &PPC::VRRCRegClass;
7020 else if (Flags.isZExt())
7032 "Reg must be a valid argument register!");
7033 return LASize + 4 * (
Reg - PPC::R3);
7038 "Reg must be a valid argument register!");
7039 return LASize + 8 * (
Reg - PPC::X3);
7085SDValue PPCTargetLowering::LowerFormalArguments_AIX(
7092 "Unexpected calling convention!");
7100 const PPCSubtarget &Subtarget = DAG.
getSubtarget<PPCSubtarget>();
7102 const bool IsPPC64 = Subtarget.isPPC64();
7103 const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
7109 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
7110 CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.
getContext());
7114 const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
7115 CCInfo.AllocateStack(LinkageSize,
Align(PtrByteSize));
7116 uint64_t SaveStackPos = CCInfo.getStackSize();
7118 CCInfo.AnalyzeFormalArguments(Ins,
CC_AIX);
7122 for (
size_t I = 0, End = ArgLocs.
size();
I != End; ) {
7123 CCValAssign &VA = ArgLocs[
I++];
7128 EVT ArgVT = Ins[VA.
getValNo()].ArgVT;
7129 bool ArgSignExt = Ins[VA.
getValNo()].Flags.isSExt();
7141 LocVT.
SimpleTy, IsPPC64, Subtarget.hasP8Vector(), Subtarget.hasVSX());
7143 MVT SaveVT = RegClass == &PPC::G8RCRegClass ? MVT::i64 : LocVT;
7149 MachinePointerInfo(),
Align(PtrByteSize));
7155 unsigned StoreSize =
7157 SaveStackPos =
alignTo(SaveStackPos + StoreSize, PtrByteSize);
7160 auto HandleMemLoc = [&]() {
7163 assert((ValSize <= LocSize) &&
7164 "Object size is larger than size of MemLoc");
7167 if (LocSize > ValSize)
7168 CurArgOffset += LocSize - ValSize;
7170 const bool IsImmutable =
7176 DAG.
getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo());
7210 assert(isVarArg &&
"Only use custom memloc for vararg.");
7213 const unsigned OriginalValNo = VA.
getValNo();
7214 (void)OriginalValNo;
7216 auto HandleCustomVecRegLoc = [&]() {
7217 assert(
I != End && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7218 "Missing custom RegLoc.");
7221 "Unexpected Val type for custom RegLoc.");
7223 "ValNo mismatch between custom MemLoc and RegLoc.");
7227 Subtarget.hasVSX()));
7234 HandleCustomVecRegLoc();
7235 HandleCustomVecRegLoc();
7239 if (
I != End && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom()) {
7241 "Only 2 custom RegLocs expected for 64-bit codegen.");
7242 HandleCustomVecRegLoc();
7243 HandleCustomVecRegLoc();
7287 const unsigned Size =
7299 if (
Flags.isByVal()) {
7303 const PPCFrameLowering *FL = Subtarget.getFrameLowering();
7305 const unsigned StackSize =
alignTo(
Flags.getByValSize(), PtrByteSize);
7313 const TargetRegisterClass *RegClass =
7314 IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
7316 auto HandleRegLoc = [&, RegClass, LocVT](
const MCPhysReg PhysReg,
7329 CopyFrom.
getValue(1), dl, CopyFrom,
7339 for (;
Offset != StackSize && ArgLocs[
I].isRegLoc();
7342 "RegLocs should be for ByVal argument.");
7344 const CCValAssign RL = ArgLocs[
I++];
7349 if (
Offset != StackSize) {
7351 "Expected MemLoc for remaining bytes.");
7352 assert(ArgLocs[
I].isMemLoc() &&
"Expected MemLoc for remaining bytes.");
7366 Subtarget.hasVSX()));
7383 const unsigned MinParameterSaveArea = 8 * PtrByteSize;
7385 unsigned CallerReservedArea = std::max<unsigned>(
7386 CCInfo.getStackSize(), LinkageSize + MinParameterSaveArea);
7392 CallerReservedArea =
7397 int VAListIndex = 0;
7401 if (CCInfo.getStackSize() < (LinkageSize + MinParameterSaveArea)) {
7402 unsigned FixedStackSize =
7403 LinkageSize + MinParameterSaveArea - CCInfo.getStackSize();
7419 static const MCPhysReg GPR_32[] = {PPC::R3, PPC::R4, PPC::R5, PPC::R6,
7420 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
7422 static const MCPhysReg GPR_64[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6,
7423 PPC::X7, PPC::X8, PPC::X9, PPC::X10};
7424 const unsigned NumGPArgRegs = std::size(IsPPC64 ? GPR_64 : GPR_32);
7430 GPRIndex = (CCInfo.getStackSize() - LinkageSize) / PtrByteSize,
7432 GPRIndex < NumGPArgRegs; ++GPRIndex,
Offset += PtrByteSize) {
7435 IsPPC64 ? MF.
addLiveIn(GPR_64[GPRIndex], &PPC::G8RCRegClass)
7436 : MF.
addLiveIn(GPR_32[GPRIndex], &PPC::GPRCRegClass);
7439 MachinePointerInfo MPI =
7449 if (!MemOps.
empty())
7455SDValue PPCTargetLowering::LowerCall_AIX(
7468 "Unexpected calling convention!");
7470 if (CFlags.IsPatchPoint)
7473 const PPCSubtarget &Subtarget = DAG.
getSubtarget<PPCSubtarget>();
7477 CCState CCInfo(CFlags.CallConv, CFlags.IsVarArg, MF, ArgLocs,
7484 const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
7485 const bool IsPPC64 = Subtarget.isPPC64();
7487 const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
7488 CCInfo.AllocateStack(LinkageSize,
Align(PtrByteSize));
7489 CCInfo.AnalyzeCallOperands(Outs,
CC_AIX);
7497 const unsigned MinParameterSaveAreaSize = 8 * PtrByteSize;
7498 const unsigned NumBytes = std::max<unsigned>(
7499 LinkageSize + MinParameterSaveAreaSize, CCInfo.getStackSize());
7515 for (
unsigned I = 0,
E = ArgLocs.
size();
I !=
E;) {
7516 const unsigned ValNo = ArgLocs[
I].getValNo();
7518 ISD::ArgFlagsTy
Flags = Outs[ValNo].Flags;
7520 if (
Flags.isByVal()) {
7521 const unsigned ByValSize =
Flags.getByValSize();
7529 auto GetLoad = [&](EVT VT,
unsigned LoadOffset) {
7535 MachinePointerInfo(), VT);
7538 unsigned LoadOffset = 0;
7541 while (LoadOffset + PtrByteSize <= ByValSize && ArgLocs[
I].isRegLoc()) {
7544 LoadOffset += PtrByteSize;
7545 const CCValAssign &ByValVA = ArgLocs[
I++];
7547 "Unexpected location for pass-by-value argument.");
7551 if (LoadOffset == ByValSize)
7555 assert(ArgLocs[
I].getValNo() == ValNo &&
7556 "Expected additional location for by-value argument.");
7558 if (ArgLocs[
I].isMemLoc()) {
7559 assert(LoadOffset < ByValSize &&
"Unexpected memloc for by-val arg.");
7560 const CCValAssign &ByValVA = ArgLocs[
I++];
7561 ISD::ArgFlagsTy MemcpyFlags =
Flags;
7564 Chain = CallSeqStart = createMemcpyOutsideCallSeq(
7570 CallSeqStart, MemcpyFlags, DAG, dl);
7579 const unsigned ResidueBytes = ByValSize % PtrByteSize;
7580 assert(ResidueBytes != 0 && LoadOffset + PtrByteSize > ByValSize &&
7581 "Unexpected register residue for by-value argument.");
7583 for (
unsigned Bytes = 0; Bytes != ResidueBytes;) {
7587 : ((
N == 2) ? MVT::i16 : (
N == 4 ? MVT::i32 : MVT::i64));
7597 "Unexpected load emitted during handling of pass-by-value "
7605 ResidueVal = ResidueVal ? DAG.
getNode(
ISD::OR, dl, PtrVT, ResidueVal,
7610 const CCValAssign &ByValVA = ArgLocs[
I++];
7615 CCValAssign &VA = ArgLocs[
I++];
7640 assert(CFlags.IsVarArg &&
"Custom MemLocs only used for Vector args.");
7646 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
7648 const unsigned OriginalValNo = VA.
getValNo();
7650 unsigned LoadOffset = 0;
7651 auto HandleCustomVecRegLoc = [&]() {
7652 assert(
I !=
E &&
"Unexpected end of CCvalAssigns.");
7653 assert(ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7654 "Expected custom RegLoc.");
7655 CCValAssign RegVA = ArgLocs[
I++];
7657 "Custom MemLoc ValNo and custom RegLoc ValNo must match.");
7663 LoadOffset += PtrByteSize;
7669 HandleCustomVecRegLoc();
7670 HandleCustomVecRegLoc();
7672 if (
I !=
E && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7673 ArgLocs[
I].getValNo() == OriginalValNo) {
7675 "Only 2 custom RegLocs expected for 64-bit codegen.");
7676 HandleCustomVecRegLoc();
7677 HandleCustomVecRegLoc();
7688 DAG.
getStore(Chain, dl, Arg, PtrOff,
7690 Subtarget.getFrameLowering()->getStackAlign()));
7697 "Unexpected register handling for calling convention.");
7703 "Custom register handling only expected for VarArg.");
7708 if (Arg.getValueType().getStoreSize() == LocVT.
getStoreSize())
7712 else if (Arg.getValueType().getFixedSizeInBits() <
7720 assert(Arg.getValueType() == MVT::f64 && CFlags.IsVarArg && !IsPPC64 &&
7721 "Unexpected custom register for argument!");
7722 CCValAssign &GPR1 = VA;
7731 CCValAssign &PeekArg = ArgLocs[
I];
7734 CCValAssign &GPR2 = ArgLocs[
I++];
7742 if (!MemOpChains.
empty())
7747 if (CFlags.IsIndirect) {
7748 assert(!CFlags.IsTailCall &&
"Indirect tail-calls not supported.");
7749 const MCRegister TOCBaseReg = Subtarget.getTOCPointerRegister();
7750 const MCRegister StackPtrReg = Subtarget.getStackPointerRegister();
7751 const MVT PtrVT = Subtarget.getScalarIntVT();
7752 const unsigned TOCSaveOffset =
7753 Subtarget.getFrameLowering()->getTOCSaveOffset();
7768 for (
auto Reg : RegsToPass) {
7773 const int SPDiff = 0;
7774 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
7775 Callee, SPDiff, NumBytes, Ins, InVals, CB);
7783 const Type *RetTy)
const {
7785 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
7786 return CCInfo.CheckReturn(
7801 CCInfo.AnalyzeReturn(Outs,
7810 for (
unsigned i = 0, RealResIdx = 0; i != RVLocs.
size(); ++i, ++RealResIdx) {
7811 CCValAssign &VA = RVLocs[i];
7814 SDValue Arg = OutVals[RealResIdx];
7829 if (Subtarget.hasSPE() && VA.
getLocVT() == MVT::f64) {
7830 bool isLittleEndian = Subtarget.isLittleEndian();
7833 DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
7837 SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
7852 RetOps.push_back(Glue);
7854 return DAG.
getNode(PPCISD::RET_GLUE, dl, MVT::Other, RetOps);
7858PPCTargetLowering::LowerGET_DYNAMIC_AREA_OFFSET(
SDValue Op,
7863 EVT IntVT =
Op.getValueType();
7867 SDValue FPSIdx = getFramePointerFrameIndex(DAG);
7871 return DAG.
getNode(PPCISD::DYNAREAOFFSET, dl, VTs,
Ops);
7883 bool isPPC64 = Subtarget.isPPC64();
7884 unsigned SP = isPPC64 ? PPC::X1 : PPC::R1;
7893 DAG.
getLoad(PtrVT, dl, Chain, StackPtr, MachinePointerInfo());
7899 return DAG.
getStore(Chain, dl, LoadLinkSP, StackPtr, MachinePointerInfo());
7904 bool isPPC64 = Subtarget.isPPC64();
7909 PPCFunctionInfo *FI = MF.
getInfo<PPCFunctionInfo>();
7915 int LROffset = Subtarget.getFrameLowering()->getReturnSaveOffset();
7925PPCTargetLowering::getFramePointerFrameIndex(
SelectionDAG & DAG)
const {
7927 bool isPPC64 = Subtarget.isPPC64();
7932 PPCFunctionInfo *FI = MF.
getInfo<PPCFunctionInfo>();
7938 int FPOffset = Subtarget.getFrameLowering()->getFramePointerSaveOffset();
7961 SDValue FPSIdx = getFramePointerFrameIndex(DAG);
7963 SDVTList VTs = DAG.
getVTList(PtrVT, MVT::Other);
7965 return DAG.
getNode(PPCISD::PROBED_ALLOCA, dl, VTs,
Ops);
7966 return DAG.
getNode(PPCISD::DYNALLOC, dl, VTs,
Ops);
7973 bool isPPC64 = Subtarget.isPPC64();
7983 return DAG.
getNode(PPCISD::EH_SJLJ_SETJMP,
DL,
7985 Op.getOperand(0),
Op.getOperand(1));
7991 return DAG.
getNode(PPCISD::EH_SJLJ_LONGJMP,
DL, MVT::Other,
7992 Op.getOperand(0),
Op.getOperand(1));
7996 if (
Op.getValueType().isVector())
7997 return LowerVectorLoad(
Op, DAG);
7999 assert(
Op.getValueType() == MVT::i1 &&
8000 "Custom lowering only for i1 loads");
8009 MachineMemOperand *MMO =
LD->getMemOperand();
8013 BasePtr, MVT::i8, MMO);
8021 if (
Op.getOperand(1).getValueType().isVector())
8022 return LowerVectorStore(
Op, DAG);
8024 assert(
Op.getOperand(1).getValueType() == MVT::i1 &&
8025 "Custom lowering only for i1 stores");
8035 MachineMemOperand *MMO =
ST->getMemOperand();
8044 assert(
Op.getValueType() == MVT::i1 &&
8045 "Custom lowering only for i1 results");
8073 EVT TrgVT =
Op.getValueType();
8097 if (SrcSize == 256) {
8108 Op1 = SrcSize == 128 ? N1 :
widenVec(DAG, N1,
DL);
8114 SmallVector<int, 16> ShuffV;
8115 if (Subtarget.isLittleEndian())
8116 for (
unsigned i = 0; i < TrgNumElts; ++i)
8119 for (
unsigned i = 1; i <= TrgNumElts; ++i)
8123 for (
unsigned i = TrgNumElts; i < WideNumElts; ++i)
8136 EVT ResVT =
Op.getValueType();
8137 EVT CmpVT =
Op.getOperand(0).getValueType();
8139 SDValue TV =
Op.getOperand(2), FV =
Op.getOperand(3);
8145 if (!Subtarget.hasP9Vector() && CmpVT == MVT::f128) {
8158 SDNodeFlags
Flags =
Op.getNode()->getFlags();
8162 if (Subtarget.hasP9Vector() &&
LHS == TV &&
RHS == FV) {
8194 if (
LHS.getValueType() == MVT::f32)
8196 Sel1 = DAG.
getNode(PPCISD::FSEL, dl, ResVT,
LHS, TV, FV);
8199 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8207 if (
LHS.getValueType() == MVT::f32)
8209 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
LHS, TV, FV);
8216 if (
LHS.getValueType() == MVT::f32)
8218 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8230 if (
Cmp.getValueType() == MVT::f32)
8232 Sel1 = DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8235 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8240 if (
Cmp.getValueType() == MVT::f32)
8242 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV);
8246 if (
Cmp.getValueType() == MVT::f32)
8248 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8252 if (
Cmp.getValueType() == MVT::f32)
8254 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV);
8258 if (
Cmp.getValueType() == MVT::f32)
8260 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8269 case PPCISD::FCTIDZ:
8270 return PPCISD::STRICT_FCTIDZ;
8271 case PPCISD::FCTIWZ:
8272 return PPCISD::STRICT_FCTIWZ;
8273 case PPCISD::FCTIDUZ:
8274 return PPCISD::STRICT_FCTIDUZ;
8275 case PPCISD::FCTIWUZ:
8276 return PPCISD::STRICT_FCTIWUZ;
8278 return PPCISD::STRICT_FCFID;
8279 case PPCISD::FCFIDU:
8280 return PPCISD::STRICT_FCFIDU;
8281 case PPCISD::FCFIDS:
8282 return PPCISD::STRICT_FCFIDS;
8283 case PPCISD::FCFIDUS:
8284 return PPCISD::STRICT_FCFIDUS;
8291 bool IsStrict =
Op->isStrictFPOpcode();
8300 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8302 MVT DestTy =
Op.getSimpleValueType();
8303 assert(Src.getValueType().isFloatingPoint() &&
8304 (DestTy == MVT::i8 || DestTy == MVT::i16 || DestTy == MVT::i32 ||
8305 DestTy == MVT::i64) &&
8306 "Invalid FP_TO_INT types");
8307 if (Src.getValueType() == MVT::f32) {
8311 DAG.
getVTList(MVT::f64, MVT::Other), {Chain, Src}, Flags);
8316 if ((DestTy == MVT::i8 || DestTy == MVT::i16) && Subtarget.hasP9Vector())
8322 Opc = IsSigned ? PPCISD::FCTIWZ
8323 : (Subtarget.hasFPCVT() ? PPCISD::FCTIWUZ : PPCISD::FCTIDZ);
8326 assert((IsSigned || Subtarget.hasFPCVT()) &&
8327 "i64 FP_TO_UINT is supported only with FPCVT");
8328 Opc = IsSigned ? PPCISD::FCTIDZ : PPCISD::FCTIDUZ;
8330 EVT ConvTy = Src.getValueType() == MVT::f128 ? MVT::f128 : MVT::f64;
8342void PPCTargetLowering::LowerFP_TO_INTForReuse(
SDValue Op, ReuseLoadInfo &RLI,
8344 const SDLoc &dl)
const {
8348 bool IsStrict =
Op->isStrictFPOpcode();
8351 bool i32Stack =
Op.getValueType() == MVT::i32 && Subtarget.hasSTFIWX() &&
8352 (IsSigned || Subtarget.hasFPCVT());
8355 MachinePointerInfo MPI =
8363 Alignment =
Align(4);
8364 MachineMemOperand *MMO =
8370 Chain = DAG.
getStore(Chain, dl, Tmp, FIPtr, MPI, Alignment);
8374 if (
Op.getValueType() == MVT::i32 && !i32Stack &&
8375 !Subtarget.isLittleEndian()) {
8384 RLI.Alignment = Alignment;
8392 const SDLoc &dl)
const {
8395 if (
Op->isStrictFPOpcode())
8402 const SDLoc &dl)
const {
8403 bool IsStrict =
Op->isStrictFPOpcode();
8406 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8407 EVT SrcVT = Src.getValueType();
8408 EVT DstVT =
Op.getValueType();
8411 if (SrcVT == MVT::f128)
8412 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8416 if (SrcVT == MVT::ppcf128) {
8417 if (DstVT == MVT::i32) {
8422 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8433 {Op.getOperand(0), Lo, Hi}, Flags);
8436 {Res.getValue(1), Res}, Flags);
8442 const uint64_t TwoE31[] = {0x41e0000000000000LL, 0};
8466 {Chain, Src, FltOfs}, Flags);
8470 {Chain, Val}, Flags);
8473 dl, DstVT, Sel, DAG.
getConstant(0, dl, DstVT), SignMask);
8491 if (Subtarget.hasDirectMove() && Subtarget.isPPC64())
8492 return LowerFP_TO_INTDirectMove(
Op, DAG, dl);
8495 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8497 return DAG.
getLoad(
Op.getValueType(), dl, RLI.Chain, RLI.Ptr, RLI.MPI,
8498 RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo, RLI.Ranges);
8509bool PPCTargetLowering::canReuseLoadAddress(
SDValue Op,
EVT MemVT,
8514 if (
Op->isStrictFPOpcode())
8519 (Subtarget.hasFPCVT() ||
Op.getValueType() == MVT::i32);
8523 Op.getOperand(0).getValueType())) {
8525 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8530 if (!LD ||
LD->getExtensionType() != ET ||
LD->isVolatile() ||
8531 LD->isNonTemporal())
8533 if (
LD->getMemoryVT() != MemVT)
8543 RLI.Ptr =
LD->getBasePtr();
8544 if (
LD->isIndexed() && !
LD->getOffset().isUndef()) {
8546 "Non-pre-inc AM on PPC?");
8551 RLI.Chain =
LD->getChain();
8552 RLI.MPI =
LD->getPointerInfo();
8553 RLI.IsDereferenceable =
LD->isDereferenceable();
8554 RLI.IsInvariant =
LD->isInvariant();
8555 RLI.Alignment =
LD->getAlign();
8556 RLI.AAInfo =
LD->getAAInfo();
8557 RLI.Ranges =
LD->getRanges();
8559 RLI.ResChain =
SDValue(LD,
LD->isIndexed() ? 2 : 1);
8566bool PPCTargetLowering::directMoveIsProfitable(
const SDValue &
Op)
const {
8567 SDNode *Origin =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0).getNode();
8574 if (!Subtarget.hasP9Vector() &&
8578 for (SDUse &Use : Origin->
uses()) {
8581 if (
Use.getResNo() != 0)
8608 bool IsSingle =
Op.getValueType() == MVT::f32 && Subtarget.hasFPCVT();
8609 unsigned ConvOpc = IsSingle ? (IsSigned ? PPCISD::FCFIDS : PPCISD::FCFIDUS)
8610 : (IsSigned ? PPCISD::FCFID : PPCISD::FCFIDU);
8611 EVT ConvTy = IsSingle ? MVT::f32 : MVT::f64;
8612 if (
Op->isStrictFPOpcode()) {
8614 Chain =
Op.getOperand(0);
8616 DAG.
getVTList(ConvTy, MVT::Other), {Chain, Src}, Flags);
8618 return DAG.
getNode(ConvOpc, dl, ConvTy, Src);
8626 const SDLoc &dl)
const {
8627 assert((
Op.getValueType() == MVT::f32 ||
8628 Op.getValueType() == MVT::f64) &&
8629 "Invalid floating point type as target of conversion");
8630 assert(Subtarget.hasFPCVT() &&
8631 "Int to FP conversions with direct moves require FPCVT");
8632 SDValue Src =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0);
8633 bool WordInt = Src.getSimpleValueType().SimpleTy == MVT::i32;
8636 unsigned MovOpc = (WordInt && !
Signed) ? PPCISD::MTVSRZ : PPCISD::MTVSRA;
8655 for (
unsigned i = 1; i < NumConcat; ++i)
8662 const SDLoc &dl)
const {
8663 bool IsStrict =
Op->isStrictFPOpcode();
8664 unsigned Opc =
Op.getOpcode();
8665 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8668 "Unexpected conversion type");
8669 assert((
Op.getValueType() == MVT::v2f64 ||
Op.getValueType() == MVT::v4f32) &&
8670 "Supports conversions to v2f64/v4f32 only.");
8674 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8677 bool FourEltRes =
Op.getValueType() == MVT::v4f32;
8682 MVT IntermediateVT = FourEltRes ? MVT::v4i32 : MVT::v2i64;
8684 SmallVector<int, 16> ShuffV;
8685 for (
unsigned i = 0; i < WideNumElts; ++i)
8688 int Stride = FourEltRes ? WideNumElts / 4 : WideNumElts / 2;
8689 int SaveElts = FourEltRes ? 4 : 2;
8690 if (Subtarget.isLittleEndian())
8691 for (
int i = 0; i < SaveElts; i++)
8692 ShuffV[i * Stride] = i;
8694 for (
int i = 1; i <= SaveElts; i++)
8695 ShuffV[i * Stride - 1] = i - 1;
8703 Arrange = DAG.
getBitcast(IntermediateVT, Arrange);
8704 EVT ExtVT = Src.getValueType();
8705 if (Subtarget.hasP9Altivec())
8716 {Op.getOperand(0), Extend}, Flags);
8718 return DAG.
getNode(
Opc, dl,
Op.getValueType(), Extend);
8726 bool IsStrict =
Op->isStrictFPOpcode();
8727 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8732 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8734 EVT InVT = Src.getValueType();
8735 EVT OutVT =
Op.getValueType();
8738 return LowerINT_TO_FPVector(
Op, DAG, dl);
8741 if (
Op.getValueType() == MVT::f128)
8742 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8745 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
8748 if (Src.getValueType() == MVT::i1) {
8760 if (Subtarget.hasDirectMove() && directMoveIsProfitable(
Op) &&
8761 Subtarget.isPPC64() && Subtarget.hasFPCVT())
8762 return LowerINT_TO_FPDirectMove(
Op, DAG, dl);
8764 assert((IsSigned || Subtarget.hasFPCVT()) &&
8765 "UINT_TO_FP is supported only with FPCVT");
8767 if (Src.getValueType() == MVT::i64) {
8782 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT() &&
8783 !
Op->getFlags().hasApproximateFuncs()) {
8823 if (canReuseLoadAddress(SINT, MVT::i64, RLI, DAG)) {
8824 Bits = DAG.
getLoad(MVT::f64, dl, RLI.Chain, RLI.Ptr, RLI.MPI,
8825 RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo, RLI.Ranges);
8828 }
else if (Subtarget.hasLFIWAX() &&
8829 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::SEXTLOAD)) {
8830 MachineMemOperand *MMO =
8832 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8836 Ops, MVT::i32, MMO);
8839 }
else if (Subtarget.hasFPCVT() &&
8840 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::ZEXTLOAD)) {
8841 MachineMemOperand *MMO =
8843 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8847 Ops, MVT::i32, MMO);
8850 }
else if (((Subtarget.hasLFIWAX() &&
8852 (Subtarget.hasFPCVT() &&
8867 "Expected an i32 store");
8873 RLI.Alignment =
Align(4);
8875 MachineMemOperand *MMO =
8877 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8880 PPCISD::LFIWZX : PPCISD::LFIWAX,
8881 dl, DAG.
getVTList(MVT::f64, MVT::Other),
8882 Ops, MVT::i32, MMO);
8883 Chain =
Bits.getValue(1);
8891 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
8895 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)},
8904 assert(Src.getValueType() == MVT::i32 &&
8905 "Unhandled INT_TO_FP type in custom expander!");
8915 if (Subtarget.hasLFIWAX() || Subtarget.hasFPCVT()) {
8918 if (!(ReusingLoad = canReuseLoadAddress(Src, MVT::i32, RLI, DAG))) {
8928 "Expected an i32 store");
8934 RLI.Alignment =
Align(4);
8937 MachineMemOperand *MMO =
8939 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8945 if (ReusingLoad && RLI.ResChain) {
8949 assert(Subtarget.isPPC64() &&
8950 "i32->FP without LFIWAX supported only on PPC64");
8959 Chain, dl, Ext64, FIdx,
8965 MVT::f64, dl, Chain, FIdx,
8974 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
8978 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)}, Flags);
8995 uint64_t
Mode = CVal->getZExtValue();
8996 assert(
Mode < 4 &&
"Unsupported rounding mode!");
8997 unsigned InternalRnd =
Mode ^ (~(
Mode >> 1) & 1);
8998 if (Subtarget.isISA3_0())
9001 PPC::MFFSCRNI, Dl, {MVT::f64, MVT::Other},
9002 {DAG.getConstant(InternalRnd, Dl, MVT::i32, true), Chain}),
9005 (InternalRnd & 2) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
9006 {DAG.
getConstant(30, Dl, MVT::i32,
true), Chain});
9008 (InternalRnd & 1) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
9026 if (!Subtarget.isISA3_0()) {
9027 MFFS = DAG.
getNode(PPCISD::MFFS, Dl, {MVT::f64, MVT::Other}, Chain);
9031 if (Subtarget.isPPC64()) {
9032 if (Subtarget.isISA3_0()) {
9037 PPC::RLDIMI, Dl, MVT::i64,
9042 NewFPSCR =
SDValue(InsertRN, 0);
9049 SDValue Addr = Subtarget.isLittleEndian()
9053 if (Subtarget.isISA3_0()) {
9054 Chain = DAG.
getStore(Chain, Dl, DstFlag, Addr, MachinePointerInfo());
9056 Chain = DAG.
getStore(Chain, Dl, MFFS, StackSlot, MachinePointerInfo());
9058 DAG.
getLoad(MVT::i32, Dl, Chain, Addr, MachinePointerInfo());
9061 PPC::RLWIMI, Dl, MVT::i32,
9062 {Tmp, DstFlag, DAG.getTargetConstant(0, Dl, MVT::i32),
9063 DAG.getTargetConstant(30, Dl, MVT::i32),
9064 DAG.getTargetConstant(31, Dl, MVT::i32)}),
9066 Chain = DAG.
getStore(Chain, Dl, Tmp, Addr, MachinePointerInfo());
9069 DAG.
getLoad(MVT::f64, Dl, Chain, StackSlot, MachinePointerInfo());
9072 if (Subtarget.isISA3_0())
9078 PPC::MTFSF, Dl, MVT::Other,
9106 EVT VT =
Op.getValueType();
9111 SDValue MFFS = DAG.
getNode(PPCISD::MFFS, dl, {MVT::f64, MVT::Other}, Chain);
9122 Chain = DAG.
getStore(Chain, dl, MFFS, StackSlot, MachinePointerInfo());
9126 "Stack slot adjustment is valid only on big endian subtargets!");
9129 CWD = DAG.
getLoad(MVT::i32, dl, Chain, Addr, MachinePointerInfo());
9156 EVT VT =
Op.getValueType();
9160 VT ==
Op.getOperand(1).getValueType() &&
9180 SDValue OutOps[] = { OutLo, OutHi };
9185 EVT VT =
Op.getValueType();
9189 VT ==
Op.getOperand(1).getValueType() &&
9209 SDValue OutOps[] = { OutLo, OutHi };
9215 EVT VT =
Op.getValueType();
9218 VT ==
Op.getOperand(1).getValueType() &&
9238 SDValue OutOps[] = { OutLo, OutHi };
9245 EVT VT =
Op.getValueType();
9252 EVT AmtVT =
Z.getValueType();
9262 X = DAG.
getNode(PPCISD::SHL, dl, VT,
X, IsFSHL ? Z : SubZ);
9263 Y = DAG.
getNode(PPCISD::SRL, dl, VT,
Y, IsFSHL ? SubZ : Z);
9275 static const MVT VTys[] = {
9276 MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
9279 EVT ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1];
9282 if (Val == ((1LLU << (SplatSize * 8)) - 1)) {
9287 EVT CanonicalVT = VTys[SplatSize-1];
9300 const SDLoc &dl,
EVT DestVT = MVT::Other) {
9301 if (DestVT == MVT::Other) DestVT =
Op.getValueType();
9310 EVT DestVT = MVT::Other) {
9311 if (DestVT == MVT::Other) DestVT =
LHS.getValueType();
9320 EVT DestVT = MVT::Other) {
9323 DAG.
getConstant(IID, dl, MVT::i32), Op0, Op1, Op2);
9335 for (
unsigned i = 0; i != 16; ++i)
9356 EVT VecVT = V->getValueType(0);
9357 bool RightType = VecVT == MVT::v2f64 ||
9358 (HasP8Vector && VecVT == MVT::v4f32) ||
9359 (HasDirectMove && (VecVT == MVT::v2i64 || VecVT == MVT::v4i32));
9363 bool IsSplat =
true;
9364 bool IsLoad =
false;
9370 if (V->isConstant())
9372 for (
int i = 0, e = V->getNumOperands(); i < e; ++i) {
9373 if (V->getOperand(i).isUndef())
9377 if (V->getOperand(i).getOpcode() ==
ISD::LOAD ||
9379 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD) ||
9381 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD) ||
9383 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD))
9387 if (V->getOperand(i) != Op0 ||
9388 (!IsLoad && !V->isOnlyUserOf(V->getOperand(i).getNode())))
9391 return !(IsSplat && IsLoad);
9401 (
Op.getValueType() != MVT::f128))
9406 if ((
Lo.getValueType() != MVT::i64) || (
Hi.getValueType() != MVT::i64))
9409 if (!Subtarget.isLittleEndian())
9412 return DAG.
getNode(PPCISD::BUILD_FP128, dl, MVT::f128,
Lo,
Hi);
9420 InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED) {
9421 IsPermuted = InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED;
9434 APFloat APFloatToConvert = ArgAPFloat;
9435 bool LosesInfo =
true;
9440 ArgAPFloat = APFloatToConvert;
9462 APFloat APFloatToConvert = ArgAPFloat;
9463 bool LosesInfo =
true;
9467 return (!LosesInfo && !APFloatToConvert.
isDenormal());
9476 EVT Ty =
Op->getValueType(0);
9479 if ((Ty == MVT::v2f64 || Ty == MVT::v4f32 || Ty == MVT::v4i32) &&
9488 if ((Ty == MVT::v8i16 || Ty == MVT::v16i8) &&
ISD::isEXTLoad(InputNode) &&
9492 if (Ty == MVT::v2i64) {
9495 if (MemVT == MVT::i32) {
9497 Opcode = PPCISD::ZEXT_LD_SPLAT;
9499 Opcode = PPCISD::SEXT_LD_SPLAT;
9507 bool IsLittleEndian) {
9513 APInt ConstValue(VTSize, 0);
9517 unsigned BitPos = 0;
9525 ConstValue.
insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth),
9526 IsLittleEndian ? BitPos : VTSize - EltWidth - BitPos);
9530 for (
unsigned J = 0; J < 16; ++J) {
9532 if (ExtractValue != 0x00 && ExtractValue != 0xFF)
9534 if (ExtractValue == 0xFF)
9549 assert(BVN &&
"Expected a BuildVectorSDNode in LowerBUILD_VECTOR");
9551 if (Subtarget.hasP10Vector()) {
9552 APInt BitMask(32, 0);
9558 BitMask != 0 && BitMask != 0xffff) {
9560 MachineSDNode *MSDNode =
9572 if (
SDValue VecPat = combineBVLoadsSpecialValue(
Op, DAG))
9576 APInt APSplatBits, APSplatUndef;
9577 unsigned SplatBitSize;
9579 bool BVNIsConstantSplat =
9581 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
9587 if (BVNIsConstantSplat && (SplatBitSize == 64) &&
9588 Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
9591 if ((
Op->getValueType(0) == MVT::v2f64) &&
9594 PPCISD::XXSPLTI_SP_TO_DP, dl, MVT::v2f64,
9610 PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9616 DAG.
getNode(PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9624 bool IsSplat64 =
false;
9625 uint64_t SplatBits = 0;
9626 int32_t SextVal = 0;
9627 if (BVNIsConstantSplat && SplatBitSize <= 64) {
9629 if (SplatBitSize <= 32) {
9631 }
else if (SplatBitSize == 64 && Subtarget.hasP8Altivec()) {
9632 int64_t Splat64Val =
static_cast<int64_t
>(SplatBits);
9633 bool P9Vector = Subtarget.hasP9Vector();
9634 int32_t
Hi = P9Vector ? 127 : 15;
9635 int32_t
Lo = P9Vector ? -128 : -16;
9636 IsSplat64 = Splat64Val >=
Lo && Splat64Val <=
Hi;
9637 SextVal =
static_cast<int32_t
>(SplatBits);
9641 if (!BVNIsConstantSplat || (SplatBitSize > 32 && !IsSplat64)) {
9642 unsigned NewOpcode = PPCISD::LD_SPLAT;
9648 const SDValue *InputLoad = &
Op.getOperand(0);
9653 unsigned MemorySize =
LD->getMemoryVT().getScalarSizeInBits();
9654 unsigned ElementSize =
9655 MemorySize * ((NewOpcode == PPCISD::LD_SPLAT) ? 1 : 2);
9657 assert(((ElementSize == 2 * MemorySize)
9658 ? (NewOpcode == PPCISD::ZEXT_LD_SPLAT ||
9659 NewOpcode == PPCISD::SEXT_LD_SPLAT)
9660 : (NewOpcode == PPCISD::LD_SPLAT)) &&
9661 "Unmatched element size and opcode!\n");
9666 unsigned NumUsesOfInputLD = 128 / ElementSize;
9668 if (BVInOp.isUndef())
9683 if (NumUsesOfInputLD == 1 &&
9684 (
Op->getValueType(0) == MVT::v2i64 && NewOpcode != PPCISD::LD_SPLAT &&
9685 !Subtarget.isLittleEndian() && Subtarget.hasVSX() &&
9686 Subtarget.hasLFIWAX()))
9694 if (NumUsesOfInputLD == 1 && Subtarget.isLittleEndian() &&
9695 Subtarget.isISA3_1() && ElementSize <= 16)
9698 assert(NumUsesOfInputLD > 0 &&
"No uses of input LD of a build_vector?");
9700 Subtarget.hasVSX()) {
9707 NewOpcode, dl, DAG.
getVTList(
Op.getValueType(), MVT::Other),
Ops,
9708 LD->getMemoryVT(),
LD->getMemOperand());
9720 if (Subtarget.hasVSX() && Subtarget.isPPC64() &&
9722 Subtarget.hasP8Vector()))
9728 unsigned SplatSize = SplatBitSize / 8;
9733 if (SplatBits == 0) {
9735 if (
Op.getValueType() != MVT::v4i32 || HasAnyUndefs) {
9747 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 2)
9749 Op.getValueType(), DAG, dl);
9751 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 4)
9756 if (Subtarget.hasP9Vector() && SplatSize == 1)
9762 if (SextVal >= -16 && SextVal <= 15) {
9765 unsigned UseSize = SplatSize == 8 ? 4 : SplatSize;
9775 if (Subtarget.hasP9Vector() && SextVal >= -128 && SextVal <= 127) {
9781 switch (SplatSize) {
9785 IID = Intrinsic::ppc_altivec_vupklsb;
9789 IID = Intrinsic::ppc_altivec_vextsb2w;
9793 IID = Intrinsic::ppc_altivec_vextsb2d;
9800 assert(!IsSplat64 &&
"Unhandled 64-bit splat pattern");
9809 if (SextVal >= -32 && SextVal <= 31) {
9814 EVT VT = (SplatSize == 1 ? MVT::v16i8 :
9815 (SplatSize == 2 ? MVT::v8i16 : MVT::v4i32));
9818 if (VT ==
Op.getValueType())
9827 if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) {
9841 static const signed char SplatCsts[] = {
9842 -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
9843 -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
9846 for (
unsigned idx = 0; idx < std::size(SplatCsts); ++idx) {
9849 int i = SplatCsts[idx];
9853 unsigned TypeShiftAmt = i & (SplatBitSize-1);
9856 if (SextVal == (
int)((
unsigned)i << TypeShiftAmt)) {
9858 static const unsigned IIDs[] = {
9859 Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
9860 Intrinsic::ppc_altivec_vslw
9867 if (SextVal == (
int)((
unsigned)i >> TypeShiftAmt)) {
9869 static const unsigned IIDs[] = {
9870 Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
9871 Intrinsic::ppc_altivec_vsrw
9878 if (SextVal == (
int)(((
unsigned)i << TypeShiftAmt) |
9879 ((
unsigned)i >> (SplatBitSize-TypeShiftAmt)))) {
9881 static const unsigned IIDs[] = {
9882 Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0,
9883 Intrinsic::ppc_altivec_vrlw
9890 if (SextVal == (
int)(((
unsigned)i << 8) | (i < 0 ? 0xFF : 0))) {
9892 unsigned Amt = Subtarget.isLittleEndian() ? 15 : 1;
9896 if (SextVal == (
int)(((
unsigned)i << 16) | (i < 0 ? 0xFFFF : 0))) {
9898 unsigned Amt = Subtarget.isLittleEndian() ? 14 : 2;
9902 if (SextVal == (
int)(((
unsigned)i << 24) | (i < 0 ? 0xFFFFFF : 0))) {
9904 unsigned Amt = Subtarget.isLittleEndian() ? 13 : 3;
9917 unsigned OpNum = (PFEntry >> 26) & 0x0F;
9918 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
9919 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
9935 if (LHSID == (1*9+2)*9+3)
return LHS;
9936 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
9948 ShufIdxs[ 0] = 0; ShufIdxs[ 1] = 1; ShufIdxs[ 2] = 2; ShufIdxs[ 3] = 3;
9949 ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19;
9950 ShufIdxs[ 8] = 4; ShufIdxs[ 9] = 5; ShufIdxs[10] = 6; ShufIdxs[11] = 7;
9951 ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23;
9954 ShufIdxs[ 0] = 8; ShufIdxs[ 1] = 9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11;
9955 ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27;
9956 ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15;
9957 ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31;
9960 for (
unsigned i = 0; i != 16; ++i)
9961 ShufIdxs[i] = (i&3)+0;
9964 for (
unsigned i = 0; i != 16; ++i)
9965 ShufIdxs[i] = (i&3)+4;
9968 for (
unsigned i = 0; i != 16; ++i)
9969 ShufIdxs[i] = (i&3)+8;
9972 for (
unsigned i = 0; i != 16; ++i)
9973 ShufIdxs[i] = (i&3)+12;
9994 const unsigned BytesInVector = 16;
9995 bool IsLE = Subtarget.isLittleEndian();
9999 unsigned ShiftElts = 0, InsertAtByte = 0;
10003 unsigned LittleEndianShifts[] = {8, 7, 6, 5, 4, 3, 2, 1,
10004 0, 15, 14, 13, 12, 11, 10, 9};
10005 unsigned BigEndianShifts[] = {9, 10, 11, 12, 13, 14, 15, 0,
10006 1, 2, 3, 4, 5, 6, 7, 8};
10008 ArrayRef<int>
Mask =
N->getMask();
10009 int OriginalOrder[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
10021 bool FoundCandidate =
false;
10025 unsigned VINSERTBSrcElem = IsLE ? 8 : 7;
10028 for (
unsigned i = 0; i < BytesInVector; ++i) {
10029 unsigned CurrentElement =
Mask[i];
10032 if (V2.
isUndef() && CurrentElement != VINSERTBSrcElem)
10035 bool OtherElementsInOrder =
true;
10038 for (
unsigned j = 0;
j < BytesInVector; ++
j) {
10045 (!V2.
isUndef() && CurrentElement < BytesInVector) ? BytesInVector : 0;
10046 if (Mask[j] != OriginalOrder[j] + MaskOffset) {
10047 OtherElementsInOrder =
false;
10054 if (OtherElementsInOrder) {
10061 ShiftElts = IsLE ? LittleEndianShifts[CurrentElement & 0xF]
10062 : BigEndianShifts[CurrentElement & 0xF];
10063 Swap = CurrentElement < BytesInVector;
10065 InsertAtByte = IsLE ? BytesInVector - (i + 1) : i;
10066 FoundCandidate =
true;
10071 if (!FoundCandidate)
10081 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10083 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8, V1, Shl,
10086 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8, V1, V2,
10095 const unsigned NumHalfWords = 8;
10096 const unsigned BytesInVector = NumHalfWords * 2;
10101 bool IsLE = Subtarget.isLittleEndian();
10105 unsigned ShiftElts = 0, InsertAtByte = 0;
10109 unsigned LittleEndianShifts[] = {4, 3, 2, 1, 0, 7, 6, 5};
10110 unsigned BigEndianShifts[] = {5, 6, 7, 0, 1, 2, 3, 4};
10113 uint32_t OriginalOrderLow = 0x1234567;
10114 uint32_t OriginalOrderHigh = 0x89ABCDEF;
10117 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10118 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10135 bool FoundCandidate =
false;
10138 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10139 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10141 uint32_t MaskOtherElts = ~(0xF <<
MaskShift);
10142 uint32_t TargetOrder = 0x0;
10149 unsigned VINSERTHSrcElem = IsLE ? 4 : 3;
10150 TargetOrder = OriginalOrderLow;
10154 if (MaskOneElt == VINSERTHSrcElem &&
10155 (Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10156 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10157 FoundCandidate =
true;
10163 (MaskOneElt < NumHalfWords) ? OriginalOrderHigh : OriginalOrderLow;
10165 if ((Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10167 ShiftElts = IsLE ? LittleEndianShifts[MaskOneElt & 0x7]
10168 : BigEndianShifts[MaskOneElt & 0x7];
10169 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10170 Swap = MaskOneElt < NumHalfWords;
10171 FoundCandidate =
true;
10177 if (!FoundCandidate)
10189 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10192 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10197 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10212 auto ShuffleMask = SVN->
getMask();
10227 ShuffleMask = CommutedSV->
getMask();
10236 APInt APSplatValue, APSplatUndef;
10237 unsigned SplatBitSize;
10240 HasAnyUndefs, 0, !Subtarget.isLittleEndian()) ||
10252 bool IsLE = Subtarget.isLittleEndian();
10253 if ((ShuffleMask[0] == 0 && ShuffleMask[8] == 8) &&
10254 (ShuffleMask[4] % 4 == 0 && ShuffleMask[12] % 4 == 0 &&
10255 ShuffleMask[4] > 15 && ShuffleMask[12] > 15))
10257 else if ((ShuffleMask[4] == 4 && ShuffleMask[12] == 12) &&
10258 (ShuffleMask[0] % 4 == 0 && ShuffleMask[8] % 4 == 0 &&
10259 ShuffleMask[0] > 15 && ShuffleMask[8] > 15))
10267 for (; SplatBitSize < 32; SplatBitSize <<= 1)
10268 SplatVal |= (SplatVal << SplatBitSize);
10271 PPCISD::XXSPLTI32DX,
DL, MVT::v2i64, DAG.
getBitcast(MVT::v2i64,
LHS),
10282 assert(
Op.getValueType() == MVT::v1i128 &&
10283 "Only set v1i128 as custom, other type shouldn't reach here!");
10288 if (SHLAmt % 8 == 0) {
10289 std::array<int, 16>
Mask;
10290 std::iota(
Mask.begin(),
Mask.end(), 0);
10291 std::rotate(
Mask.begin(),
Mask.begin() + SHLAmt / 8,
Mask.end());
10320 if (
SDValue NewShuffle = combineVectorShuffle(SVOp, DAG)) {
10325 V1 =
Op.getOperand(0);
10326 V2 =
Op.getOperand(1);
10328 EVT VT =
Op.getValueType();
10329 bool isLittleEndian = Subtarget.isLittleEndian();
10331 unsigned ShiftElts, InsertAtByte;
10337 bool IsPermutedLoad =
false;
10339 if (InputLoad && Subtarget.hasVSX() && V2.
isUndef() &&
10349 if (IsPermutedLoad) {
10350 assert((isLittleEndian || IsFourByte) &&
10351 "Unexpected size for permuted load on big endian target");
10352 SplatIdx += IsFourByte ? 2 : 1;
10353 assert((SplatIdx < (IsFourByte ? 4 : 2)) &&
10354 "Splat of a value outside of the loaded memory");
10359 if ((IsFourByte && Subtarget.hasP9Vector()) || !IsFourByte) {
10362 Offset = isLittleEndian ? (3 - SplatIdx) * 4 : SplatIdx * 4;
10364 Offset = isLittleEndian ? (1 - SplatIdx) * 8 : SplatIdx * 8;
10368 if (
LD->getValueType(0).getSizeInBits() == (IsFourByte ? 32 : 64))
10381 DAG.
getVTList(IsFourByte ? MVT::v4i32 : MVT::v2i64, MVT::Other);
10384 Ops,
LD->getMemoryVT(),
LD->getMemOperand());
10393 if (VT == MVT::v2i64 || VT == MVT::v2f64)
10396 if (Subtarget.hasP9Vector() &&
10406 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv2, Conv2,
10408 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Shl,
10412 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Conv2,
10417 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
10419 if ((SplatInsertNode = lowerToXXSPLTI32DX(SVOp, DAG)))
10420 return SplatInsertNode;
10423 if (Subtarget.hasP9Altivec()) {
10425 if ((NewISDNode = lowerToVINSERTH(SVOp, DAG)))
10428 if ((NewISDNode = lowerToVINSERTB(SVOp, DAG)))
10432 if (Subtarget.hasVSX() &&
10440 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv1, Conv2,
10445 if (Subtarget.hasVSX() &&
10453 SDValue PermDI = DAG.
getNode(PPCISD::XXPERMDI, dl, MVT::v2i64, Conv1, Conv2,
10458 if (Subtarget.hasP9Vector()) {
10478 if (Subtarget.hasVSX()) {
10491 SDValue Swap = DAG.
getNode(PPCISD::SWAP_NO_CHAIN, dl, MVT::v2f64, Conv);
10499 if (V2.isUndef()) {
10512 (Subtarget.hasP8Altivec() && (
10523 unsigned int ShuffleKind = isLittleEndian ? 2 : 0;
10533 (Subtarget.hasP8Altivec() && (
10541 ArrayRef<int> PermMask = SVOp->
getMask();
10544 unsigned PFIndexes[4];
10545 bool isFourElementShuffle =
true;
10546 for (
unsigned i = 0; i != 4 && isFourElementShuffle;
10548 unsigned EltNo = 8;
10549 for (
unsigned j = 0;
j != 4; ++
j) {
10550 if (PermMask[i * 4 + j] < 0)
10553 unsigned ByteSource = PermMask[i * 4 +
j];
10554 if ((ByteSource & 3) != j) {
10555 isFourElementShuffle =
false;
10560 EltNo = ByteSource / 4;
10561 }
else if (EltNo != ByteSource / 4) {
10562 isFourElementShuffle =
false;
10566 PFIndexes[i] = EltNo;
10574 if (isFourElementShuffle) {
10576 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
10577 PFIndexes[2] * 9 + PFIndexes[3];
10580 unsigned Cost = (PFEntry >> 30);
10600 if (V2.isUndef()) V2 = V1;
10602 return LowerVPERM(
Op, DAG, PermMask, VT, V1, V2);
10608 unsigned Opcode = PPCISD::VPERM;
10611 bool NeedSwap =
false;
10612 bool isLittleEndian = Subtarget.isLittleEndian();
10613 bool isPPC64 = Subtarget.isPPC64();
10615 if (Subtarget.hasVSX() && Subtarget.hasP9Vector() &&
10617 LLVM_DEBUG(
dbgs() <<
"At least one of two input vectors are dead - using "
10618 "XXPERM instead\n");
10619 Opcode = PPCISD::XXPERM;
10627 NeedSwap = !NeedSwap;
10662 unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i];
10664 if (V1HasXXSWAPD) {
10667 else if (SrcElt < 16)
10670 if (V2HasXXSWAPD) {
10673 else if (SrcElt > 15)
10682 for (
unsigned j = 0;
j != BytesPerElement; ++
j)
10683 if (isLittleEndian)
10685 DAG.
getConstant(31 - (SrcElt * BytesPerElement + j), dl, MVT::i32));
10688 DAG.
getConstant(SrcElt * BytesPerElement + j, dl, MVT::i32));
10691 if (V1HasXXSWAPD) {
10695 if (V2HasXXSWAPD) {
10700 if (isPPC64 && (V1HasXXSWAPD || V2HasXXSWAPD)) {
10701 if (ValType != MVT::v2f64)
10707 ShufflesHandledWithVPERM++;
10711 if (Opcode == PPCISD::XXPERM) {
10712 dbgs() <<
"Emitting a XXPERM for the following shuffle:\n";
10714 dbgs() <<
"Emitting a VPERM for the following shuffle:\n";
10717 dbgs() <<
"With the following permute control vector:\n";
10721 if (Opcode == PPCISD::XXPERM)
10722 VPermMask = DAG.
getBitcast(MVT::v4i32, VPermMask);
10726 if (isLittleEndian)
10732 VPERMNode = DAG.
getBitcast(ValType, VPERMNode);
10744 switch (IntrinsicID) {
10748 case Intrinsic::ppc_altivec_vcmpbfp_p:
10752 case Intrinsic::ppc_altivec_vcmpeqfp_p:
10756 case Intrinsic::ppc_altivec_vcmpequb_p:
10760 case Intrinsic::ppc_altivec_vcmpequh_p:
10764 case Intrinsic::ppc_altivec_vcmpequw_p:
10768 case Intrinsic::ppc_altivec_vcmpequd_p:
10769 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10775 case Intrinsic::ppc_altivec_vcmpneb_p:
10776 case Intrinsic::ppc_altivec_vcmpneh_p:
10777 case Intrinsic::ppc_altivec_vcmpnew_p:
10778 case Intrinsic::ppc_altivec_vcmpnezb_p:
10779 case Intrinsic::ppc_altivec_vcmpnezh_p:
10780 case Intrinsic::ppc_altivec_vcmpnezw_p:
10781 if (Subtarget.hasP9Altivec()) {
10782 switch (IntrinsicID) {
10785 case Intrinsic::ppc_altivec_vcmpneb_p:
10788 case Intrinsic::ppc_altivec_vcmpneh_p:
10791 case Intrinsic::ppc_altivec_vcmpnew_p:
10794 case Intrinsic::ppc_altivec_vcmpnezb_p:
10797 case Intrinsic::ppc_altivec_vcmpnezh_p:
10800 case Intrinsic::ppc_altivec_vcmpnezw_p:
10808 case Intrinsic::ppc_altivec_vcmpgefp_p:
10812 case Intrinsic::ppc_altivec_vcmpgtfp_p:
10816 case Intrinsic::ppc_altivec_vcmpgtsb_p:
10820 case Intrinsic::ppc_altivec_vcmpgtsh_p:
10824 case Intrinsic::ppc_altivec_vcmpgtsw_p:
10828 case Intrinsic::ppc_altivec_vcmpgtsd_p:
10829 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10835 case Intrinsic::ppc_altivec_vcmpgtub_p:
10839 case Intrinsic::ppc_altivec_vcmpgtuh_p:
10843 case Intrinsic::ppc_altivec_vcmpgtuw_p:
10847 case Intrinsic::ppc_altivec_vcmpgtud_p:
10848 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10855 case Intrinsic::ppc_altivec_vcmpequq:
10856 case Intrinsic::ppc_altivec_vcmpgtsq:
10857 case Intrinsic::ppc_altivec_vcmpgtuq:
10858 if (!Subtarget.isISA3_1())
10860 switch (IntrinsicID) {
10863 case Intrinsic::ppc_altivec_vcmpequq:
10866 case Intrinsic::ppc_altivec_vcmpgtsq:
10869 case Intrinsic::ppc_altivec_vcmpgtuq:
10876 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10877 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10878 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
10879 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
10880 case Intrinsic::ppc_vsx_xvcmpgesp_p:
10881 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
10882 if (Subtarget.hasVSX()) {
10883 switch (IntrinsicID) {
10884 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10887 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10890 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
10893 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
10896 case Intrinsic::ppc_vsx_xvcmpgesp_p:
10899 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
10909 case Intrinsic::ppc_altivec_vcmpbfp:
10912 case Intrinsic::ppc_altivec_vcmpeqfp:
10915 case Intrinsic::ppc_altivec_vcmpequb:
10918 case Intrinsic::ppc_altivec_vcmpequh:
10921 case Intrinsic::ppc_altivec_vcmpequw:
10924 case Intrinsic::ppc_altivec_vcmpequd:
10925 if (Subtarget.hasP8Altivec())
10930 case Intrinsic::ppc_altivec_vcmpneb:
10931 case Intrinsic::ppc_altivec_vcmpneh:
10932 case Intrinsic::ppc_altivec_vcmpnew:
10933 case Intrinsic::ppc_altivec_vcmpnezb:
10934 case Intrinsic::ppc_altivec_vcmpnezh:
10935 case Intrinsic::ppc_altivec_vcmpnezw:
10936 if (Subtarget.hasP9Altivec())
10937 switch (IntrinsicID) {
10940 case Intrinsic::ppc_altivec_vcmpneb:
10943 case Intrinsic::ppc_altivec_vcmpneh:
10946 case Intrinsic::ppc_altivec_vcmpnew:
10949 case Intrinsic::ppc_altivec_vcmpnezb:
10952 case Intrinsic::ppc_altivec_vcmpnezh:
10955 case Intrinsic::ppc_altivec_vcmpnezw:
10962 case Intrinsic::ppc_altivec_vcmpgefp:
10965 case Intrinsic::ppc_altivec_vcmpgtfp:
10968 case Intrinsic::ppc_altivec_vcmpgtsb:
10971 case Intrinsic::ppc_altivec_vcmpgtsh:
10974 case Intrinsic::ppc_altivec_vcmpgtsw:
10977 case Intrinsic::ppc_altivec_vcmpgtsd:
10978 if (Subtarget.hasP8Altivec())
10983 case Intrinsic::ppc_altivec_vcmpgtub:
10986 case Intrinsic::ppc_altivec_vcmpgtuh:
10989 case Intrinsic::ppc_altivec_vcmpgtuw:
10992 case Intrinsic::ppc_altivec_vcmpgtud:
10993 if (Subtarget.hasP8Altivec())
10998 case Intrinsic::ppc_altivec_vcmpequq_p:
10999 case Intrinsic::ppc_altivec_vcmpgtsq_p:
11000 case Intrinsic::ppc_altivec_vcmpgtuq_p:
11001 if (!Subtarget.isISA3_1())
11003 switch (IntrinsicID) {
11006 case Intrinsic::ppc_altivec_vcmpequq_p:
11009 case Intrinsic::ppc_altivec_vcmpgtsq_p:
11012 case Intrinsic::ppc_altivec_vcmpgtuq_p:
11026 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11032 auto MapNodeWithSplatVector =
11033 [&](
unsigned Opcode,
11034 std::initializer_list<SDValue> ExtraOps = {}) ->
SDValue {
11039 Ops.append(ExtraOps.begin(), ExtraOps.end());
11040 return DAG.
getNode(Opcode, dl, MVT::v16i8,
Ops);
11043 switch (IntrinsicID) {
11044 case Intrinsic::thread_pointer:
11046 if (Subtarget.isPPC64())
11050 case Intrinsic::ppc_rldimi: {
11051 assert(Subtarget.isPPC64() &&
"rldimi is only available in 64-bit!");
11053 APInt
Mask =
Op.getConstantOperandAPInt(4);
11055 return Op.getOperand(2);
11056 if (
Mask.isAllOnes())
11058 uint64_t SH =
Op.getConstantOperandVal(3);
11059 unsigned MB = 0, ME = 0;
11063 if (ME < 63 - SH) {
11066 }
else if (ME > 63 - SH) {
11072 {Op.getOperand(2), Src,
11073 DAG.getTargetConstant(63 - ME, dl, MVT::i32),
11074 DAG.getTargetConstant(MB, dl, MVT::i32)}),
11078 case Intrinsic::ppc_rlwimi: {
11079 APInt
Mask =
Op.getConstantOperandAPInt(4);
11081 return Op.getOperand(2);
11082 if (
Mask.isAllOnes())
11085 unsigned MB = 0, ME = 0;
11089 PPC::RLWIMI, dl, MVT::i32,
11090 {Op.getOperand(2), Op.getOperand(1), Op.getOperand(3),
11091 DAG.getTargetConstant(MB, dl, MVT::i32),
11092 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11096 case Intrinsic::ppc_bcdshift:
11097 return MapNodeWithSplatVector(PPCISD::BCDSHIFT, {
Op.getOperand(3)});
11098 case Intrinsic::ppc_bcdshiftround:
11099 return MapNodeWithSplatVector(PPCISD::BCDSHIFTROUND, {
Op.getOperand(3)});
11100 case Intrinsic::ppc_bcdtruncate:
11101 return MapNodeWithSplatVector(PPCISD::BCDTRUNC, {
Op.getOperand(3)});
11102 case Intrinsic::ppc_bcdunsignedtruncate:
11103 return MapNodeWithSplatVector(PPCISD::BCDUTRUNC);
11104 case Intrinsic::ppc_bcdunsignedshift:
11105 return MapNodeWithSplatVector(PPCISD::BCDUSHIFT);
11107 case Intrinsic::ppc_rlwnm: {
11108 if (
Op.getConstantOperandVal(3) == 0)
11110 unsigned MB = 0, ME = 0;
11115 {Op.getOperand(1), Op.getOperand(2),
11116 DAG.getTargetConstant(MB, dl, MVT::i32),
11117 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11121 case Intrinsic::ppc_mma_disassemble_acc: {
11122 if (Subtarget.isISAFuture()) {
11123 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11134 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11135 Subtarget.isLittleEndian() ? Value2 :
Value,
11136 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11140 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11141 Subtarget.isLittleEndian() ? Value2 :
Value,
11142 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11146 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11147 Subtarget.isLittleEndian() ?
Value : Value2,
11148 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11152 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11153 Subtarget.isLittleEndian() ?
Value : Value2,
11154 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11161 case Intrinsic::ppc_vsx_disassemble_pair: {
11164 if (IntrinsicID == Intrinsic::ppc_mma_disassemble_acc) {
11166 WideVec = DAG.
getNode(PPCISD::XXMFACC, dl, MVT::v512i1, WideVec);
11169 for (
int VecNo = 0; VecNo < NumVecs; VecNo++) {
11171 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8, WideVec,
11172 DAG.
getConstant(Subtarget.isLittleEndian() ? NumVecs - 1 - VecNo
11180 case Intrinsic::ppc_mma_build_dmr: {
11183 for (
int i = 1; i < 9; i += 2) {
11191 DAG.
getNode(PPCISD::PAIR_BUILD, dl, MVT::v256i1, {Hi, Lo}));
11198 case Intrinsic::ppc_mma_dmxxextfdmr512: {
11199 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr512 requires ISA Future");
11201 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11202 "Specify P of 0 or 1 for lower or upper 512 bytes");
11203 unsigned HiLo = Idx->getSExtValue();
11207 Opcode = PPC::DMXXEXTFDMR512;
11208 Subx = PPC::sub_wacc_lo;
11210 Opcode = PPC::DMXXEXTFDMR512_HI;
11211 Subx = PPC::sub_wacc_hi;
11214 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
11218 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11222 case Intrinsic::ppc_mma_dmxxextfdmr256: {
11223 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr256 requires ISA Future");
11225 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11226 "Specify a dmr row pair 0-3");
11227 unsigned IdxVal = Idx->getSExtValue();
11231 Subx = PPC::sub_dmrrowp0;
11234 Subx = PPC::sub_dmrrowp1;
11237 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11240 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11244 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v256i1,
11250 DAG.
getMachineNode(PPC::DMXXEXTFDMR256, dl, MVT::v256i1, {Subreg, P}),
11254 case Intrinsic::ppc_mma_dmxxinstdmr512: {
11255 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr512 requires ISA Future");
11257 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11258 "Specify P of 0 or 1 for lower or upper 512 bytes");
11259 unsigned HiLo = Idx->getSExtValue();
11263 Opcode = PPCISD::INST512;
11264 Subx = PPC::sub_wacc_lo;
11266 Opcode = PPCISD::INST512HI;
11267 Subx = PPC::sub_wacc_hi;
11277 case Intrinsic::ppc_mma_dmxxinstdmr256: {
11278 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr256 requires ISA Future");
11280 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11281 "Specify a dmr row pair 0-3");
11282 unsigned IdxVal = Idx->getSExtValue();
11286 Subx = PPC::sub_dmrrowp0;
11289 Subx = PPC::sub_dmrrowp1;
11292 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11295 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11301 DAG.
getNode(PPCISD::INST256, dl, MVT::v256i1,
Op.getOperand(2),
P);
11303 Op.getOperand(1), DMRRowp,
SubReg),
11307 case Intrinsic::ppc_mma_xxmfacc:
11308 case Intrinsic::ppc_mma_xxmtacc: {
11310 if (!Subtarget.isISAFuture())
11321 case Intrinsic::ppc_unpack_longdouble: {
11323 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11324 "Argument of long double unpack must be 0 or 1!");
11327 Idx->getValueType(0)));
11330 case Intrinsic::ppc_compare_exp_lt:
11331 case Intrinsic::ppc_compare_exp_gt:
11332 case Intrinsic::ppc_compare_exp_eq:
11333 case Intrinsic::ppc_compare_exp_uo: {
11335 switch (IntrinsicID) {
11336 case Intrinsic::ppc_compare_exp_lt:
11339 case Intrinsic::ppc_compare_exp_gt:
11342 case Intrinsic::ppc_compare_exp_eq:
11345 case Intrinsic::ppc_compare_exp_uo:
11351 PPC::SELECT_CC_I4, dl, MVT::i32,
11352 {SDValue(DAG.getMachineNode(PPC::XSCMPEXPDP, dl, MVT::i32,
11353 Op.getOperand(1), Op.getOperand(2)),
11355 DAG.getConstant(1, dl, MVT::i32), DAG.getConstant(0, dl, MVT::i32),
11356 DAG.getTargetConstant(Pred, dl, MVT::i32)}),
11359 case Intrinsic::ppc_test_data_class: {
11360 EVT OpVT =
Op.getOperand(1).getValueType();
11361 unsigned CmprOpc = OpVT == MVT::f128 ? PPC::XSTSTDCQP
11362 : (OpVT == MVT::f64 ? PPC::XSTSTDCDP
11366 PPC::SELECT_CC_I4, dl, MVT::i32,
11367 {SDValue(DAG.getMachineNode(CmprOpc, dl, MVT::i32, Op.getOperand(2),
11370 DAG.getConstant(1, dl, MVT::i32), DAG.getConstant(0, dl, MVT::i32),
11371 DAG.getTargetConstant(PPC::PRED_EQ, dl, MVT::i32)}),
11374 case Intrinsic::ppc_fnmsub: {
11375 EVT VT =
Op.getOperand(1).getValueType();
11376 if (!Subtarget.hasVSX() || (!Subtarget.hasFloat128() && VT == MVT::f128))
11381 return DAG.
getNode(PPCISD::FNMSUB, dl, VT,
Op.getOperand(1),
11382 Op.getOperand(2),
Op.getOperand(3));
11384 case Intrinsic::ppc_convert_f128_to_ppcf128:
11385 case Intrinsic::ppc_convert_ppcf128_to_f128: {
11386 RTLIB::Libcall LC = IntrinsicID == Intrinsic::ppc_convert_ppcf128_to_f128
11387 ? RTLIB::CONVERT_PPCF128_F128
11388 : RTLIB::CONVERT_F128_PPCF128;
11390 std::pair<SDValue, SDValue>
Result =
11391 makeLibCall(DAG, LC,
Op.getValueType(),
Op.getOperand(1), CallOptions,
11395 case Intrinsic::ppc_maxfe:
11396 case Intrinsic::ppc_maxfl:
11397 case Intrinsic::ppc_maxfs:
11398 case Intrinsic::ppc_minfe:
11399 case Intrinsic::ppc_minfl:
11400 case Intrinsic::ppc_minfs: {
11401 EVT VT =
Op.getValueType();
11404 [VT](
const SDUse &Use) { return Use.getValueType() == VT; }) &&
11405 "ppc_[max|min]f[e|l|s] must have uniform type arguments");
11408 if (IntrinsicID == Intrinsic::ppc_minfe ||
11409 IntrinsicID == Intrinsic::ppc_minfl ||
11410 IntrinsicID == Intrinsic::ppc_minfs)
11431 SDValue Tmp = DAG.
getNode(PPCISD::VCMP, dl,
Op.getOperand(2).getValueType(),
11432 Op.getOperand(1),
Op.getOperand(2),
11443 EVT VTs[] = {
Op.getOperand(2).getValueType(), MVT::Glue };
11451 switch (
Op.getConstantOperandVal(1)) {
11456 Bitx = PPC::sub_eq;
11457 SetOp = PPCISD::SETBC;
11462 Bitx = PPC::sub_eq;
11463 SetOp = PPCISD::SETBCR;
11468 Bitx = PPC::sub_lt;
11469 SetOp = PPCISD::SETBC;
11474 Bitx = PPC::sub_lt;
11475 SetOp = PPCISD::SETBCR;
11480 if (Subtarget.isISA3_1()) {
11485 CR6Reg, SubRegIdx, GlueOp),
11487 return DAG.
getNode(SetOp, dl, MVT::i32, CRBit);
11515 switch (
Op.getConstantOperandVal(ArgStart)) {
11516 case Intrinsic::ppc_cfence: {
11517 assert(ArgStart == 1 &&
"llvm.ppc.cfence must carry a chain argument.");
11518 SDValue Val =
Op.getOperand(ArgStart + 1);
11520 if (Ty == MVT::i128) {
11525 unsigned Opcode = Subtarget.isPPC64() ? PPC::CFENCE8 : PPC::CFENCE;
11528 Opcode,
DL, MVT::Other,
11533 case Intrinsic::ppc_mma_disassemble_dmr: {
11535 Op.getOperand(ArgStart + 1), MachinePointerInfo());
11537 case Intrinsic::ppc_amo_stwat:
11538 case Intrinsic::ppc_amo_stdat: {
11541 SDValue Ptr =
Op.getOperand(ArgStart + 1);
11542 SDValue Val =
Op.getOperand(ArgStart + 2);
11545 return DAG.
getNode(PPCISD::STAT, dl, MVT::Other, Chain, Val, Ptr, FC);
11556 if (!Subtarget.isPPC64())
11564 int VectorIndex = 0;
11565 if (Subtarget.isLittleEndian())
11577 "Expecting an atomic compare-and-swap here.");
11580 EVT MemVT = AtomicNode->getMemoryVT();
11598 for (
int i = 0, e = AtomicNode->getNumOperands(); i < e; i++)
11599 Ops.push_back(AtomicNode->getOperand(i));
11601 MachineMemOperand *MMO = AtomicNode->getMemOperand();
11602 SDVTList Tys = DAG.
getVTList(MVT::i32, MVT::Other);
11604 (MemVT == MVT::i8) ? PPCISD::ATOMIC_CMP_SWAP_8 : PPCISD::ATOMIC_CMP_SWAP_16;
11611 EVT MemVT =
N->getMemoryVT();
11613 "Expect quadword atomic operations");
11615 unsigned Opc =
N->getOpcode();
11620 SDVTList Tys = DAG.
getVTList(MVT::i64, MVT::i64, MVT::Other);
11623 DAG.
getConstant(Intrinsic::ppc_atomic_load_i128, dl, MVT::i32)};
11624 for (
int I = 1,
E =
N->getNumOperands();
I <
E; ++
I)
11625 Ops.push_back(
N->getOperand(
I));
11627 Ops, MemVT,
N->getMemOperand());
11634 DAG.
getNode(
ISD::OR, dl, {MVT::i128, MVT::Other}, {ValLo, ValHi});
11641 SDVTList Tys = DAG.
getVTList(MVT::Other);
11644 DAG.
getConstant(Intrinsic::ppc_atomic_store_i128, dl, MVT::i32)};
11650 Ops.push_back(ValLo);
11651 Ops.push_back(ValHi);
11652 Ops.push_back(
N->getOperand(2));
11654 N->getMemOperand());
11666 enum DataClassMask {
11668 DC_NEG_INF = 1 << 4,
11669 DC_POS_INF = 1 << 5,
11670 DC_NEG_ZERO = 1 << 2,
11671 DC_POS_ZERO = 1 << 3,
11672 DC_NEG_SUBNORM = 1,
11673 DC_POS_SUBNORM = 1 << 1,
11676 EVT VT =
Op.getValueType();
11678 unsigned TestOp = VT == MVT::f128 ? PPC::XSTSTDCQP
11679 : VT == MVT::f64 ? PPC::XSTSTDCDP
11690 return DAG.
getNOT(Dl, Rev, MVT::i1);
11697 TestOp, Dl, MVT::i32,
11699 DC_NEG_ZERO | DC_POS_ZERO |
11700 DC_NEG_SUBNORM | DC_POS_SUBNORM,
11706 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11712 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11717 Sign = DAG.
getNOT(Dl, Sign, MVT::i1);
11730 bool IsQuiet = Mask &
fcQNan;
11736 if (VT == MVT::f128) {
11740 QuietMask = 0x8000;
11741 }
else if (VT == MVT::f64) {
11742 if (Subtarget.isPPC64()) {
11753 QuietMask = 0x80000;
11754 }
else if (VT == MVT::f32) {
11756 QuietMask = 0x400000;
11772 unsigned NativeMask = 0;
11774 NativeMask |= DC_NAN;
11776 NativeMask |= DC_NEG_INF;
11778 NativeMask |= DC_POS_INF;
11780 NativeMask |= DC_NEG_ZERO;
11782 NativeMask |= DC_POS_ZERO;
11784 NativeMask |= DC_NEG_SUBNORM;
11786 NativeMask |= DC_POS_SUBNORM;
11789 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1,
11791 TestOp, Dl, MVT::i32,
11800 assert(Subtarget.hasP9Vector() &&
"Test data class requires Power9");
11802 uint64_t RHSC =
Op.getConstantOperandVal(1);
11805 if (
LHS.getValueType() == MVT::ppcf128) {
11829 bool Future = Subtarget.isISAFuture();
11832 "Mask predication not supported");
11835 unsigned IID = Future ? Intrinsic::ppc_vsx_lxvrl : Intrinsic::ppc_vsx_lxvl;
11836 unsigned EltBits =
Op->getValueType(0).getScalarType().getSizeInBits();
11840 SDVTList Tys = DAG.
getVTList(
Op->getValueType(0), MVT::Other);
11843 VPLD->getMemoryVT(), VPLD->getMemOperand());
11850 "Mask predication not supported");
11855 Op->getOperand(1).getValueType().getScalarType().getSizeInBits();
11856 bool Future = Subtarget.isISAFuture();
11857 unsigned IID = Future ? Intrinsic::ppc_vsx_stxvrl : Intrinsic::ppc_vsx_stxvl;
11860 VPST->getChain(), DAG.
getConstant(IID, dl, MVT::i32),
11863 SDVTList Tys = DAG.
getVTList(MVT::Other);
11866 VPST->getMemoryVT(), VPST->getMemOperand());
11877 unsigned EltSize =
Op.getValueType().getScalarSizeInBits();
11879 int64_t
IntVal =
Op.getConstantOperandVal(0);
11880 if (IntVal >= -16 && IntVal <= 15)
11886 if (Subtarget.hasLFIWAX() && Subtarget.hasVSX() &&
11891 MachineMemOperand *MMO =
11893 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
11896 PPCISD::LD_SPLAT, dl, DAG.
getVTList(MVT::v4i32, MVT::Other),
Ops,
11900 return Bits.getValue(0);
11916 !Subtarget.isLittleEndian() && ValVT.
isInteger() &&
11921 64 -
Op.getValueType().getScalarSizeInBits(), dl, ShiftAmountTy);
11928 return DAG.
getLoad(
Op.getValueType(), dl, Store, FIdx,
11929 MachinePointerInfo());
11936 return DAG.
getLoad(
Op.getValueType(), dl, Store, FIdx, MachinePointerInfo());
11942 "Should only be called for ISD::INSERT_VECTOR_ELT");
11946 EVT VT =
Op.getValueType();
11951 if (VT == MVT::v2f64 &&
C)
11954 if (Subtarget.hasP9Vector()) {
11963 if ((VT == MVT::v4f32) && (V2.
getValueType() == MVT::f32) &&
11969 BitcastLoad,
Op.getOperand(2));
11970 return DAG.
getBitcast(MVT::v4f32, InsVecElt);
11974 if (Subtarget.isISA3_1()) {
11975 if ((VT == MVT::v2i64 || VT == MVT::v2f64) && !Subtarget.isPPC64())
11979 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
11980 VT == MVT::v2i64 || VT == MVT::v4f32 || VT == MVT::v2f64)
11990 if (VT == MVT::v8i16 || VT == MVT::v16i8) {
11993 unsigned InsertAtElement =
C->getZExtValue();
11994 unsigned InsertAtByte = InsertAtElement * BytesInEachElement;
11995 if (Subtarget.isLittleEndian()) {
11996 InsertAtByte = (16 - BytesInEachElement) - InsertAtByte;
11998 return DAG.
getNode(PPCISD::VECINSERT, dl, VT, V1, Mtvsrz,
12010 EVT VT =
Op.getValueType();
12011 bool IsV1024i1 = VT == MVT::v1024i1;
12012 bool IsV2048i1 = VT == MVT::v2048i1;
12016 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12018 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12019 "Dense Math support required.");
12020 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12029 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12030 MachineMemOperand *NewMMO =
12038 DAG.
getVTList(MVT::v256i1, MVT::Other),
12039 LoadOps, MVT::v256i1, NewMMO);
12044 if (Subtarget.isLittleEndian()) {
12045 std::reverse(Loads.
begin(), Loads.
end());
12046 std::reverse(LoadChains.
begin(), LoadChains.
end());
12051 DAG.
getNode(PPCISD::INST512, dl, MVT::v512i1, Loads[0], Loads[1]);
12054 DAG.
getNode(PPCISD::INST512HI, dl, MVT::v512i1, Loads[2], Loads[3]);
12069 DAG.
getNode(PPCISD::INST512, dl, MVT::v512i1, Loads[4], Loads[5]);
12071 DAG.
getNode(PPCISD::INST512HI, dl, MVT::v512i1, Loads[6], Loads[7]);
12072 const SDValue Dmr1Ops[] = {RC, Dmr1Lo, LoSub, Dmr1Hi, HiSub};
12074 DAG.
getMachineNode(PPC::REG_SEQUENCE, dl, MVT::v1024i1, Dmr1Ops), 0);
12080 const SDValue DmrPOps[] = {DmrPRC,
Value, Dmr0Sub, Dmr1Value, Dmr1Sub};
12083 DAG.
getMachineNode(PPC::REG_SEQUENCE, dl, MVT::v2048i1, DmrPOps), 0);
12092 DAG.
getNode(PPCISD::INST512, dl, MVT::v512i1, Pairs[0], Pairs[1]);
12095 DAG.
getNode(PPCISD::INST512HI, dl, MVT::v512i1, Pairs[2], Pairs[3]);
12100 {RC, Lo, LoSub, Hi, HiSub}),
12110 EVT VT =
Op.getValueType();
12112 if (VT == MVT::v1024i1 || VT == MVT::v2048i1)
12113 return LowerDMFVectorLoad(
Op, DAG);
12115 if (VT != MVT::v256i1 && VT != MVT::v512i1)
12121 assert((VT != MVT::v512i1 || Subtarget.hasMMA()) &&
12122 "Type unsupported without MMA");
12123 assert((VT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12124 "Type unsupported without paired vector support");
12129 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12131 DAG.
getLoad(MVT::v16i8, dl, LoadChain, BasePtr,
12140 if (Subtarget.isLittleEndian()) {
12141 std::reverse(Loads.
begin(), Loads.
end());
12142 std::reverse(LoadChains.
begin(), LoadChains.
end());
12146 DAG.
getNode(VT == MVT::v512i1 ? PPCISD::ACC_BUILD : PPCISD::PAIR_BUILD,
12162 bool IsV1024i1 = VT == MVT::v1024i1;
12163 bool IsV2048i1 = VT == MVT::v2048i1;
12167 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12169 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12170 "Dense Math support required.");
12171 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12173 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12176 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12181 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12185 MachineSDNode *ExtNode =
12189 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes,
Hi);
12195 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12201 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12207 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12212 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12217 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12222 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12226 MachineSDNode *ExtNode =
12227 DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr0Lo);
12231 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr0Hi);
12234 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr1Lo);
12238 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr1Hi);
12243 if (Subtarget.isLittleEndian())
12244 std::reverse(Values.
begin(), Values.
end());
12246 SDVTList Tys = DAG.
getVTList(MVT::Other);
12248 StoreChain, DAG.
getConstant(Intrinsic::ppc_vsx_stxvp, dl, MVT::i32),
12252 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12253 MachineMemOperand *NewMMO =
12260 Ops[2] = Values[Idx];
12262 MVT::v256i1, NewMMO);
12278 EVT StoreVT =
Value.getValueType();
12280 if (StoreVT == MVT::v1024i1 || StoreVT == MVT::v2048i1)
12281 return LowerDMFVectorStore(
Op, DAG);
12283 if (StoreVT != MVT::v256i1 && StoreVT != MVT::v512i1)
12289 assert((StoreVT != MVT::v512i1 || Subtarget.hasMMA()) &&
12290 "Type unsupported without MMA");
12291 assert((StoreVT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12292 "Type unsupported without paired vector support");
12295 unsigned NumVecs = 2;
12296 if (StoreVT == MVT::v512i1) {
12297 if (Subtarget.isISAFuture()) {
12298 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12300 PPC::DMXXEXTFDMR512, dl, ReturnTypes,
Op.getOperand(1));
12303 Value2 =
SDValue(ExtNode, 1);
12308 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12309 unsigned VecNum = Subtarget.isLittleEndian() ? NumVecs - 1 - Idx : Idx;
12311 if (Subtarget.isISAFuture()) {
12312 VecNum = Subtarget.isLittleEndian() ? 1 - (Idx % 2) : (Idx % 2);
12313 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
12314 Idx > 1 ? Value2 :
Value,
12317 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
Value,
12321 DAG.
getStore(StoreChain, dl, Elt, BasePtr,
12335 if (
Op.getValueType() == MVT::v4i32) {
12352 LHS,
RHS, DAG, dl, MVT::v4i32);
12355 LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32);
12360 }
else if (
Op.getValueType() == MVT::v16i8) {
12362 bool isLittleEndian = Subtarget.isLittleEndian();
12366 LHS,
RHS, DAG, dl, MVT::v8i16);
12371 LHS,
RHS, DAG, dl, MVT::v8i16);
12379 for (
unsigned i = 0; i != 8; ++i) {
12380 if (isLittleEndian) {
12382 Ops[i*2+1] = 2*i+16;
12385 Ops[i*2+1] = 2*i+1+16;
12388 if (isLittleEndian)
12398 bool IsStrict =
Op->isStrictFPOpcode();
12399 if (
Op.getOperand(IsStrict ? 1 : 0).getValueType() == MVT::f128 &&
12400 !Subtarget.hasP9Vector())
12410 "Should only be called for ISD::FP_EXTEND");
12414 if (
Op.getValueType() != MVT::v2f64 ||
12415 Op.getOperand(0).getValueType() != MVT::v2f32)
12427 "Node should have 2 operands with second one being a constant!");
12439 int DWord = Idx >> 1;
12442 if (Subtarget.isLittleEndian())
12445 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64,
12459 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12461 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12462 LD->getMemoryVT(),
LD->getMemOperand());
12467 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewOp,
12472 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12474 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12475 LD->getMemoryVT(),
LD->getMemOperand());
12476 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewLd,
12487 if (STI.useCRBits())
12504 PPCISD::ADDE,
DL, DAG.
getVTList(SumType, MVT::i32), Zero, Zero, Flag);
12505 if (STI.useCRBits())
12513 SDNode *
N =
Op.getNode();
12514 EVT VT =
N->getValueType(0);
12515 EVT CarryType =
N->getValueType(1);
12516 unsigned Opc =
N->getOpcode();
12518 Opc = IsAdd ? PPCISD::ADDC : PPCISD::SUBC;
12520 N->getOperand(0),
N->getOperand(1));
12532 SDNode *
N =
Op.getNode();
12533 unsigned Opc =
N->getOpcode();
12534 EVT VT =
N->getValueType(0);
12535 EVT CarryType =
N->getValueType(1);
12536 SDValue CarryOp =
N->getOperand(2);
12538 Opc = IsAdd ? PPCISD::ADDE : PPCISD::SUBE;
12544 Op.getOperand(0),
Op.getOperand(1), CarryOp);
12558 EVT VT =
Op.getNode()->getValueType(0);
12584 EVT VT =
Op.getNode()->getValueType(0);
12613 EVT OpVT =
A.getValueType();
12614 EVT ResVT =
Op.getValueType();
12620 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12638 switch (
Op.getOpcode()) {
12658 return LowerSSUBO(
Op, DAG);
12660 return LowerSADDO(
Op, DAG);
12672 return LowerGET_DYNAMIC_AREA_OFFSET(
Op, DAG);
12693 return LowerSET_ROUNDING(
Op, DAG);
12700 case ISD::FSHL:
return LowerFunnelShift(
Op, DAG);
12701 case ISD::FSHR:
return LowerFunnelShift(
Op, DAG);
12713 return LowerFP_ROUND(
Op, DAG);
12727 return LowerINTRINSIC_VOID(
Op, DAG);
12729 return LowerBSWAP(
Op, DAG);
12731 return LowerATOMIC_CMP_SWAP(
Op, DAG);
12733 return LowerATOMIC_LOAD_STORE(
Op, DAG);
12735 return LowerIS_FPCLASS(
Op, DAG);
12738 return LowerADDSUBO(
Op, DAG);
12741 return LowerADDSUBO_CARRY(
Op, DAG);
12743 return LowerUCMP(
Op, DAG);
12749 if (
Op->getFlags().hasNoFPExcept())
12753 return LowerVP_LOAD(
Op, DAG);
12754 case ISD::VP_STORE:
12755 return LowerVP_STORE(
Op, DAG);
12763 switch (
N->getOpcode()) {
12765 llvm_unreachable(
"Do not know how to custom type legalize this operation!");
12782 if (
N->getConstantOperandVal(1) != Intrinsic::loop_decrement)
12785 assert(
N->getValueType(0) == MVT::i1 &&
12786 "Unexpected result type for CTR decrement intrinsic");
12788 N->getValueType(0));
12798 switch (
N->getConstantOperandVal(0)) {
12799 case Intrinsic::ppc_pack_longdouble:
12801 N->getOperand(2),
N->getOperand(1)));
12803 case Intrinsic::ppc_maxfe:
12804 case Intrinsic::ppc_minfe:
12805 case Intrinsic::ppc_fnmsub:
12806 case Intrinsic::ppc_convert_f128_to_ppcf128:
12813 if (!Subtarget.isSVR4ABI() || Subtarget.isPPC64())
12816 EVT VT =
N->getValueType(0);
12818 if (VT == MVT::i64) {
12831 if (
N->getOperand(
N->isStrictFPOpcode() ? 1 : 0).getValueType() ==
12835 Results.push_back(LoweredValue);
12836 if (
N->isStrictFPOpcode())
12841 if (!
N->getValueType(0).isVector())
12874 return Builder.CreateIntrinsic(Id, {});
12880 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
12882 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
12883 "Only 8/16/32/64-bit atomic loads supported");
12889 IntID = Intrinsic::ppc_lbarx;
12890 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
12893 IntID = Intrinsic::ppc_lharx;
12894 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
12897 IntID = Intrinsic::ppc_lwarx;
12900 IntID = Intrinsic::ppc_ldarx;
12904 Builder.CreateIntrinsic(IntID, Addr,
nullptr,
"larx");
12906 return Builder.CreateTruncOrBitCast(
Call, ValueTy);
12917 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
12918 "Only 8/16/32/64-bit atomic loads supported");
12924 IntID = Intrinsic::ppc_stbcx;
12925 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
12928 IntID = Intrinsic::ppc_sthcx;
12929 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
12932 IntID = Intrinsic::ppc_stwcx;
12935 IntID = Intrinsic::ppc_stdcx;
12939 if (SZ == 8 || SZ == 16)
12940 Val = Builder.CreateZExt(Val, Builder.getInt32Ty());
12942 Value *
Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
12944 return Builder.CreateXor(
Call, Builder.getInt32(1));
12967 return Builder.CreateIntrinsic(Intrinsic::ppc_cfence, {Inst->
getType()},
12977 unsigned AtomicSize,
12978 unsigned BinOpcode,
12979 unsigned CmpOpcode,
12980 unsigned CmpPred)
const {
12984 auto LoadMnemonic = PPC::LDARX;
12985 auto StoreMnemonic = PPC::STDCX;
12986 switch (AtomicSize) {
12990 LoadMnemonic = PPC::LBARX;
12991 StoreMnemonic = PPC::STBCX;
12992 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
12995 LoadMnemonic = PPC::LHARX;
12996 StoreMnemonic = PPC::STHCX;
12997 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13000 LoadMnemonic = PPC::LWARX;
13001 StoreMnemonic = PPC::STWCX;
13004 LoadMnemonic = PPC::LDARX;
13005 StoreMnemonic = PPC::STDCX;
13021 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13023 F->insert(It, loopMBB);
13025 F->insert(It, loop2MBB);
13026 F->insert(It, exitMBB);
13032 Register TmpReg = (!BinOpcode) ? incr :
13033 RegInfo.createVirtualRegister( AtomicSize == 8 ? &PPC::G8RCRegClass
13034 : &PPC::GPRCRegClass);
13059 BuildMI(BB, dl,
TII->get(LoadMnemonic), dest)
13064 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13066 if (CmpOpcode == PPC::CMPW && AtomicSize < 4) {
13067 Register ExtReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13068 BuildMI(BB, dl,
TII->get(AtomicSize == 1 ? PPC::EXTSB : PPC::EXTSH),
13098 switch(
MI.getOpcode()) {
13102 return TII->isSignExtended(
MI.getOperand(1).getReg(),
13103 &
MI.getMF()->getRegInfo());
13127 case PPC::EXTSB8_32_64:
13128 case PPC::EXTSB8_rec:
13129 case PPC::EXTSB_rec:
13132 case PPC::EXTSH8_32_64:
13133 case PPC::EXTSH8_rec:
13134 case PPC::EXTSH_rec:
13136 case PPC::EXTSWSLI:
13137 case PPC::EXTSWSLI_32_64:
13138 case PPC::EXTSWSLI_32_64_rec:
13139 case PPC::EXTSWSLI_rec:
13140 case PPC::EXTSW_32:
13141 case PPC::EXTSW_32_64:
13142 case PPC::EXTSW_32_64_rec:
13143 case PPC::EXTSW_rec:
13146 case PPC::SRAWI_rec:
13147 case PPC::SRAW_rec:
13156 unsigned BinOpcode,
unsigned CmpOpcode,
unsigned CmpPred)
const {
13166 bool IsSignExtended =
13169 if (CmpOpcode == PPC::CMPW && !IsSignExtended) {
13170 Register ValueReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13171 BuildMI(*BB,
MI, dl,
TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueReg)
13172 .
addReg(
MI.getOperand(3).getReg());
13173 MI.getOperand(3).setReg(ValueReg);
13177 if (Subtarget.hasPartwordAtomics())
13185 bool is64bit = Subtarget.isPPC64();
13186 bool isLittleEndian = Subtarget.isLittleEndian();
13187 unsigned ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
13198 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13200 F->insert(It, loopMBB);
13202 F->insert(It, loop2MBB);
13203 F->insert(It, exitMBB);
13209 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13212 Register PtrReg = RegInfo.createVirtualRegister(RC);
13213 Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
13215 isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
13216 Register Incr2Reg = RegInfo.createVirtualRegister(GPRC);
13217 Register MaskReg = RegInfo.createVirtualRegister(GPRC);
13218 Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
13219 Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
13220 Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
13221 Register Tmp3Reg = RegInfo.createVirtualRegister(GPRC);
13222 Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
13223 Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
13224 Register SrwDestReg = RegInfo.createVirtualRegister(GPRC);
13227 (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(GPRC);
13254 if (ptrA != ZeroReg) {
13255 Ptr1Reg = RegInfo.createVirtualRegister(RC);
13256 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
13264 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
13265 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
13268 .
addImm(is8bit ? 28 : 27);
13269 if (!isLittleEndian)
13270 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
13272 .
addImm(is8bit ? 24 : 16);
13274 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
13279 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
13289 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
13293 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
13298 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
13302 BuildMI(BB, dl,
TII->get(BinOpcode), TmpReg)
13305 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
13312 Register SReg = RegInfo.createVirtualRegister(GPRC);
13313 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13317 unsigned ValueReg = SReg;
13318 unsigned CmpReg = Incr2Reg;
13319 if (CmpOpcode == PPC::CMPW) {
13320 ValueReg = RegInfo.createVirtualRegister(GPRC);
13321 BuildMI(BB, dl,
TII->get(PPC::SRW), ValueReg)
13324 Register ValueSReg = RegInfo.createVirtualRegister(GPRC);
13325 BuildMI(BB, dl,
TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueSReg)
13327 ValueReg = ValueSReg;
13359 .
addImm(is8bit ? 24 : 16)
13380 Register DstReg =
MI.getOperand(0).getReg();
13382 assert(
TRI->isTypeLegalForClass(*RC, MVT::i32) &&
"Invalid destination!");
13383 Register mainDstReg =
MRI.createVirtualRegister(RC);
13384 Register restoreDstReg =
MRI.createVirtualRegister(RC);
13387 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13388 "Invalid Pointer Size!");
13436 Register LabelReg =
MRI.createVirtualRegister(PtrRC);
13437 Register BufReg =
MI.getOperand(1).getReg();
13439 if (Subtarget.is64BitELFABI()) {
13452 BaseReg = Subtarget.isPPC64() ? PPC::X1 : PPC::R1;
13454 BaseReg = Subtarget.isPPC64() ? PPC::BP8 : PPC::BP;
13457 TII->get(Subtarget.isPPC64() ? PPC::STD : PPC::STW))
13480 TII->get(Subtarget.isPPC64() ? PPC::MFLR8 : PPC::MFLR), LabelReg);
13483 if (Subtarget.isPPC64()) {
13501 TII->get(PPC::PHI), DstReg)
13505 MI.eraseFromParent();
13519 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13520 "Invalid Pointer Size!");
13523 (PVT == MVT::i64) ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13526 unsigned FP = (PVT == MVT::i64) ? PPC::X31 : PPC::R31;
13527 unsigned SP = (PVT == MVT::i64) ? PPC::X1 : PPC::R1;
13541 Register BufReg =
MI.getOperand(0).getReg();
13546 if (PVT == MVT::i64) {
13558 if (PVT == MVT::i64) {
13570 if (PVT == MVT::i64) {
13582 if (PVT == MVT::i64) {
13594 if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) {
13604 TII->get(PVT == MVT::i64 ? PPC::MTCTR8 : PPC::MTCTR)).
addReg(Tmp);
13607 MI.eraseFromParent();
13623 "Unexpected stack alignment");
13627 unsigned StackProbeSize =
13630 StackProbeSize &= ~(StackAlign - 1);
13631 return StackProbeSize ? StackProbeSize : StackAlign;
13643 const bool isPPC64 = Subtarget.isPPC64();
13675 MF->
insert(MBBIter, TestMBB);
13676 MF->
insert(MBBIter, BlockMBB);
13677 MF->
insert(MBBIter, TailMBB);
13682 Register DstReg =
MI.getOperand(0).getReg();
13683 Register NegSizeReg =
MI.getOperand(1).getReg();
13685 Register FinalStackPtr =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13686 Register FramePointer =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13687 Register ActualNegSizeReg =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13693 if (!
MRI.hasOneNonDBGUse(NegSizeReg))
13695 isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_64 : PPC::PREPARE_PROBED_ALLOCA_32;
13701 ProbeOpc = isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_64
13702 : PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_32;
13704 .
addDef(ActualNegSizeReg)
13706 .
add(
MI.getOperand(2))
13707 .
add(
MI.getOperand(3));
13713 .
addReg(ActualNegSizeReg);
13716 int64_t NegProbeSize = -(int64_t)ProbeSize;
13718 Register ScratchReg =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13720 Register TempReg =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13722 .
addImm(NegProbeSize >> 16);
13726 .
addImm(NegProbeSize & 0xFFFF);
13733 Register Div =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13735 .
addReg(ActualNegSizeReg)
13737 Register Mul =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13741 Register NegMod =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13744 .
addReg(ActualNegSizeReg);
13753 Register CmpResult =
MRI.createVirtualRegister(&PPC::CRRCRegClass);
13754 BuildMI(TestMBB,
DL,
TII->get(isPPC64 ? PPC::CMPD : PPC::CMPW), CmpResult)
13779 MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13781 TII->get(isPPC64 ? PPC::DYNAREAOFFSET8 : PPC::DYNAREAOFFSET),
13782 MaxCallFrameSizeReg)
13783 .
add(
MI.getOperand(2))
13784 .
add(
MI.getOperand(3));
13785 BuildMI(TailMBB,
DL,
TII->get(isPPC64 ? PPC::ADD8 : PPC::ADD4), DstReg)
13787 .
addReg(MaxCallFrameSizeReg);
13793 MBB->addSuccessor(TestMBB);
13796 MI.eraseFromParent();
13798 ++NumDynamicAllocaProbed;
13803 switch (
MI.getOpcode()) {
13804 case PPC::SELECT_CC_I4:
13805 case PPC::SELECT_CC_I8:
13806 case PPC::SELECT_CC_F4:
13807 case PPC::SELECT_CC_F8:
13808 case PPC::SELECT_CC_F16:
13809 case PPC::SELECT_CC_VRRC:
13810 case PPC::SELECT_CC_VSFRC:
13811 case PPC::SELECT_CC_VSSRC:
13812 case PPC::SELECT_CC_VSRC:
13813 case PPC::SELECT_CC_SPE4:
13814 case PPC::SELECT_CC_SPE:
13822 switch (
MI.getOpcode()) {
13823 case PPC::SELECT_I4:
13824 case PPC::SELECT_I8:
13825 case PPC::SELECT_F4:
13826 case PPC::SELECT_F8:
13827 case PPC::SELECT_F16:
13828 case PPC::SELECT_SPE:
13829 case PPC::SELECT_SPE4:
13830 case PPC::SELECT_VRRC:
13831 case PPC::SELECT_VSFRC:
13832 case PPC::SELECT_VSSRC:
13833 case PPC::SELECT_VSRC:
13843 if (
MI.getOpcode() == TargetOpcode::STACKMAP ||
13844 MI.getOpcode() == TargetOpcode::PATCHPOINT) {
13845 if (Subtarget.is64BitELFABI() &&
13846 MI.getOpcode() == TargetOpcode::PATCHPOINT &&
13847 !Subtarget.isUsingPCRelativeCalls()) {
13859 if (
MI.getOpcode() == PPC::EH_SjLj_SetJmp32 ||
13860 MI.getOpcode() == PPC::EH_SjLj_SetJmp64) {
13862 }
else if (
MI.getOpcode() == PPC::EH_SjLj_LongJmp32 ||
13863 MI.getOpcode() == PPC::EH_SjLj_LongJmp64) {
13877 if (Subtarget.hasISEL() &&
13878 (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
13879 MI.getOpcode() == PPC::SELECT_CC_I8 ||
13880 MI.getOpcode() == PPC::SELECT_I4 ||
MI.getOpcode() == PPC::SELECT_I8)) {
13882 if (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
13883 MI.getOpcode() == PPC::SELECT_CC_I8)
13884 Cond.push_back(
MI.getOperand(4));
13887 Cond.push_back(
MI.getOperand(1));
13890 TII->insertSelect(*BB,
MI, dl,
MI.getOperand(0).getReg(),
Cond,
13891 MI.getOperand(2).getReg(),
MI.getOperand(3).getReg());
13907 F->insert(It, copy0MBB);
13908 F->insert(It, sinkMBB);
13917 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
13932 .
addReg(
MI.getOperand(1).getReg())
13935 unsigned SelectPred =
MI.getOperand(4).getImm();
13938 .
addReg(
MI.getOperand(1).getReg())
13955 .
addReg(
MI.getOperand(3).getReg())
13957 .
addReg(
MI.getOperand(2).getReg())
13959 }
else if (
MI.getOpcode() == PPC::ReadTB) {
13975 F->insert(It, readMBB);
13976 F->insert(It, sinkMBB);
13987 Register ReadAgainReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13995 Register CmpReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13997 BuildMI(BB, dl,
TII->get(PPC::CMPW), CmpReg)
14007 }
else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I8)
14009 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I16)
14011 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I32)
14013 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I64)
14016 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I8)
14018 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I16)
14020 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I32)
14022 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I64)
14025 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I8)
14027 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I16)
14029 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I32)
14031 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I64)
14034 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I8)
14036 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I16)
14038 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I32)
14040 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I64)
14043 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I8)
14045 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I16)
14047 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I32)
14049 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I64)
14052 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I8)
14054 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I16)
14056 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I32)
14058 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I64)
14061 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I8)
14063 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I16)
14065 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I32)
14067 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I64)
14070 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I8)
14072 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I16)
14074 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I32)
14076 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I64)
14079 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I8)
14081 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I16)
14083 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I32)
14085 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I64)
14088 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I8)
14090 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I16)
14092 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I32)
14094 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I64)
14097 else if (
MI.getOpcode() == PPC::ATOMIC_SWAP_I8)
14099 else if (
MI.getOpcode() == PPC::ATOMIC_SWAP_I16)
14101 else if (
MI.getOpcode() == PPC::ATOMIC_SWAP_I32)
14103 else if (
MI.getOpcode() == PPC::ATOMIC_SWAP_I64)
14105 else if (
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
14106 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64 ||
14107 (Subtarget.hasPartwordAtomics() &&
14108 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8) ||
14109 (Subtarget.hasPartwordAtomics() &&
14110 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16)) {
14111 bool is64bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
14113 auto LoadMnemonic = PPC::LDARX;
14114 auto StoreMnemonic = PPC::STDCX;
14115 switch (
MI.getOpcode()) {
14118 case PPC::ATOMIC_CMP_SWAP_I8:
14119 LoadMnemonic = PPC::LBARX;
14120 StoreMnemonic = PPC::STBCX;
14121 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14123 case PPC::ATOMIC_CMP_SWAP_I16:
14124 LoadMnemonic = PPC::LHARX;
14125 StoreMnemonic = PPC::STHCX;
14126 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14128 case PPC::ATOMIC_CMP_SWAP_I32:
14129 LoadMnemonic = PPC::LWARX;
14130 StoreMnemonic = PPC::STWCX;
14132 case PPC::ATOMIC_CMP_SWAP_I64:
14133 LoadMnemonic = PPC::LDARX;
14134 StoreMnemonic = PPC::STDCX;
14141 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14142 Register oldval =
MI.getOperand(3).getReg();
14143 Register newval =
MI.getOperand(4).getReg();
14149 F->insert(It, loop1MBB);
14150 F->insert(It, loop2MBB);
14151 F->insert(It, exitMBB);
14172 BuildMI(BB, dl,
TII->get(is64bit ? PPC::CMPD : PPC::CMPW), CrReg)
14198 }
else if (
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 ||
14199 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16) {
14203 bool is64bit = Subtarget.isPPC64();
14204 bool isLittleEndian = Subtarget.isLittleEndian();
14205 bool is8bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8;
14210 Register oldval =
MI.getOperand(3).getReg();
14211 Register newval =
MI.getOperand(4).getReg();
14217 F->insert(It, loop1MBB);
14218 F->insert(It, loop2MBB);
14219 F->insert(It, exitMBB);
14226 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
14229 Register PtrReg = RegInfo.createVirtualRegister(RC);
14230 Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
14232 isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
14233 Register NewVal2Reg = RegInfo.createVirtualRegister(GPRC);
14234 Register NewVal3Reg = RegInfo.createVirtualRegister(GPRC);
14235 Register OldVal2Reg = RegInfo.createVirtualRegister(GPRC);
14236 Register OldVal3Reg = RegInfo.createVirtualRegister(GPRC);
14237 Register MaskReg = RegInfo.createVirtualRegister(GPRC);
14238 Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
14239 Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
14240 Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
14241 Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
14242 Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
14244 Register TmpReg = RegInfo.createVirtualRegister(GPRC);
14245 Register ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
14246 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14277 if (ptrA != ZeroReg) {
14278 Ptr1Reg = RegInfo.createVirtualRegister(RC);
14279 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
14288 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
14289 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
14292 .
addImm(is8bit ? 28 : 27);
14293 if (!isLittleEndian)
14294 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
14296 .
addImm(is8bit ? 24 : 16);
14298 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
14303 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
14308 BuildMI(BB, dl,
TII->get(PPC::SLW), NewVal2Reg)
14311 BuildMI(BB, dl,
TII->get(PPC::SLW), OldVal2Reg)
14318 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
14322 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
14325 BuildMI(BB, dl,
TII->get(PPC::AND), NewVal3Reg)
14328 BuildMI(BB, dl,
TII->get(PPC::AND), OldVal3Reg)
14333 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
14350 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
14374 }
else if (
MI.getOpcode() == PPC::FADDrtz) {
14384 Register MFFSReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14399 auto MIB =
BuildMI(*BB,
MI, dl,
TII->get(PPC::FADD), Dest)
14407 }
else if (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
14408 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT ||
14409 MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
14410 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8) {
14411 unsigned Opcode = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
14412 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8)
14415 bool IsEQ = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
14416 MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8);
14419 Register Dest = RegInfo.createVirtualRegister(
14420 Opcode == PPC::ANDI_rec ? &PPC::GPRCRegClass : &PPC::G8RCRegClass);
14424 .
addReg(
MI.getOperand(1).getReg())
14427 MI.getOperand(0).getReg())
14428 .
addReg(IsEQ ? PPC::CR0EQ : PPC::CR0GT);
14429 }
else if (
MI.getOpcode() == PPC::TCHECK_RET) {
14432 Register CRReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14435 MI.getOperand(0).getReg())
14437 }
else if (
MI.getOpcode() == PPC::TBEGIN_RET) {
14439 unsigned Imm =
MI.getOperand(1).getImm();
14442 MI.getOperand(0).getReg())
14444 }
else if (
MI.getOpcode() == PPC::SETRNDi) {
14446 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14449 if (
MRI.use_empty(OldFPSCRReg))
14450 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14452 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14463 unsigned Mode =
MI.getOperand(1).getImm();
14464 BuildMI(*BB,
MI, dl,
TII->get((Mode & 1) ? PPC::MTFSB1 : PPC::MTFSB0))
14468 BuildMI(*BB,
MI, dl,
TII->get((Mode & 2) ? PPC::MTFSB1 : PPC::MTFSB0))
14471 }
else if (
MI.getOpcode() == PPC::SETRND) {
14479 auto copyRegFromG8RCOrF8RC = [&] (
unsigned DestReg,
unsigned SrcReg) {
14480 if (Subtarget.hasDirectMove()) {
14481 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::COPY), DestReg)
14485 unsigned StoreOp = PPC::STD, LoadOp = PPC::LFD;
14488 if (RC == &PPC::F8RCRegClass) {
14490 assert((RegInfo.getRegClass(DestReg) == &PPC::G8RCRegClass) &&
14491 "Unsupported RegClass.");
14493 StoreOp = PPC::STFD;
14497 assert((RegInfo.getRegClass(SrcReg) == &PPC::G8RCRegClass) &&
14498 (RegInfo.getRegClass(DestReg) == &PPC::F8RCRegClass) &&
14499 "Unsupported RegClass.");
14532 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14535 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14547 Register OldFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14549 copyRegFromG8RCOrF8RC(OldFPSCRTmpReg, OldFPSCRReg);
14551 Register ImDefReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14552 Register ExtSrcReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14557 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), ImDefReg);
14558 BuildMI(*BB,
MI, dl,
TII->get(PPC::INSERT_SUBREG), ExtSrcReg)
14563 Register NewFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14564 BuildMI(*BB,
MI, dl,
TII->get(PPC::RLDIMI), NewFPSCRTmpReg)
14570 Register NewFPSCRReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14571 copyRegFromG8RCOrF8RC(NewFPSCRReg, NewFPSCRTmpReg);
14580 }
else if (
MI.getOpcode() == PPC::SETFLM) {
14584 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14585 if (
MRI.use_empty(OldFPSCRReg))
14586 BuildMI(*BB,
MI, Dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14588 BuildMI(*BB,
MI, Dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14591 Register NewFPSCRReg =
MI.getOperand(1).getReg();
14597 }
else if (
MI.getOpcode() == PPC::PROBED_ALLOCA_32 ||
14598 MI.getOpcode() == PPC::PROBED_ALLOCA_64) {
14600 }
else if (
MI.getOpcode() == PPC::SPLIT_QUADWORD) {
14607 .
addUse(Src, {}, PPC::sub_gp8_x1);
14610 .
addUse(Src, {}, PPC::sub_gp8_x0);
14611 }
else if (
MI.getOpcode() == PPC::LQX_PSEUDO ||
14612 MI.getOpcode() == PPC::STQX_PSEUDO) {
14618 F->getRegInfo().createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass);
14624 MI.getOpcode() == PPC::LQX_PSEUDO ?
TII->get(PPC::LQ)
14625 :
TII->get(PPC::STQ))
14629 }
else if (
MI.getOpcode() == PPC::LWAT_PSEUDO ||
14630 MI.getOpcode() == PPC::LDAT_PSEUDO) {
14632 Register DstReg =
MI.getOperand(0).getReg();
14633 Register PtrReg =
MI.getOperand(1).getReg();
14634 Register ValReg =
MI.getOperand(2).getReg();
14635 unsigned FC =
MI.getOperand(3).getImm();
14636 bool IsLwat =
MI.getOpcode() == PPC::LWAT_PSEUDO;
14637 Register Val64 =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
14639 BuildMI(*BB,
MI,
DL,
TII->get(TargetOpcode::SUBREG_TO_REG), Val64)
14646 Register G8rPair =
MRI.createVirtualRegister(&PPC::G8pRCRegClass);
14647 Register UndefG8r =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
14648 BuildMI(*BB,
MI,
DL,
TII->get(TargetOpcode::IMPLICIT_DEF), UndefG8r);
14651 .
addImm(PPC::sub_gp8_x0)
14653 .
addImm(PPC::sub_gp8_x1);
14655 Register PairResult =
MRI.createVirtualRegister(&PPC::G8pRCRegClass);
14656 BuildMI(*BB,
MI,
DL,
TII->get(IsLwat ? PPC::LWAT : PPC::LDAT), PairResult)
14660 Register Result64 =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
14662 .
addReg(PairResult, {}, PPC::sub_gp8_x0);
14665 .
addReg(Result64, {}, PPC::sub_32);
14669 }
else if (
MI.getOpcode() == PPC::LWAT_COND_PSEUDO ||
14670 MI.getOpcode() == PPC::LDAT_COND_PSEUDO) {
14672 Register DstReg =
MI.getOperand(0).getReg();
14673 Register PtrReg =
MI.getOperand(1).getReg();
14674 unsigned FC =
MI.getOperand(2).getImm();
14675 bool IsLwat_Cond =
MI.getOpcode() == PPC::LWAT_COND_PSEUDO;
14677 Register Pair =
MRI.createVirtualRegister(&PPC::G8pRCRegClass);
14678 BuildMI(*BB,
MI,
DL,
TII->get(TargetOpcode::IMPLICIT_DEF), Pair);
14680 Register PairResult =
MRI.createVirtualRegister(&PPC::G8pRCRegClass);
14681 BuildMI(*BB,
MI,
DL,
TII->get(IsLwat_Cond ? PPC::LWAT : PPC::LDAT),
14686 Register Result64 =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
14688 .
addReg(PairResult, {}, PPC::sub_gp8_x0);
14691 .
addReg(Result64, {}, PPC::sub_32);
14699 MI.eraseFromParent();
14712 int RefinementSteps = Subtarget.hasRecipPrec() ? 1 : 3;
14715 return RefinementSteps;
14721 EVT VT =
Op.getValueType();
14724 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX())))
14748PPCTargetLowering::getSqrtResultForDenormInput(
SDValue Op,
14751 EVT VT =
Op.getValueType();
14752 if (VT != MVT::f64 &&
14753 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX()))
14756 return DAG.
getNode(PPCISD::FSQRT, SDLoc(
Op), VT,
Op);
14760 int Enabled,
int &RefinementSteps,
14761 bool &UseOneConstNR,
14762 bool Reciprocal)
const {
14764 if ((VT == MVT::f32 && Subtarget.hasFRSQRTES()) ||
14765 (VT == MVT::f64 && Subtarget.hasFRSQRTE()) ||
14766 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
14767 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
14773 UseOneConstNR = !Subtarget.needsTwoConstNR();
14774 return DAG.
getNode(PPCISD::FRSQRTE, SDLoc(Operand), VT, Operand);
14781 int &RefinementSteps)
const {
14783 if ((VT == MVT::f32 && Subtarget.hasFRES()) ||
14784 (VT == MVT::f64 && Subtarget.hasFRE()) ||
14785 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
14786 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
14789 return DAG.
getNode(PPCISD::FRE, SDLoc(Operand), VT, Operand);
14805 switch (Subtarget.getCPUDirective()) {
14832 unsigned Bytes,
int Dist,
14846 if (FS != BFS || FS != (
int)Bytes)
return false;
14851 int64_t Offset1 = 0, Offset2 = 0;
14854 if (Base1 == Base2 && Offset1 == (Offset2 + Dist * Bytes))
14864 if (isGA1 && isGA2 && GV1 == GV2)
14865 return Offset1 == (Offset2 + Dist*Bytes);
14872 unsigned Bytes,
int Dist,
14875 EVT VT = LS->getMemoryVT();
14882 switch (
N->getConstantOperandVal(1)) {
14883 default:
return false;
14884 case Intrinsic::ppc_altivec_lvx:
14885 case Intrinsic::ppc_altivec_lvxl:
14886 case Intrinsic::ppc_vsx_lxvw4x:
14887 case Intrinsic::ppc_vsx_lxvw4x_be:
14890 case Intrinsic::ppc_vsx_lxvd2x:
14891 case Intrinsic::ppc_vsx_lxvd2x_be:
14894 case Intrinsic::ppc_altivec_lvebx:
14897 case Intrinsic::ppc_altivec_lvehx:
14900 case Intrinsic::ppc_altivec_lvewx:
14910 switch (
N->getConstantOperandVal(1)) {
14911 default:
return false;
14912 case Intrinsic::ppc_altivec_stvx:
14913 case Intrinsic::ppc_altivec_stvxl:
14914 case Intrinsic::ppc_vsx_stxvw4x:
14917 case Intrinsic::ppc_vsx_stxvd2x:
14920 case Intrinsic::ppc_vsx_stxvw4x_be:
14923 case Intrinsic::ppc_vsx_stxvd2x_be:
14926 case Intrinsic::ppc_altivec_stvebx:
14929 case Intrinsic::ppc_altivec_stvehx:
14932 case Intrinsic::ppc_altivec_stvewx:
14949 SDValue Chain = LD->getChain();
14950 EVT VT = LD->getMemoryVT();
14959 while (!Queue.empty()) {
14960 SDNode *ChainNext = Queue.pop_back_val();
14961 if (!Visited.
insert(ChainNext).second)
14968 if (!Visited.
count(ChainLD->getChain().getNode()))
14969 Queue.push_back(ChainLD->getChain().getNode());
14971 for (
const SDUse &O : ChainNext->
ops())
14972 if (!Visited.
count(O.getNode()))
14973 Queue.push_back(O.getNode());
14975 LoadRoots.
insert(ChainNext);
14986 for (
SDNode *
I : LoadRoots) {
14987 Queue.push_back(
I);
14989 while (!Queue.empty()) {
14990 SDNode *LoadRoot = Queue.pop_back_val();
14991 if (!Visited.
insert(LoadRoot).second)
15003 Queue.push_back(U);
15036 auto Final = Shifted;
15047 DAGCombinerInfo &DCI)
const {
15050 SelectionDAG &DAG = DCI.DAG;
15055 if (!DCI.isAfterLegalizeDAG())
15060 for (
const SDNode *U :
N->users())
15065 auto OpSize =
N->getOperand(0).getValueSizeInBits();
15069 if (OpSize <
Size) {
15087 DAGCombinerInfo &DCI)
const {
15088 SelectionDAG &DAG = DCI.DAG;
15091 assert(Subtarget.useCRBits() &&
"Expecting to be tracking CR bits");
15102 N->getValueType(0) != MVT::i1)
15105 if (
N->getOperand(0).getValueType() != MVT::i32 &&
15106 N->getOperand(0).getValueType() != MVT::i64)
15116 unsigned OpBits =
N->getOperand(0).getValueSizeInBits();
15127 return (
N->getOpcode() ==
ISD::SETCC ? ConvertSETCCToSubtract(
N, DCI)
15150 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15151 N->getOperand(0).getOpcode() !=
ISD::OR &&
15152 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15162 N->getOperand(1).getOpcode() !=
ISD::AND &&
15163 N->getOperand(1).getOpcode() !=
ISD::OR &&
15164 N->getOperand(1).getOpcode() !=
ISD::XOR &&
15175 SmallPtrSet<SDNode *, 16> Visited;
15177 for (
unsigned i = 0; i < 2; ++i) {
15181 N->getOperand(i).getOperand(0).getValueType() == MVT::i1) ||
15193 while (!BinOps.
empty()) {
15201 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15235 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15239 for (
const SDNode *User : Inputs[i].
getNode()->
users()) {
15240 if (User !=
N && !Visited.
count(User))
15249 if (
User->getOperand(0) == Inputs[i])
15252 if (
User->getOperand(0) == Inputs[i] ||
15253 User->getOperand(1) == Inputs[i])
15259 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15260 for (
const SDNode *User : PromOps[i].
getNode()->
users()) {
15261 if (User !=
N && !Visited.
count(User))
15270 if (
User->getOperand(0) == PromOps[i])
15273 if (
User->getOperand(0) == PromOps[i] ||
15274 User->getOperand(1) == PromOps[i])
15281 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15290 std::list<HandleSDNode> PromOpHandles;
15291 for (
auto &PromOp : PromOps)
15292 PromOpHandles.emplace_back(PromOp);
15299 while (!PromOpHandles.empty()) {
15300 SDValue PromOp = PromOpHandles.back().getValue();
15301 PromOpHandles.pop_back();
15310 PromOpHandles.emplace_front(PromOp);
15324 default:
C = 0;
break;
15337 PromOpHandles.emplace_front(PromOp);
15344 for (
unsigned i = 0; i < 2; ++i)
15354 return N->getOperand(0);
15362 DAGCombinerInfo &DCI)
const {
15363 SelectionDAG &DAG = DCI.DAG;
15380 if (
N->getValueType(0) != MVT::i32 &&
15381 N->getValueType(0) != MVT::i64)
15384 if (!((
N->getOperand(0).getValueType() == MVT::i1 && Subtarget.useCRBits()) ||
15385 (
N->getOperand(0).getValueType() == MVT::i32 && Subtarget.isPPC64())))
15388 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15389 N->getOperand(0).getOpcode() !=
ISD::OR &&
15390 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15397 SmallPtrSet<SDNode *, 16> Visited;
15401 while (!BinOps.
empty()) {
15409 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15435 DenseMap<SDNode *, EVT> SelectTruncOp[2];
15440 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15445 if (User !=
N && !Visited.
count(User))
15451 if (
User->getOperand(0) == Inputs[i])
15452 SelectTruncOp[0].
insert(std::make_pair(User,
15453 User->getOperand(0).getValueType()));
15455 if (
User->getOperand(0) == Inputs[i])
15456 SelectTruncOp[0].
insert(std::make_pair(User,
15457 User->getOperand(0).getValueType()));
15458 if (
User->getOperand(1) == Inputs[i])
15459 SelectTruncOp[1].
insert(std::make_pair(User,
15460 User->getOperand(1).getValueType()));
15465 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15467 if (User !=
N && !Visited.
count(User))
15473 if (
User->getOperand(0) == PromOps[i])
15474 SelectTruncOp[0].
insert(std::make_pair(User,
15475 User->getOperand(0).getValueType()));
15477 if (
User->getOperand(0) == PromOps[i])
15478 SelectTruncOp[0].
insert(std::make_pair(User,
15479 User->getOperand(0).getValueType()));
15480 if (
User->getOperand(1) == PromOps[i])
15481 SelectTruncOp[1].
insert(std::make_pair(User,
15482 User->getOperand(1).getValueType()));
15487 unsigned PromBits =
N->getOperand(0).getValueSizeInBits();
15488 bool ReallyNeedsExt =
false;
15492 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15497 Inputs[i].getOperand(0).getValueSizeInBits();
15498 assert(PromBits < OpBits &&
"Truncation not to a smaller bit count?");
15503 OpBits-PromBits))) ||
15506 (OpBits-(PromBits-1)))) {
15507 ReallyNeedsExt =
true;
15515 std::list<HandleSDNode> PromOpHandles;
15516 for (
auto &PromOp : PromOps)
15517 PromOpHandles.emplace_back(PromOp);
15521 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15528 SDValue InSrc = Inputs[i].getOperand(0);
15546 while (!PromOpHandles.empty()) {
15548 PromOpHandles.pop_back();
15552 default:
C = 0;
break;
15565 PromOpHandles.emplace_front(PromOp);
15575 (SelectTruncOp[1].count(PromOp.
getNode()) &&
15577 PromOpHandles.emplace_front(PromOp);
15585 for (
unsigned i = 0; i < 2; ++i) {
15603 auto SI0 = SelectTruncOp[0].
find(PromOp.
getNode());
15604 if (SI0 != SelectTruncOp[0].
end())
15606 auto SI1 = SelectTruncOp[1].
find(PromOp.
getNode());
15607 if (SI1 != SelectTruncOp[1].
end())
15616 if (!ReallyNeedsExt)
15617 return N->getOperand(0);
15624 N->getValueSizeInBits(0), PromBits),
15625 dl,
N->getValueType(0)));
15628 "Invalid extension type");
15631 DAG.
getConstant(
N->getValueSizeInBits(0) - PromBits, dl, ShiftAmountTy);
15641 auto isValidForConvert = [](
SDValue &Operand) {
15660 if (LoadNode->isVolatile())
15681 return (isValidForConvert(
LHS) && isValidForConvert(
RHS));
15691 "CC mus be ISD::SETNE or ISD::SETEQ");
15693 auto getV16i8Load = [&](
const SDValue &Operand) {
15700 return DAG.
getLoad(MVT::v16i8,
DL, LoadNode->getChain(),
15701 LoadNode->getBasePtr(), LoadNode->getMemOperand());
15740 SDValue LHSVec = getV16i8Load(
N->getOperand(0));
15741 SDValue RHSVec = getV16i8Load(
N->getOperand(1));
15744 DAG.
getConstant(Intrinsic::ppc_altivec_vcmpequb_p,
DL, MVT::i32);
15747 IntrID, CRSel, LHSVec, RHSVec);
15750 return DAG.
getSetCC(
DL,
N->getValueType(0), PredResult,
15768 auto IsAndWithOne = [](
SDValue &V) {
15779 auto IsCompareWithZero = [](
SDValue &V) {
15786 return (IsAndWithOne(
LHS) && IsCompareWithZero(
RHS)) ||
15787 (IsAndWithOne(
RHS) && IsCompareWithZero(
LHS));
15804 auto MakeXor1 = [&](
SDValue V) {
15805 EVT VT = V.getValueType();
15812 return MakeXor1(
LHS);
15815 return MakeXor1(
RHS);
15821 DAGCombinerInfo &DCI)
const {
15823 "Should be called with a SETCC node");
15845 SelectionDAG &DAG = DCI.DAG;
15846 EVT VT =
N->getValueType(0);
15847 EVT OpVT =
LHS.getValueType();
15869 return DAGCombineTruncBoolExt(
N, DCI);
15876 Op.getValueType() == MVT::f64;
15888combineElementTruncationToVectorTruncation(
SDNode *
N,
15889 DAGCombinerInfo &DCI)
const {
15891 "Should be called with a BUILD_VECTOR node");
15893 SelectionDAG &DAG = DCI.DAG;
15896 SDValue FirstInput =
N->getOperand(0);
15898 "The input operand must be an fp-to-int conversion.");
15903 if (FirstConversion == PPCISD::FCTIDZ ||
15904 FirstConversion == PPCISD::FCTIDUZ ||
15905 FirstConversion == PPCISD::FCTIWZ ||
15906 FirstConversion == PPCISD::FCTIWUZ) {
15907 bool IsSplat =
true;
15908 bool Is32Bit = FirstConversion == PPCISD::FCTIWZ ||
15909 FirstConversion == PPCISD::FCTIWUZ;
15912 EVT TargetVT =
N->getValueType(0);
15913 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
15914 SDValue NextOp =
N->getOperand(i);
15915 if (NextOp.
getOpcode() != PPCISD::MFVSR)
15918 if (NextConversion != FirstConversion)
15926 if (
N->getOperand(i) != FirstInput)
15937 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
15938 SDValue In =
N->getOperand(i).getOperand(0);
15948 Ops.push_back(Trunc);
15951 Ops.push_back(
In.isUndef() ? DAG.
getUNDEF(SrcVT) :
In.getOperand(0));
15955 if (FirstConversion == PPCISD::FCTIDZ ||
15956 FirstConversion == PPCISD::FCTIWZ)
15961 EVT NewVT = TargetVT == MVT::v2i64 ? MVT::v2f64 : MVT::v4f32;
15963 return DAG.
getNode(Opcode, dl, TargetVT, BV);
15981 static const APInt BasePattern =
APInt(128, 0x8000000000000000ULL) << 64;
15985 if (FullVal == BasePattern)
15986 return std::make_tuple(Uim,
uint8_t{0});
15989 if (FullVal ==
APInt(128, 1))
15990 return std::make_tuple(Uim,
uint8_t{127});
15992 return std::nullopt;
16012 "Expected a BuildVectorSDNode in combineBVLoadsSpecialValue");
16016 EVT VT =
Op.getValueType();
16017 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
16031 for (
const SDValue &Operand :
Op.getNode()->op_values()) {
16041 for (
unsigned Index = 0;
Index < NumElems; ++
Index) {
16045 uint64_t ElemValue =
C->getZExtValue();
16049 ElemValue &= ((1ULL << ElemBits) - 1);
16053 (IsLittleEndian) ? (Index * ElemBits) : (128 - (
Index + 1) * ElemBits);
16056 APInt ElemAPInt(128, ElemValue);
16057 ElemAPInt <<= BitPos;
16060 FullVal |= ElemAPInt;
16067 const auto &[Uim, ShiftAmount] = *UIMOpt;
16071 if (ShiftAmount == 0) {
16076 <<
"combineBVLoadsSpecialValue: Instruction Emitted ";
16077 LxvkqInstr.
dump());
16081 assert(ShiftAmount == 127 &&
"Unexpected lxvkq shift amount value");
16093 DAG.
getMachineNode(PPC::VSRQ, Dl, VT, ShiftAmountVec, ShiftAmountVec),
16096 <<
"\n combineBVLoadsSpecialValue: Instruction Emitted ";
16112 "Should be called with a BUILD_VECTOR node");
16117 if (!
N->getValueType(0).getVectorElementType().isByteSized())
16120 bool InputsAreConsecutiveLoads =
true;
16121 bool InputsAreReverseConsecutive =
true;
16122 unsigned ElemSize =
N->getValueType(0).getScalarType().getStoreSize();
16123 SDValue FirstInput =
N->getOperand(0);
16124 bool IsRoundOfExtLoad =
false;
16134 N->getNumOperands() == 1)
16137 if (!IsRoundOfExtLoad)
16142 for (
int i = 1, e =
N->getNumOperands(); i < e; ++i) {
16144 if (IsRoundOfExtLoad &&
N->getOperand(i).getOpcode() !=
ISD::FP_ROUND)
16147 SDValue NextInput = IsRoundOfExtLoad ?
N->getOperand(i).getOperand(0) :
16153 IsRoundOfExtLoad ?
N->getOperand(i-1).getOperand(0) :
N->getOperand(i-1);
16164 InputsAreConsecutiveLoads =
false;
16166 InputsAreReverseConsecutive =
false;
16169 if (!InputsAreConsecutiveLoads && !InputsAreReverseConsecutive)
16174 assert(!(InputsAreConsecutiveLoads && InputsAreReverseConsecutive) &&
16175 "The loads cannot be both consecutive and reverse consecutive.");
16179 if (InputsAreConsecutiveLoads) {
16180 assert(FirstLoad &&
"Input needs to be a LoadSDNode.");
16184 ReturnSDVal = WideLoad;
16185 }
else if (InputsAreReverseConsecutive) {
16187 assert(LastLoad &&
"Input needs to be a LoadSDNode.");
16192 for (
int i =
N->getNumOperands() - 1; i >= 0; i--)
16200 for (
auto *LD : InputLoads)
16202 return ReturnSDVal;
16213 unsigned NumElems =
Input.getValueType().getVectorNumElements();
16219 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16221 ShuffleMask[CorrectElems & 0xF] = Elems & 0xF;
16223 ShuffleMask[(CorrectElems & 0xF0) >> 4] = (Elems & 0xF0) >> 4;
16224 CorrectElems = CorrectElems >> 8;
16225 Elems = Elems >> 8;
16232 EVT VT =
N->getValueType(0);
16236 Input.getValueType().getVectorElementType(),
16270 auto isSExtOfVecExtract = [&](
SDValue Op) ->
bool {
16296 Elems = Elems << 8;
16305 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16306 if (!isSExtOfVecExtract(
N->getOperand(i))) {
16313 int TgtElemArrayIdx;
16314 int InputSize =
Input.getValueType().getScalarSizeInBits();
16315 int OutputSize =
N->getValueType(0).getScalarSizeInBits();
16316 if (InputSize + OutputSize == 40)
16317 TgtElemArrayIdx = 0;
16318 else if (InputSize + OutputSize == 72)
16319 TgtElemArrayIdx = 1;
16320 else if (InputSize + OutputSize == 48)
16321 TgtElemArrayIdx = 2;
16322 else if (InputSize + OutputSize == 80)
16323 TgtElemArrayIdx = 3;
16324 else if (InputSize + OutputSize == 96)
16325 TgtElemArrayIdx = 4;
16329 uint64_t CorrectElems = TargetElems[TgtElemArrayIdx];
16331 ? CorrectElems & 0x0F0F0F0F0F0F0F0F
16332 : CorrectElems & 0xF0F0F0F0F0F0F0F0;
16333 if (Elems != CorrectElems) {
16349 if (
N->getValueType(0) != MVT::v1i128)
16352 SDValue Operand =
N->getOperand(0);
16359 EVT MemoryType = LD->getMemoryVT();
16363 bool ValidLDType = MemoryType == MVT::i8 || MemoryType == MVT::i16 ||
16364 MemoryType == MVT::i32 || MemoryType == MVT::i64;
16367 if (!ValidLDType ||
16373 LD->getChain(), LD->getBasePtr(),
16377 DAG.
getVTList(MVT::v1i128, MVT::Other),
16378 LoadOps, MemoryType, LD->getMemOperand());
16382 DAGCombinerInfo &DCI)
const {
16384 "Should be called with a BUILD_VECTOR node");
16386 SelectionDAG &DAG = DCI.DAG;
16389 if (!Subtarget.hasVSX())
16396 if (FirstInput.
getOpcode() == PPCISD::MFVSR) {
16397 SDValue Reduced = combineElementTruncationToVectorTruncation(
N, DCI);
16412 if (Subtarget.hasP9Altivec() && !DCI.isBeforeLegalize()) {
16421 if (Subtarget.isISA3_1()) {
16427 if (
N->getValueType(0) != MVT::v2f64)
16438 if (FirstInput.
getOpcode() !=
N->getOperand(1).getOpcode())
16449 if (!Ext1Op || !Ext2Op)
16458 if (FirstElem == 0 && SecondElem == 1)
16459 SubvecIdx = Subtarget.isLittleEndian() ? 1 : 0;
16460 else if (FirstElem == 2 && SecondElem == 3)
16461 SubvecIdx = Subtarget.isLittleEndian() ? 0 : 1;
16467 PPCISD::SINT_VEC_TO_FP : PPCISD::UINT_VEC_TO_FP;
16468 return DAG.
getNode(NodeType, dl, MVT::v2f64,
16473 DAGCombinerInfo &DCI)
const {
16476 "Need an int -> FP conversion node here");
16481 SelectionDAG &DAG = DCI.DAG;
16487 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
16489 if (!
Op.getOperand(0).getValueType().isSimple())
16491 if (
Op.getOperand(0).getValueType().getSimpleVT() <= MVT(MVT::i1) ||
16492 Op.getOperand(0).getValueType().getSimpleVT() > MVT(MVT::i64))
16495 SDValue FirstOperand(
Op.getOperand(0));
16496 bool SubWordLoad = FirstOperand.getOpcode() ==
ISD::LOAD &&
16497 (FirstOperand.getValueType() == MVT::i8 ||
16498 FirstOperand.getValueType() == MVT::i16);
16499 if (Subtarget.hasP9Vector() && Subtarget.hasP9Altivec() && SubWordLoad) {
16501 bool DstDouble =
Op.getValueType() == MVT::f64;
16502 unsigned ConvOp =
Signed ?
16503 (DstDouble ? PPCISD::FCFID : PPCISD::FCFIDS) :
16504 (DstDouble ? PPCISD::FCFIDU : PPCISD::FCFIDUS);
16509 SDValue Ops[] = { LDN->getChain(), LDN->getBasePtr(), WidthConst };
16512 Ops, MVT::i8, LDN->getMemOperand());
16517 SDValue ExtOps[] = { Ld, WidthConst };
16519 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ext);
16521 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ld);
16529 if (
Op.getOperand(0).getValueType() == MVT::i32)
16533 "UINT_TO_FP is supported only with FPCVT");
16537 unsigned FCFOp = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16542 MVT FCFTy = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16549 Subtarget.hasFPCVT()) ||
16551 SDValue Src =
Op.getOperand(0).getOperand(0);
16552 if (Src.getValueType() == MVT::f32) {
16554 DCI.AddToWorklist(Src.getNode());
16555 }
else if (Src.getValueType() != MVT::f64) {
16567 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
16570 DCI.AddToWorklist(
FP.getNode());
16594 switch (
N->getOpcode()) {
16599 Chain = LD->getChain();
16600 Base = LD->getBasePtr();
16601 MMO = LD->getMemOperand();
16620 MVT VecTy =
N->getValueType(0).getSimpleVT();
16628 Chain = Load.getValue(1);
16630 PPCISD::XXSWAPD, dl, DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Load);
16634 if (VecTy != MVT::v2f64) {
16661 switch (
N->getOpcode()) {
16666 Chain = ST->getChain();
16667 Base = ST->getBasePtr();
16668 MMO = ST->getMemOperand();
16688 SDValue Src =
N->getOperand(SrcOpnd);
16689 MVT VecTy = Src.getValueType().getSimpleVT();
16692 if (VecTy != MVT::v2f64) {
16698 DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Src);
16704 StoreOps, VecTy, MMO);
16711 DAGCombinerInfo &DCI)
const {
16714 unsigned Opcode =
N->getOperand(1).getOpcode();
16716 bool Strict =
N->getOperand(1)->isStrictFPOpcode();
16720 &&
"Not a FP_TO_INT Instruction!");
16722 SDValue Val =
N->getOperand(1).getOperand(Strict ? 1 : 0);
16723 EVT Op1VT =
N->getOperand(1).getValueType();
16726 if (!Subtarget.hasVSX() || !Subtarget.hasFPCVT() || !
isTypeLegal(ResVT))
16730 bool ValidTypeForStoreFltAsInt =
16731 (Op1VT == MVT::i32 || (Op1VT == MVT::i64 && Subtarget.isPPC64()) ||
16732 (Subtarget.hasP9Vector() && (Op1VT == MVT::i16 || Op1VT == MVT::i8)));
16735 if (ResVT == MVT::ppcf128 || (ResVT == MVT::f128 && !Subtarget.hasP9Vector()))
16738 if ((Op1VT != MVT::i64 && !Subtarget.hasP8Vector()) ||
16746 SDValue Ops[] = {
N->getOperand(0), Val,
N->getOperand(2),
16761 bool PrevElemFromFirstVec = Mask[0] < NumElts;
16762 for (
int i = 1, e = Mask.size(); i < e; i++) {
16763 if (PrevElemFromFirstVec && Mask[i] < NumElts)
16765 if (!PrevElemFromFirstVec && Mask[i] >= NumElts)
16767 PrevElemFromFirstVec = !PrevElemFromFirstVec;
16778 for (
int i = 0, e =
Op.getNumOperands(); i < e; i++) {
16779 FirstOp =
Op.getOperand(i);
16785 for (
int i = 1, e =
Op.getNumOperands(); i < e; i++)
16786 if (
Op.getOperand(i) != FirstOp && !
Op.getOperand(i).isUndef())
16796 Op =
Op.getOperand(0);
16812 int RHSFirstElt,
int RHSLastElt,
int HalfVec,
unsigned LHSNumValidElts,
16813 unsigned RHSNumValidElts,
const PPCSubtarget &Subtarget) {
16815 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - LHSNumValidElts;
16817 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - RHSNumValidElts;
16818 for (
int I = 0,
E = ShuffV.
size();
I <
E; ++
I) {
16819 int Idx = ShuffV[
I];
16820 if (Idx >= LHSFirstElt && Idx <= LHSLastElt)
16821 ShuffV[
I] += LHSEltFixup;
16822 else if (Idx >= RHSFirstElt && Idx <= RHSLastElt)
16823 ShuffV[
I] += RHSEltFixup;
16834 SDLoc dl(OrigSToV);
16837 "Expecting a SCALAR_TO_VECTOR here");
16850 "Cannot produce a permuted scalar_to_vector for one element vector");
16852 unsigned ResultInElt = NumElts / 2;
16858 return DAG.
getNode(PPCISD::SCALAR_TO_VECTOR_PERMUTED, dl, VT,
16863 int HalfVec,
int LHSLastElementDefined,
16864 int RHSLastElementDefined) {
16865 for (
int Index : ShuffV) {
16869 if ((LHSLastElementDefined >= 0) && (Index < HalfVec) &&
16870 (Index > LHSLastElementDefined))
16873 if ((RHSLastElementDefined >= 0) &&
16874 (Index > HalfVec + RHSLastElementDefined))
16881 int ScalarSize,
uint64_t ShuffleEltWidth,
unsigned &NumValidElts,
16882 int FirstElt,
int &LastElt,
SDValue VecShuffOperand,
SDValue SToVNode,
16898 LastElt = (
uint64_t)ScalarSize > ShuffleEltWidth
16899 ? ScalarSize / ShuffleEltWidth - 1 + FirstElt
16902 if (SToVPermuted.
getValueType() != VecShuffOperandType)
16903 SToVPermuted = DAG.
getBitcast(VecShuffOperandType, SToVPermuted);
16904 return SToVPermuted;
16924 int NumElts =
LHS.getValueType().getVectorNumElements();
16927 bool IsLittleEndian = Subtarget.isLittleEndian();
16934 if (!Subtarget.hasDirectMove())
16954 SmallVector<int, 16> ShuffV(Mask);
16957 if (SToVLHS || SToVRHS) {
16960 int ShuffleNumElts = ShuffV.
size();
16961 int HalfVec = ShuffleNumElts / 2;
16967 unsigned LHSNumValidElts = HalfVec;
16968 unsigned RHSNumValidElts = HalfVec;
16973 int LHSFirstElt = 0;
16974 int RHSFirstElt = ShuffleNumElts;
16975 int LHSLastElt = -1;
16976 int RHSLastElt = -1;
16984 int LHSScalarSize = 0;
16985 int RHSScalarSize = 0;
16988 if (!IsLittleEndian && LHSScalarSize >= 64)
16993 if (!IsLittleEndian && RHSScalarSize >= 64)
16996 if (LHSScalarSize != 0)
16998 LHSScalarSize, ShuffleEltWidth, LHSNumValidElts, LHSFirstElt,
16999 LHSLastElt,
LHS, SToVLHS, DAG, Subtarget);
17000 if (RHSScalarSize != 0)
17002 RHSScalarSize, ShuffleEltWidth, RHSNumValidElts, RHSFirstElt,
17003 RHSLastElt,
RHS, SToVRHS, DAG, Subtarget);
17014 ShuffV, LHSFirstElt, LHSLastElt, RHSFirstElt, RHSLastElt, HalfVec,
17015 LHSNumValidElts, RHSNumValidElts, Subtarget);
17041 if (IsLittleEndian) {
17044 if (Mask[0] < NumElts)
17045 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17049 ShuffV[i] = (ShuffV[i - 1] >= 0 ? ShuffV[i - 1] : 0) + NumElts;
17054 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17058 ShuffV[i] = (ShuffV[i + 1] >= 0 ? ShuffV[i + 1] : 0) + NumElts;
17063 if (Mask[0] < NumElts)
17064 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17068 ShuffV[i] = ShuffV[i + 1] >= 0 ? ShuffV[i + 1] - NumElts : 0;
17073 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17077 ShuffV[i] = ShuffV[i - 1] >= 0 ? ShuffV[i - 1] - NumElts : 0;
17087 if (IsLittleEndian)
17096 DAGCombinerInfo &DCI)
const {
17098 "Not a reverse memop pattern!");
17100 auto IsElementReverse = [](
const ShuffleVectorSDNode *SVN) ->
bool {
17103 auto I =
Mask.rbegin();
17104 auto E =
Mask.rend();
17106 for (;
I !=
E; ++
I) {
17114 SelectionDAG &DAG = DCI.DAG;
17117 if (!
isTypeLegal(VT) || !Subtarget.isLittleEndian() || !Subtarget.hasVSX())
17123 if (!Subtarget.hasP9Vector())
17126 if(!IsElementReverse(SVN))
17133 for (SDUse &Use : LSBase->
uses())
17134 if (
Use.getResNo() == 0 &&
17141 PPCISD::LOAD_VEC_BE, dl, DAG.
getVTList(VT, MVT::Other), LoadOps,
17156 PPCISD::STORE_VEC_BE, dl, DAG.
getVTList(MVT::Other), StoreOps,
17165 if (IntrinsicID == Intrinsic::ppc_stdcx)
17167 else if (IntrinsicID == Intrinsic::ppc_stwcx)
17169 else if (IntrinsicID == Intrinsic::ppc_sthcx)
17171 else if (IntrinsicID == Intrinsic::ppc_stbcx)
17180 if (
N->getOpcode() == PPCISD::ADDC &&
N->hasAnyUseOfValue(1)) {
17184 if (
LHS->getOpcode() == PPCISD::ADDE &&
17197 switch (
N->getOpcode()) {
17200 return combineADD(
N, DCI);
17226 return combineSHL(
N, DCI);
17228 return combineSRA(
N, DCI);
17230 return combineSRL(
N, DCI);
17232 return combineMUL(
N, DCI);
17234 case PPCISD::FNMSUB:
17235 return combineFMALike(
N, DCI);
17238 return N->getOperand(0);
17242 return N->getOperand(0);
17248 return N->getOperand(0);
17254 return DAGCombineExtBoolTrunc(
N, DCI);
17256 return combineTRUNCATE(
N, DCI);
17258 if (
SDValue CSCC = combineSetCC(
N, DCI))
17262 return DAGCombineTruncBoolExt(
N, DCI);
17265 return combineFPToIntToFP(
N, DCI);
17274 EVT Op1VT =
N->getOperand(1).getValueType();
17275 unsigned Opcode =
N->getOperand(1).getOpcode();
17279 SDValue Val = combineStoreFPToInt(
N, DCI);
17293 N->getOperand(1).getNode()->hasOneUse() &&
17294 (Op1VT == MVT::i32 || Op1VT == MVT::i16 ||
17295 (Subtarget.hasLDBRX() && Subtarget.isPPC64() && Op1VT == MVT::i64))) {
17303 SDValue BSwapOp =
N->getOperand(1).getOperand(0);
17310 if (Op1VT.
bitsGT(mVT)) {
17315 if (Op1VT == MVT::i64)
17320 N->getOperand(0), BSwapOp,
N->getOperand(2), DAG.
getValueType(mVT)
17340 ST->getBasePtr(), ST->getOffset(), MemVT,
17341 ST->getMemOperand(), ST->getAddressingMode(),
17345 return ST->isUnindexed()
17354 if (Subtarget.needsSwapsForVSXMemOps() &&
17355 (StoreVT == MVT::v2f64 || StoreVT == MVT::v2i64 ||
17356 StoreVT == MVT::v4f32 || StoreVT == MVT::v4i32))
17363 EVT VT = LD->getValueType(0);
17369 if (Subtarget.needsSwapsForVSXMemOps() &&
17370 (LoadVT == MVT::v2f64 || LoadVT == MVT::v2i64 ||
17371 LoadVT == MVT::v4f32 || LoadVT == MVT::v4i32))
17382 auto ReplaceTwoFloatLoad = [&]() {
17383 if (VT != MVT::i64)
17398 if (!LD->hasNUsesOfValue(2, 0))
17401 auto UI = LD->user_begin();
17402 while (UI.getUse().getResNo() != 0) ++UI;
17404 while (UI.getUse().getResNo() != 0) ++UI;
17405 SDNode *RightShift = *UI;
17413 if (RightShift->getOpcode() !=
ISD::SRL ||
17415 RightShift->getConstantOperandVal(1) != 32 ||
17416 !RightShift->hasOneUse())
17419 SDNode *Trunc2 = *RightShift->user_begin();
17429 Bitcast->getValueType(0) != MVT::f32)
17435 if (Subtarget.isLittleEndian())
17441 SDValue BasePtr = LD->getBasePtr();
17442 if (LD->isIndexed()) {
17444 "Non-pre-inc AM on PPC?");
17452 SDValue FloatLoad = DAG.
getLoad(MVT::f32, dl, LD->getChain(), BasePtr,
17453 LD->getPointerInfo(), LD->getAlign(),
17454 MMOFlags, LD->getAAInfo());
17460 LD->getPointerInfo().getWithOffset(4),
17463 if (LD->isIndexed()) {
17477 if (ReplaceTwoFloatLoad())
17480 EVT MemVT = LD->getMemoryVT();
17483 if (LD->isUnindexed() && VT.
isVector() &&
17486 !Subtarget.hasP8Vector() &&
17487 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
17488 VT == MVT::v4f32))) &&
17489 LD->getAlign() < ABIAlignment) {
17491 SDValue Chain = LD->getChain();
17492 SDValue Ptr = LD->getBasePtr();
17493 bool isLittleEndian = Subtarget.isLittleEndian();
17520 MVT PermCntlTy, PermTy, LDTy;
17521 Intr = isLittleEndian ? Intrinsic::ppc_altivec_lvsr
17522 : Intrinsic::ppc_altivec_lvsl;
17523 IntrLD = Intrinsic::ppc_altivec_lvx;
17524 IntrPerm = Intrinsic::ppc_altivec_vperm;
17525 PermCntlTy = MVT::v16i8;
17526 PermTy = MVT::v4i32;
17545 SDValue BaseLoadOps[] = { Chain, LDXIntID, Ptr };
17549 BaseLoadOps, LDTy, BaseMMO);
17558 int IncValue = IncOffset;
17575 SDValue ExtraLoadOps[] = { Chain, LDXIntID, Ptr };
17579 ExtraLoadOps, LDTy, ExtraMMO);
17590 if (isLittleEndian)
17592 ExtraLoad, BaseLoad, PermCntl, DAG, dl);
17595 BaseLoad, ExtraLoad, PermCntl, DAG, dl);
17598 Perm = Subtarget.hasAltivec()
17613 bool isLittleEndian = Subtarget.isLittleEndian();
17614 unsigned IID =
N->getConstantOperandVal(0);
17615 Intrinsic::ID Intr = (isLittleEndian ? Intrinsic::ppc_altivec_lvsr
17616 : Intrinsic::ppc_altivec_lvsl);
17617 if (IID == Intr &&
N->getOperand(1)->getOpcode() ==
ISD::ADD) {
17624 .zext(
Add.getScalarValueSizeInBits()))) {
17625 SDNode *BasePtr =
Add->getOperand(0).getNode();
17626 for (
SDNode *U : BasePtr->users()) {
17628 U->getConstantOperandVal(0) == IID) {
17639 SDNode *BasePtr =
Add->getOperand(0).getNode();
17640 for (
SDNode *U : BasePtr->users()) {
17643 (
Add->getConstantOperandVal(1) - U->getConstantOperandVal(1)) %
17649 V->getConstantOperandVal(0) == IID) {
17661 (IID == Intrinsic::ppc_altivec_vmaxsw ||
17662 IID == Intrinsic::ppc_altivec_vmaxsh ||
17663 IID == Intrinsic::ppc_altivec_vmaxsb)) {
17694 switch (
N->getConstantOperandVal(1)) {
17697 case Intrinsic::ppc_altivec_vsum4sbs:
17698 case Intrinsic::ppc_altivec_vsum4shs:
17699 case Intrinsic::ppc_altivec_vsum4ubs: {
17706 APInt APSplatBits, APSplatUndef;
17707 unsigned SplatBitSize;
17710 APSplatBits, APSplatUndef, SplatBitSize, HasAnyUndefs, 0,
17711 !Subtarget.isLittleEndian());
17713 if (BVNIsConstantSplat && APSplatBits == 0)
17718 case Intrinsic::ppc_vsx_lxvw4x:
17719 case Intrinsic::ppc_vsx_lxvd2x:
17722 if (Subtarget.needsSwapsForVSXMemOps())
17730 if (Subtarget.needsSwapsForVSXMemOps()) {
17731 switch (
N->getConstantOperandVal(1)) {
17734 case Intrinsic::ppc_vsx_stxvw4x:
17735 case Intrinsic::ppc_vsx_stxvd2x:
17744 bool Is64BitBswapOn64BitTgt =
17745 Subtarget.isPPC64() &&
N->getValueType(0) == MVT::i64;
17747 N->getOperand(0).hasOneUse();
17748 if (IsSingleUseNormalLd &&
17749 (
N->getValueType(0) == MVT::i32 ||
N->getValueType(0) == MVT::i16 ||
17750 (Subtarget.hasLDBRX() && Is64BitBswapOn64BitTgt))) {
17761 DAG.
getVTList(
N->getValueType(0) == MVT::i64 ?
17762 MVT::i64 : MVT::i32, MVT::Other),
17763 Ops, LD->getMemoryVT(), LD->getMemOperand());
17767 if (
N->getValueType(0) == MVT::i16)
17784 !IsSingleUseNormalLd)
17789 if (!LD->isSimple())
17791 SDValue BasePtr = LD->getBasePtr();
17793 LD->getPointerInfo(), LD->getAlign());
17798 LD->getMemOperand(), 4, 4);
17802 if (Subtarget.isLittleEndian())
17808 Hi.getOperand(0).getValue(1),
Lo.getOperand(0).getValue(1));
17817 if (!
N->getOperand(0).hasOneUse() &&
17818 !
N->getOperand(1).hasOneUse() &&
17819 !
N->getOperand(2).hasOneUse()) {
17822 SDNode *VCMPrecNode =
nullptr;
17824 SDNode *LHSN =
N->getOperand(0).getNode();
17826 if (
User->getOpcode() == PPCISD::VCMP_rec &&
17830 VCMPrecNode =
User;
17842 SDNode *FlagUser =
nullptr;
17844 FlagUser ==
nullptr; ++UI) {
17845 assert(UI != VCMPrecNode->
use_end() &&
"Didn't find user!");
17858 return SDValue(VCMPrecNode, 0);
17869 SDValue LHS =
N->getOperand(2), RHS =
N->getOperand(3);
17880 auto RHSAPInt = RHS->getAsAPIntVal();
17881 if (!RHSAPInt.isIntN(64))
17884 unsigned Val = RHSAPInt.getZExtValue();
17885 auto isImpossibleCompare = [&]() {
17888 if (Val != 0 && Val != 1) {
17890 return N->getOperand(0);
17893 N->getOperand(0),
N->getOperand(4));
17898 unsigned StoreWidth = 0;
17901 if (
SDValue Impossible = isImpossibleCompare())
17913 SDValue Ops[] = {LHS.getOperand(0), LHS.getOperand(2), LHS.getOperand(3),
17917 PPCISD::STORE_COND, dl,
17919 MemNode->getMemoryVT(), MemNode->getMemOperand());
17923 if (
N->getOperand(0) == LHS.getValue(1))
17934 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other, InChain,
17936 DAG.
getRegister(PPC::CR0, MVT::i32),
N->getOperand(4),
17942 assert(isDot &&
"Can't compare against a vector result!");
17944 if (
SDValue Impossible = isImpossibleCompare())
17947 bool BranchOnWhenPredTrue = (CC ==
ISD::SETEQ) ^ (Val == 0);
17954 EVT VTs[] = { LHS.getOperand(2).getValueType(), MVT::Glue };
17959 switch (LHS.getConstantOperandVal(1)) {
17975 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other,
N->getOperand(0),
17978 N->getOperand(4), CompNode.
getValue(1));
17983 return DAGCombineBuildVector(
N, DCI);
17996 EVT VT =
N->getValueType(0);
17997 if (VT == MVT::i64 && !Subtarget.isPPC64())
17999 if ((VT != MVT::i32 && VT != MVT::i64) ||
18007 unsigned Lg2 = (IsNegPow2 ? -Divisor : Divisor).
countr_zero();
18027 const APInt &DemandedElts,
18029 unsigned Depth)
const {
18031 switch (
Op.getOpcode()) {
18033 case PPCISD::LBRX: {
18036 Known.
Zero = 0xFFFF0000;
18039 case PPCISD::ADDE: {
18040 if (
Op.getResNo() == 0) {
18045 Known.
Zero = ~1ULL;
18050 switch (
Op.getConstantOperandVal(0)) {
18052 case Intrinsic::ppc_altivec_vcmpbfp_p:
18053 case Intrinsic::ppc_altivec_vcmpeqfp_p:
18054 case Intrinsic::ppc_altivec_vcmpequb_p:
18055 case Intrinsic::ppc_altivec_vcmpequh_p:
18056 case Intrinsic::ppc_altivec_vcmpequw_p:
18057 case Intrinsic::ppc_altivec_vcmpequd_p:
18058 case Intrinsic::ppc_altivec_vcmpequq_p:
18059 case Intrinsic::ppc_altivec_vcmpgefp_p:
18060 case Intrinsic::ppc_altivec_vcmpgtfp_p:
18061 case Intrinsic::ppc_altivec_vcmpgtsb_p:
18062 case Intrinsic::ppc_altivec_vcmpgtsh_p:
18063 case Intrinsic::ppc_altivec_vcmpgtsw_p:
18064 case Intrinsic::ppc_altivec_vcmpgtsd_p:
18065 case Intrinsic::ppc_altivec_vcmpgtsq_p:
18066 case Intrinsic::ppc_altivec_vcmpgtub_p:
18067 case Intrinsic::ppc_altivec_vcmpgtuh_p:
18068 case Intrinsic::ppc_altivec_vcmpgtuw_p:
18069 case Intrinsic::ppc_altivec_vcmpgtud_p:
18070 case Intrinsic::ppc_altivec_vcmpgtuq_p:
18077 switch (
Op.getConstantOperandVal(1)) {
18080 case Intrinsic::ppc_load2r:
18082 Known.
Zero = 0xFFFF0000;
18091 switch (Subtarget.getCPUDirective()) {
18113 if (
ML->getLoopDepth() > 1 &&
ML->getSubLoops().empty())
18122 for (
auto I =
ML->block_begin(), IE =
ML->block_end();
I != IE; ++
I)
18124 LoopSize +=
TII->getInstSizeInBytes(J);
18129 if (LoopSize > 16 && LoopSize <= 32)
18143 if (Constraint.
size() == 1) {
18144 switch (Constraint[0]) {
18162 }
else if (Constraint ==
"wc") {
18164 }
else if (Constraint ==
"wa" || Constraint ==
"wd" ||
18165 Constraint ==
"wf" || Constraint ==
"ws" ||
18166 Constraint ==
"wi" || Constraint ==
"ww") {
18179 Value *CallOperandVal =
info.CallOperandVal;
18182 if (!CallOperandVal)
18189 else if ((
StringRef(constraint) ==
"wa" ||
18201 switch (*constraint) {
18231std::pair<unsigned, const TargetRegisterClass *>
18235 if (Constraint.
size() == 1) {
18237 switch (Constraint[0]) {
18239 if (VT == MVT::i64 && Subtarget.isPPC64())
18240 return std::make_pair(0U, &PPC::G8RC_NOX0RegClass);
18241 return std::make_pair(0U, &PPC::GPRC_NOR0RegClass);
18243 if (VT == MVT::i64 && Subtarget.isPPC64())
18244 return std::make_pair(0U, &PPC::G8RCRegClass);
18245 return std::make_pair(0U, &PPC::GPRCRegClass);
18251 if (Subtarget.hasSPE()) {
18252 if (VT == MVT::f32 || VT == MVT::i32)
18253 return std::make_pair(0U, &PPC::GPRCRegClass);
18254 if (VT == MVT::f64 || VT == MVT::i64)
18255 return std::make_pair(0U, &PPC::SPERCRegClass);
18257 if (VT == MVT::f32 || VT == MVT::i32)
18258 return std::make_pair(0U, &PPC::F4RCRegClass);
18259 if (VT == MVT::f64 || VT == MVT::i64)
18260 return std::make_pair(0U, &PPC::F8RCRegClass);
18264 if (Subtarget.hasAltivec() && VT.
isVector())
18265 return std::make_pair(0U, &PPC::VRRCRegClass);
18266 else if (Subtarget.hasVSX())
18268 return std::make_pair(0U, &PPC::VFRCRegClass);
18271 return std::make_pair(0U, &PPC::CRRCRegClass);
18273 }
else if (Constraint ==
"wc" && Subtarget.useCRBits()) {
18275 return std::make_pair(0U, &PPC::CRBITRCRegClass);
18276 }
else if ((Constraint ==
"wa" || Constraint ==
"wd" ||
18277 Constraint ==
"wf" || Constraint ==
"wi") &&
18278 Subtarget.hasVSX()) {
18282 return std::make_pair(0U, &PPC::VSRCRegClass);
18283 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18284 return std::make_pair(0U, &PPC::VSSRCRegClass);
18285 return std::make_pair(0U, &PPC::VSFRCRegClass);
18286 }
else if ((Constraint ==
"ws" || Constraint ==
"ww") && Subtarget.hasVSX()) {
18287 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18288 return std::make_pair(0U, &PPC::VSSRCRegClass);
18290 return std::make_pair(0U, &PPC::VSFRCRegClass);
18291 }
else if (Constraint ==
"lr") {
18292 if (VT == MVT::i64)
18293 return std::make_pair(0U, &PPC::LR8RCRegClass);
18295 return std::make_pair(0U, &PPC::LRRCRegClass);
18300 if (Constraint[0] ==
'{' && Constraint[Constraint.
size() - 1] ==
'}') {
18304 if (Constraint.
size() > 3 && Constraint[1] ==
'v' && Constraint[2] ==
's') {
18305 int VSNum = atoi(Constraint.
data() + 3);
18306 assert(VSNum >= 0 && VSNum <= 63 &&
18307 "Attempted to access a vsr out of range");
18309 return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass);
18310 return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass);
18315 if (Constraint.
size() > 3 && Constraint[1] ==
'f') {
18316 int RegNum = atoi(Constraint.
data() + 2);
18317 if (RegNum > 31 || RegNum < 0)
18319 if (VT == MVT::f32 || VT == MVT::i32)
18320 return Subtarget.hasSPE()
18321 ? std::make_pair(PPC::R0 + RegNum, &PPC::GPRCRegClass)
18322 : std::make_pair(PPC::F0 + RegNum, &PPC::F4RCRegClass);
18323 if (VT == MVT::f64 || VT == MVT::i64)
18324 return Subtarget.hasSPE()
18325 ? std::make_pair(PPC::S0 + RegNum, &PPC::SPERCRegClass)
18326 : std::make_pair(PPC::F0 + RegNum, &PPC::F8RCRegClass);
18330 std::pair<unsigned, const TargetRegisterClass *> R =
18339 if (R.first && VT == MVT::i64 && Subtarget.isPPC64() &&
18340 PPC::GPRCRegClass.contains(R.first))
18341 return std::make_pair(
TRI->getMatchingSuperReg(R.first,
18342 PPC::sub_32, &PPC::G8RCRegClass),
18343 &PPC::G8RCRegClass);
18346 if (!R.second &&
StringRef(
"{cc}").equals_insensitive(Constraint)) {
18347 R.first = PPC::CR0;
18348 R.second = &PPC::CRRCRegClass;
18352 if (Subtarget.isAIXABI() && !TM.getAIXExtendedAltivecABI()) {
18353 if (((R.first >= PPC::V20 && R.first <= PPC::V31) ||
18354 (R.first >= PPC::VF20 && R.first <= PPC::VF31)) &&
18355 (R.second == &PPC::VSRCRegClass || R.second == &PPC::VSFRCRegClass))
18356 errs() <<
"warning: vector registers 20 to 32 are reserved in the "
18357 "default AIX AltiVec ABI and cannot be used\n";
18367 std::vector<SDValue> &
Ops,
18372 if (Constraint.
size() > 1)
18375 char Letter = Constraint[0];
18390 EVT TCVT = MVT::i64;
18431 if (Result.getNode()) {
18432 Ops.push_back(Result);
18443 if (
I.getNumOperands() <= 1)
18447 auto IntrinsicID =
Ops[1].getNode()->getAsZExtVal();
18448 if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw &&
18449 IntrinsicID != Intrinsic::ppc_trapd && IntrinsicID != Intrinsic::ppc_trap)
18452 if (
MDNode *MDN =
I.getMetadata(LLVMContext::MD_annotation))
18468 if (Ty->isVectorTy() && AM.
BaseOffs != 0 && !Subtarget.hasP9Vector())
18480 switch (AM.
Scale) {
18508 unsigned Depth =
Op.getConstantOperandVal(0);
18532 SDValue RetAddrFI = getReturnAddrFrameIndex(DAG);
18540 unsigned Depth =
Op.getConstantOperandVal(0);
18547 bool isPPC64 = PtrVT == MVT::i64;
18553 FrameReg = isPPC64 ? PPC::X1 : PPC::R1;
18555 FrameReg = isPPC64 ? PPC::FP8 : PPC::FP;
18561 FrameAddr, MachinePointerInfo());
18565#define GET_REGISTER_MATCHER
18566#include "PPCGenAsmMatcher.inc"
18570 bool IsPPC64 = Subtarget.isPPC64();
18582 if ((IsPPC64 && Reg == PPC::R2) || Reg == PPC::R0)
18588 Reg = Reg.id() - PPC::R0 + PPC::X0;
18595 if (Subtarget.is32BitELFABI())
18600 if (Subtarget.isAIXABI())
18614 return Subtarget.isGVIndirectSymbol(
G->getGlobal());
18630 case Intrinsic::ppc_atomicrmw_xchg_i128:
18631 case Intrinsic::ppc_atomicrmw_add_i128:
18632 case Intrinsic::ppc_atomicrmw_sub_i128:
18633 case Intrinsic::ppc_atomicrmw_nand_i128:
18634 case Intrinsic::ppc_atomicrmw_and_i128:
18635 case Intrinsic::ppc_atomicrmw_or_i128:
18636 case Intrinsic::ppc_atomicrmw_xor_i128:
18637 case Intrinsic::ppc_cmpxchg_i128:
18639 Info.memVT = MVT::i128;
18640 Info.ptrVal =
I.getArgOperand(0);
18642 Info.align =
Align(16);
18646 case Intrinsic::ppc_atomic_load_i128:
18648 Info.memVT = MVT::i128;
18649 Info.ptrVal =
I.getArgOperand(0);
18651 Info.align =
Align(16);
18654 case Intrinsic::ppc_atomic_store_i128:
18656 Info.memVT = MVT::i128;
18657 Info.ptrVal =
I.getArgOperand(2);
18659 Info.align =
Align(16);
18662 case Intrinsic::ppc_altivec_lvx:
18663 case Intrinsic::ppc_altivec_lvxl:
18664 case Intrinsic::ppc_altivec_lvebx:
18665 case Intrinsic::ppc_altivec_lvehx:
18666 case Intrinsic::ppc_altivec_lvewx:
18667 case Intrinsic::ppc_vsx_lxvd2x:
18668 case Intrinsic::ppc_vsx_lxvw4x:
18669 case Intrinsic::ppc_vsx_lxvd2x_be:
18670 case Intrinsic::ppc_vsx_lxvw4x_be:
18671 case Intrinsic::ppc_vsx_lxvl:
18672 case Intrinsic::ppc_vsx_lxvll: {
18675 case Intrinsic::ppc_altivec_lvebx:
18678 case Intrinsic::ppc_altivec_lvehx:
18681 case Intrinsic::ppc_altivec_lvewx:
18684 case Intrinsic::ppc_vsx_lxvd2x:
18685 case Intrinsic::ppc_vsx_lxvd2x_be:
18695 Info.ptrVal =
I.getArgOperand(0);
18698 Info.align =
Align(1);
18702 case Intrinsic::ppc_altivec_stvx:
18703 case Intrinsic::ppc_altivec_stvxl:
18704 case Intrinsic::ppc_altivec_stvebx:
18705 case Intrinsic::ppc_altivec_stvehx:
18706 case Intrinsic::ppc_altivec_stvewx:
18707 case Intrinsic::ppc_vsx_stxvd2x:
18708 case Intrinsic::ppc_vsx_stxvw4x:
18709 case Intrinsic::ppc_vsx_stxvd2x_be:
18710 case Intrinsic::ppc_vsx_stxvw4x_be:
18711 case Intrinsic::ppc_vsx_stxvl:
18712 case Intrinsic::ppc_vsx_stxvll: {
18715 case Intrinsic::ppc_altivec_stvebx:
18718 case Intrinsic::ppc_altivec_stvehx:
18721 case Intrinsic::ppc_altivec_stvewx:
18724 case Intrinsic::ppc_vsx_stxvd2x:
18725 case Intrinsic::ppc_vsx_stxvd2x_be:
18735 Info.ptrVal =
I.getArgOperand(1);
18738 Info.align =
Align(1);
18742 case Intrinsic::ppc_stdcx:
18743 case Intrinsic::ppc_stwcx:
18744 case Intrinsic::ppc_sthcx:
18745 case Intrinsic::ppc_stbcx: {
18747 auto Alignment =
Align(8);
18749 case Intrinsic::ppc_stdcx:
18752 case Intrinsic::ppc_stwcx:
18754 Alignment =
Align(4);
18756 case Intrinsic::ppc_sthcx:
18758 Alignment =
Align(2);
18760 case Intrinsic::ppc_stbcx:
18762 Alignment =
Align(1);
18767 Info.ptrVal =
I.getArgOperand(0);
18769 Info.align = Alignment;
18784 const AttributeList &FuncAttributes)
const {
18788 if (Subtarget.hasAltivec() &&
Op.size() >= 16) {
18789 if (
Op.isMemset() && Subtarget.hasVSX()) {
18794 if (TailSize > 2 && TailSize <= 4) {
18799 if (
Op.isAligned(
Align(16)) || Subtarget.hasP8Vector())
18804 if (Subtarget.isPPC64()) {
18815 assert(Ty->isIntegerTy());
18817 unsigned BitSize = Ty->getPrimitiveSizeInBits();
18818 return !(BitSize == 0 || BitSize > 64);
18826 return NumBits1 == 64 && NumBits2 == 32;
18834 return NumBits1 == 64 && NumBits2 == 32;
18841 EVT MemVT = LD->getMemoryVT();
18842 if ((MemVT == MVT::i1 || MemVT == MVT::i8 || MemVT == MVT::i16 ||
18843 (Subtarget.isPPC64() && MemVT == MVT::i32)) &&
18859 "invalid fpext types");
18861 if (DestVT == MVT::f128)
18876 unsigned *
Fast)
const {
18890 !Subtarget.allowsUnalignedFPAccess())
18894 if (Subtarget.hasVSX()) {
18895 if (VT != MVT::v2f64 && VT != MVT::v2i64 &&
18896 VT != MVT::v4f32 && VT != MVT::v4i32)
18903 if (VT == MVT::ppcf128)
18918 if (!ConstNode->getAPIntValue().isSignedIntN(64))
18926 int64_t Imm = ConstNode->getSExtValue();
18947 if (Subtarget.hasSPE() || Subtarget.useSoftFloat())
18949 switch (Ty->getScalarType()->getTypeID()) {
18954 return Subtarget.hasP9Vector();
18962 if (!
I->hasOneUse())
18966 assert(
User &&
"A single use instruction with no uses.");
18968 switch (
I->getOpcode()) {
18969 case Instruction::FMul: {
18971 if (
User->getOpcode() != Instruction::FSub &&
18972 User->getOpcode() != Instruction::FAdd)
18979 bool AllowContract =
I->getFastMathFlags().allowContract() &&
18980 User->getFastMathFlags().allowContract();
18986 case Instruction::Load: {
18999 if (
User->getOpcode() != Instruction::Store)
19019 static const MCPhysReg ScratchRegs[] = {
19020 PPC::X12, PPC::LR8, PPC::CTR8, 0
19023 return ScratchRegs;
19027 const Constant *PersonalityFn)
const {
19028 return Subtarget.isPPC64() ? PPC::X3 : PPC::R3;
19032 const Constant *PersonalityFn)
const {
19033 return Subtarget.isPPC64() ? PPC::X4 : PPC::R4;
19038 EVT VT ,
unsigned DefinedValues)
const {
19039 if (VT == MVT::v2i64)
19040 return Subtarget.hasDirectMove();
19042 if (Subtarget.hasVSX())
19069 return PPCISD::FNMSUB;
19070 case PPCISD::FNMSUB:
19076 bool LegalOps,
bool OptForSize,
19078 unsigned Depth)
const {
19082 unsigned Opc =
Op.getOpcode();
19083 EVT VT =
Op.getValueType();
19087 case PPCISD::FNMSUB:
19108 if (Flags.hasNoSignedZeros() ||
Options.NoSignedZerosFPMath) {
19112 N0Cost,
Depth + 1);
19116 N1Cost,
Depth + 1);
19118 if (NegN0 && N0Cost <= N1Cost) {
19119 Cost = std::min(N0Cost, N2Cost);
19121 }
else if (NegN1) {
19122 Cost = std::min(N1Cost, N2Cost);
19142 if (M.getStackProtectorGuard() ==
"tls" || Subtarget.isTargetLinux())
19148 bool ForCodeSize)
const {
19149 if (!VT.
isSimple() || !Subtarget.hasVSX())
19159 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
19164 APSInt IntResult(16,
false);
19169 if (IsExact && IntResult <= 15 && IntResult >= -16)
19171 return Imm.isZero();
19174 return Imm.isPosZero();
19186 unsigned Opcode =
N->getOpcode();
19206 if (Mask->getZExtValue() == OpSizeInBits - 1)
19213 DAGCombinerInfo &DCI)
const {
19214 EVT VT =
N->getValueType(0);
19217 unsigned Opc =
N->getOpcode();
19219 "Unexpected opcode.");
19226 if (EltTy != MVT::i64 && EltTy != MVT::i32)
19230 uint64_t SplatBits = 0;
19231 bool AddSplatCase =
false;
19235 AddSplatCase =
true;
19239 if (!AddSplatCase) {
19243 unsigned SplatBitSize;
19245 APInt APSplatBits, APSplatUndef;
19247 bool BVNIsConstantSplat =
19249 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
19250 if (!BVNIsConstantSplat || SplatBitSize != EltBits)
19261 if (SplatBits == (EltBits - 1)) {
19265 NewOpc = PPCISD::SHL;
19268 NewOpc = PPCISD::SRL;
19271 NewOpc = PPCISD::SRA;
19275 return DCI.DAG.getNode(NewOpc,
DL, VT, N0, SplatOnes);
19283 if (EltTy != MVT::i64 || SplatBits != 1)
19286 return DCI.DAG.getNode(
ISD::ADD, SDLoc(
N), VT, N0, N0);
19289SDValue PPCTargetLowering::combineSHL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19293 if (
N->getValueType(0).isVector())
19294 return combineVectorShift(
N, DCI);
19298 if (!Subtarget.isISA3_0() || !Subtarget.isPPC64() ||
19301 N->getValueType(0) != MVT::i64)
19316 ShiftBy = DCI.DAG.getConstant(CN1->
getZExtValue(),
DL, MVT::i32);
19322SDValue PPCTargetLowering::combineSRA(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19326 if (
N->getValueType(0).isVector())
19327 return combineVectorShift(
N, DCI);
19332SDValue PPCTargetLowering::combineSRL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19336 if (
N->getValueType(0).isVector())
19337 return combineVectorShift(
N, DCI);
19348 if (!Subtarget.isPPC64())
19354 auto isZextOfCompareWithConstant = [](
SDValue Op) {
19356 Op.getValueType() != MVT::i64)
19360 if (Cmp.getOpcode() !=
ISD::SETCC || !Cmp.hasOneUse() ||
19361 Cmp.getOperand(0).getValueType() != MVT::i64)
19365 int64_t NegConstant = 0 -
Constant->getSExtValue();
19374 bool LHSHasPattern = isZextOfCompareWithConstant(
LHS);
19375 bool RHSHasPattern = isZextOfCompareWithConstant(
RHS);
19378 if (LHSHasPattern && !RHSHasPattern)
19380 else if (!LHSHasPattern && !RHSHasPattern)
19384 EVT CarryType = Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
19387 SDValue Z = Cmp.getOperand(0);
19389 int64_t NegConstant = 0 -
Constant->getSExtValue();
19402 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
19420 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
19450 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
19453 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
19461 if (!GSDN || !ConstNode)
19489 EVT VT =
N->getValueType(0);
19490 if (!Subtarget.hasVSX())
19494 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
19506 unsigned NumOfEles =
RHS.getNumOperands();
19507 for (
unsigned i = 0; i < NumOfEles; ++i) {
19509 if (!CN || CN->getSExtValue() != 1)
19524SDValue PPCTargetLowering::combineADD(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19546 DAGCombinerInfo &DCI)
const {
19548 if (Subtarget.useCRBits()) {
19550 if (
SDValue CRTruncValue = DAGCombineTruncBoolExt(
N, DCI))
19551 return CRTruncValue;
19558 if (Op0.
getValueType() != MVT::i128 ||
N->getValueType(0) != MVT::i64)
19561 int EltToExtract = DCI.DAG.getDataLayout().isBigEndian() ? 1 : 0;
19571 EltToExtract = EltToExtract ? 0 : 1;
19581 return DCI.DAG.getNode(
19583 DCI.DAG.getTargetConstant(EltToExtract, dl, MVT::i32));
19588SDValue PPCTargetLowering::combineMUL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19589 SelectionDAG &DAG = DCI.DAG;
19592 if (!ConstOpOrElement)
19600 auto IsProfitable = [
this](
bool IsNeg,
bool IsAddOne, EVT VT) ->
bool {
19601 switch (this->Subtarget.getCPUDirective()) {
19624 return IsAddOne && IsNeg ? VT.
isVector() :
true;
19628 EVT VT =
N->getValueType(0);
19633 APInt MulAmtAbs = MulAmt.
abs();
19635 if ((MulAmtAbs - 1).isPowerOf2()) {
19639 if (!IsProfitable(IsNeg,
true, VT))
19652 }
else if ((MulAmtAbs + 1).isPowerOf2()) {
19656 if (!IsProfitable(IsNeg,
false, VT))
19677 DAGCombinerInfo &DCI)
const {
19681 SDNodeFlags
Flags =
N->getFlags();
19682 EVT VT =
N->getValueType(0);
19683 SelectionDAG &DAG = DCI.DAG;
19685 unsigned Opc =
N->getOpcode();
19687 bool LegalOps = !DCI.isBeforeLegalizeOps();
19695 if (!
Flags.hasNoSignedZeros() && !
Options.NoSignedZerosFPMath)
19711bool PPCTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
19713 if (!Subtarget.is64BitELFABI())
19723 if (!TM.Options.GuaranteedTailCallOpt &&
DisableSCO)
19728 if (!Callee ||
Callee->isVarArg())
19741bool PPCTargetLowering::
19742isMaskAndCmp0FoldingBeneficial(
const Instruction &AndI)
const {
19747 if (CI->getBitWidth() > 64)
19749 int64_t ConstVal = CI->getZExtValue();
19751 (
isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF));
19760PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(
unsigned Flags)
const {
19766 if ((Flags & FlagSet) == FlagSet)
19769 if ((Flags & FlagSet) == FlagSet)
19772 if ((Flags & FlagSet) == FlagSet)
19775 if ((Flags & FlagSet) == FlagSet)
19796 if ((FrameIndexAlign % 4) != 0)
19797 FlagSet &=
~PPC::MOF_RPlusSImm16Mult4;
19798 if ((FrameIndexAlign % 16) != 0)
19799 FlagSet &=
~PPC::MOF_RPlusSImm16Mult16;
19803 if ((FrameIndexAlign % 4) == 0)
19805 if ((FrameIndexAlign % 16) == 0)
19818 auto SetAlignFlagsForImm = [&](
uint64_t Imm) {
19819 if ((Imm & 0x3) == 0)
19821 if ((Imm & 0xf) == 0)
19827 const APInt &ConstImm = CN->getAPIntValue();
19846 const APInt &ConstImm = CN->getAPIntValue();
19856 }
else if (
RHS.getOpcode() == PPCISD::Lo && !
RHS.getConstantOperandVal(1))
19867 return (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR ||
19876unsigned PPCTargetLowering::computeMOFlags(
const SDNode *Parent,
SDValue N,
19881 if (!Subtarget.hasP9Vector())
19886 if (Subtarget.hasPrefixInstrs())
19889 if (Subtarget.hasSPE())
19898 unsigned ParentOp = Parent->
getOpcode();
19902 if ((
ID == Intrinsic::ppc_vsx_lxvp) || (
ID == Intrinsic::ppc_vsx_stxvp)) {
19903 SDValue IntrinOp = (
ID == Intrinsic::ppc_vsx_lxvp)
19915 if (LSB->isIndexed())
19921 assert(MN &&
"Parent should be a MemSDNode!");
19926 "Not expecting scalar integers larger than 16 bytes!");
19929 else if (
Size == 32)
19936 else if (
Size == 256) {
19937 assert(Subtarget.pairedVectorMemops() &&
19938 "256-bit vectors are only available when paired vector memops is "
19946 else if (MemVT == MVT::f128 || MemVT.
isVector())
19977 FlagSet &= ~PPC::MOF_NoExt;
19982 bool IsNonP1034BitConst =
19986 IsNonP1034BitConst)
19999 int16_t ForceXFormImm = 0;
20002 Disp =
N.getOperand(0);
20003 Base =
N.getOperand(1);
20014 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
20015 Disp =
N.getOperand(0);
20016 Base =
N.getOperand(1);
20021 Disp = DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20030 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
20036 if (PartVT == MVT::f64 &&
20037 (ValVT == MVT::i32 || ValVT == MVT::i16 || ValVT == MVT::i8)) {
20046SDValue PPCTargetLowering::lowerToLibCall(
const char *LibCallName,
SDValue Op,
20050 EVT RetVT =
Op.getValueType();
20057 EVT ArgVT =
N.getValueType();
20061 Entry.IsZExt = !Entry.IsSExt;
20062 Args.push_back(Entry);
20070 (RetTy ==
F.getReturnType() ||
F.getReturnType()->isVoidTy());
20083SDValue PPCTargetLowering::lowerLibCallBasedOnType(
20084 const char *LibCallFloatName,
const char *LibCallDoubleName,
SDValue Op,
20086 if (
Op.getValueType() == MVT::f32)
20087 return lowerToLibCall(LibCallFloatName,
Op, DAG);
20089 if (
Op.getValueType() == MVT::f64)
20090 return lowerToLibCall(LibCallDoubleName,
Op, DAG);
20095bool PPCTargetLowering::isLowringToMASSFiniteSafe(
SDValue Op)
const {
20096 SDNodeFlags
Flags =
Op.getNode()->getFlags();
20097 return isLowringToMASSSafe(
Op) &&
Flags.hasNoSignedZeros() &&
20101bool PPCTargetLowering::isLowringToMASSSafe(
SDValue Op)
const {
20102 return Op.getNode()->getFlags().hasApproximateFuncs();
20105bool PPCTargetLowering::isScalarMASSConversionEnabled()
const {
20109SDValue PPCTargetLowering::lowerLibCallBase(
const char *LibCallDoubleName,
20110 const char *LibCallFloatName,
20111 const char *LibCallDoubleNameFinite,
20112 const char *LibCallFloatNameFinite,
20115 if (!isScalarMASSConversionEnabled() || !isLowringToMASSSafe(
Op))
20118 if (!isLowringToMASSFiniteSafe(
Op))
20119 return lowerLibCallBasedOnType(LibCallFloatName, LibCallDoubleName,
Op,
20122 return lowerLibCallBasedOnType(LibCallFloatNameFinite,
20123 LibCallDoubleNameFinite,
Op, DAG);
20127 return lowerLibCallBase(
"__xl_pow",
"__xl_powf",
"__xl_pow_finite",
20128 "__xl_powf_finite",
Op, DAG);
20132 return lowerLibCallBase(
"__xl_sin",
"__xl_sinf",
"__xl_sin_finite",
20133 "__xl_sinf_finite",
Op, DAG);
20137 return lowerLibCallBase(
"__xl_cos",
"__xl_cosf",
"__xl_cos_finite",
20138 "__xl_cosf_finite",
Op, DAG);
20142 return lowerLibCallBase(
"__xl_log",
"__xl_logf",
"__xl_log_finite",
20143 "__xl_logf_finite",
Op, DAG);
20147 return lowerLibCallBase(
"__xl_log10",
"__xl_log10f",
"__xl_log10_finite",
20148 "__xl_log10f_finite",
Op, DAG);
20152 return lowerLibCallBase(
"__xl_exp",
"__xl_expf",
"__xl_exp_finite",
20153 "__xl_expf_finite",
Op, DAG);
20178 unsigned Flags = computeMOFlags(Parent,
N, DAG);
20189 assert(Subtarget.isUsingPCRelativeCalls() &&
20190 "Must be using PC-Relative calls when a valid PC-Relative node is "
20220 Disp =
N.getOperand(1).getOperand(0);
20225 Base =
N.getOperand(0);
20233 EVT CNType = CN->getValueType(0);
20234 uint64_t CNImm = CN->getZExtValue();
20245 if ((CNType == MVT::i32 ||
isInt<32>(CNImm)) &&
20247 int32_t Addr = (int32_t)CNImm;
20252 uint32_t LIS = CNType == MVT::i32 ? PPC::LIS : PPC::LIS8;
20268 unsigned Opcode =
N.getOpcode();
20276 Base =
N.getOperand(0);
20295 Base = FI ?
N :
N.getOperand(1);
20296 Disp = FI ? DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20307 bool IsVarArg)
const {
20317 return Subtarget.isPPC64() && Subtarget.hasQuadwordAtomics();
20354 return Intrinsic::ppc_atomicrmw_xchg_i128;
20356 return Intrinsic::ppc_atomicrmw_add_i128;
20358 return Intrinsic::ppc_atomicrmw_sub_i128;
20360 return Intrinsic::ppc_atomicrmw_and_i128;
20362 return Intrinsic::ppc_atomicrmw_or_i128;
20364 return Intrinsic::ppc_atomicrmw_xor_i128;
20366 return Intrinsic::ppc_atomicrmw_nand_i128;
20374 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
20376 assert(ValTy->getPrimitiveSizeInBits() == 128);
20378 Value *IncrLo = Builder.CreateTrunc(Incr, Int64Ty,
"incr_lo");
20380 Builder.CreateTrunc(Builder.CreateLShr(Incr, 64), Int64Ty,
"incr_hi");
20381 Value *LoHi = Builder.CreateIntrinsic(
20383 {AlignedAddr, IncrLo, IncrHi});
20384 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
20385 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
20386 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
20387 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
20388 return Builder.CreateOr(
20389 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
20396 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
20398 assert(ValTy->getPrimitiveSizeInBits() == 128);
20402 Value *CmpLo = Builder.CreateTrunc(CmpVal, Int64Ty,
"cmp_lo");
20404 Builder.CreateTrunc(Builder.CreateLShr(CmpVal, 64), Int64Ty,
"cmp_hi");
20405 Value *NewLo = Builder.CreateTrunc(NewVal, Int64Ty,
"new_lo");
20407 Builder.CreateTrunc(Builder.CreateLShr(NewVal, 64), Int64Ty,
"new_hi");
20410 Builder.CreateCall(IntCmpXchg, {AlignedAddr, CmpLo, CmpHi, NewLo, NewHi});
20412 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
20413 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
20414 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
20415 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
20416 return Builder.CreateOr(
20417 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
20421 return Subtarget.useCRBits();
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static unsigned getCallOpcode(const MachineFunction &CallerF, bool IsIndirect, bool IsTailCall, std::optional< CallLowering::PtrAuthInfo > &PAI, MachineRegisterInfo &MRI)
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
static std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isLoad(int Opcode)
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
Atomic ordering constants.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
This file defines the DenseMap class.
const HexagonInstrInfo * TII
static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl)
CreateCopyOfByValArgument - Make a copy of an aggregate at address specified by "Src" to address "Dst...
Module.h This file contains the declarations for the Module class.
This defines the Use class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
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).
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static bool isConstantOrUndef(const SDValue Op)
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
cl::opt< bool > ANDIGlueBug("expose-ppc-andi-glue-bug", cl::desc("expose the ANDI glue bug on PPC"), cl::Hidden)
static SDValue getCanonicalConstSplat(uint64_t Val, unsigned SplatSize, EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getCanonicalConstSplat - Build a canonical splat immediate of Val with an element size of SplatSize.
static bool IsSelectCC(MachineInstr &MI)
static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static const TargetRegisterClass * getRegClassForSVT(MVT::SimpleValueType SVT, bool IsPPC64, bool HasP8Vector, bool HasVSX)
static bool isGPRShadowAligned(MCPhysReg Reg, Align RequiredAlign)
static SDValue DAGCombineAddc(SDNode *N, llvm::PPCTargetLowering::DAGCombinerInfo &DCI)
static bool needStackSlotPassParameters(const PPCSubtarget &Subtarget, const SmallVectorImpl< ISD::OutputArg > &Outs)
std::tuple< uint32_t, uint8_t > LXVKQPattern
static bool isAlternatingShuffMask(const ArrayRef< int > &Mask, int NumElts)
static bool isShuffleMaskInRange(const SmallVectorImpl< int > &ShuffV, int HalfVec, int LHSLastElementDefined, int RHSLastElementDefined)
static SDValue addShuffleForVecExtend(SDNode *N, SelectionDAG &DAG, SDValue Input, uint64_t Elems, uint64_t CorrectElems)
static cl::opt< bool > DisablePPCUnaligned("disable-ppc-unaligned", cl::desc("disable unaligned load/store generation on PPC"), cl::Hidden)
static SDValue combineADDToADDZE(SDNode *N, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
static bool findConsecutiveLoad(LoadSDNode *LD, SelectionDAG &DAG)
static SDValue generateEquivalentSub(SDNode *N, int Size, bool Complement, bool Swap, SDLoc &DL, SelectionDAG &DAG)
This function is called when we have proved that a SETCC node can be replaced by subtraction (and oth...
static unsigned mapArgRegToOffsetAIX(unsigned Reg, const PPCFrameLowering *FL)
static void CalculateTailCallArgDest(SelectionDAG &DAG, MachineFunction &MF, bool IsPPC64, SDValue Arg, int SPDiff, unsigned ArgOffset, SmallVectorImpl< TailCallArgumentInfo > &TailCallArguments)
CalculateTailCallArgDest - Remember Argument for later processing.
static SDValue combineADDToMAT_PCREL_ADDR(SDNode *N, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
static void setAlignFlagsForFI(SDValue N, unsigned &FlagSet, SelectionDAG &DAG)
Set alignment flags based on whether or not the Frame Index is aligned.
static bool isTOCSaveRestoreRequired(const PPCSubtarget &Subtarget)
static void updateForAIXShLibTLSModelOpt(TLSModel::Model &Model, SelectionDAG &DAG, const TargetMachine &TM)
updateForAIXShLibTLSModelOpt - Helper to initialize TLS model opt settings, and then apply the update...
static bool provablyDisjointOr(SelectionDAG &DAG, const SDValue &N)
Used when computing address flags for selecting loads and stores.
static bool callsShareTOCBase(const Function *Caller, const GlobalValue *CalleeGV, const TargetMachine &TM)
static SDValue generateSToVPermutedForVecShuffle(int ScalarSize, uint64_t ShuffleEltWidth, unsigned &NumValidElts, int FirstElt, int &LastElt, SDValue VecShuffOperand, SDValue SToVNode, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
constexpr uint64_t AIXSmallTlsPolicySizeLimit
static bool canConvertToVcmpequb(SDValue &LHS, SDValue &RHS)
static bool isPCRelNode(SDValue N)
static void LowerMemOpCallTo(SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, SDValue Arg, SDValue PtrOff, int SPDiff, unsigned ArgOffset, bool isPPC64, bool isTailCall, bool isVector, SmallVectorImpl< SDValue > &MemOpChains, SmallVectorImpl< TailCallArgumentInfo > &TailCallArguments, const SDLoc &dl)
LowerMemOpCallTo - Store the argument to the stack or remember it in case of tail calls.
static cl::opt< unsigned > PPCGatherAllAliasesMaxDepth("ppc-gather-alias-max-depth", cl::init(18), cl::Hidden, cl::desc("max depth when checking alias info in GatherAllAliases()"))
static bool areCallingConvEligibleForTCO_64SVR4(CallingConv::ID CallerCC, CallingConv::ID CalleeCC)
static const MCPhysReg FPR[]
FPR - The set of FP registers that should be allocated for arguments on Darwin and AIX.
static SDNode * isBLACompatibleAddress(SDValue Op, SelectionDAG &DAG)
isCallCompatibleAddress - Return the immediate to use if the specified 32-bit value is representable ...
static Align CalculateStackSlotAlignment(EVT ArgVT, EVT OrigVT, ISD::ArgFlagsTy Flags, unsigned PtrByteSize)
CalculateStackSlotAlignment - Calculates the alignment of this argument on the stack.
static bool IsSelect(MachineInstr &MI)
static SDValue ConvertCarryFlagToCarryValue(EVT SumType, SDValue Flag, EVT CarryType, SelectionDAG &DAG, const PPCSubtarget &STI)
static bool haveEfficientBuildVectorPattern(BuildVectorSDNode *V, bool HasDirectMove, bool HasP8Vector)
Do we have an efficient pattern in a .td file for this node?
static SDValue getSToVPermuted(SDValue OrigSToV, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
static void setUsesTOCBasePtr(MachineFunction &MF)
static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG, const SDLoc &dl, const PPCSubtarget &Subtarget)
static unsigned EnsureStackAlignment(const PPCFrameLowering *Lowering, unsigned NumBytes)
EnsureStackAlignment - Round stack frame size up from NumBytes to ensure minimum alignment required f...
static SDValue stripModuloOnShift(const TargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static bool isStoreConditional(SDValue Intrin, unsigned &StoreWidth)
static bool hasSameArgumentList(const Function *CallerFn, const CallBase &CB)
static bool isFPExtLoad(SDValue Op)
static SDValue BuildIntrinsicOp(unsigned IID, SDValue Op, SelectionDAG &DAG, const SDLoc &dl, EVT DestVT=MVT::Other)
BuildIntrinsicOp - Return a unary operator intrinsic node with the specified intrinsic ID.
static bool isConsecutiveLSLoc(SDValue Loc, EVT VT, LSBaseSDNode *Base, unsigned Bytes, int Dist, SelectionDAG &DAG)
static void StoreTailCallArgumentsToStackSlot(SelectionDAG &DAG, SDValue Chain, const SmallVectorImpl< TailCallArgumentInfo > &TailCallArgs, SmallVectorImpl< SDValue > &MemOpChains, const SDLoc &dl)
StoreTailCallArgumentsToStackSlot - Stores arguments to their stack slot.
static cl::opt< bool > UseAbsoluteJumpTables("ppc-use-absolute-jumptables", cl::desc("use absolute jump tables on ppc"), cl::Hidden)
static void setXFormForUnalignedFI(SDValue N, unsigned Flags, PPC::AddrMode &Mode)
static cl::opt< unsigned > PPCMinimumBitTestCmps("ppc-min-bit-test-cmps", cl::init(3), cl::Hidden, cl::desc("Set minimum of largest number of comparisons to use bit test for " "switch on PPC."))
static void getMaxByValAlign(Type *Ty, Align &MaxAlign, Align MaxMaxAlign)
getMaxByValAlign - Helper for getByValTypeAlignment to determine the desired ByVal argument alignment...
static bool isConsecutiveLS(SDNode *N, LSBaseSDNode *Base, unsigned Bytes, int Dist, SelectionDAG &DAG)
static bool isVMerge(ShuffleVectorSDNode *N, unsigned UnitSize, unsigned LHSStart, unsigned RHSStart)
isVMerge - Common function, used to match vmrg* shuffles.
static void getLabelAccessInfo(bool IsPIC, const PPCSubtarget &Subtarget, unsigned &HiOpFlags, unsigned &LoOpFlags, const GlobalValue *GV=nullptr)
Return true if we should reference labels using a PICBase, set the HiOpFlags and LoOpFlags to the tar...
cl::opt< bool > DisableAutoPairedVecSt("disable-auto-paired-vec-st", cl::desc("disable automatically generated 32byte paired vector stores"), cl::init(true), cl::Hidden)
static void buildCallOperands(SmallVectorImpl< SDValue > &Ops, PPCTargetLowering::CallFlags CFlags, const SDLoc &dl, SelectionDAG &DAG, SmallVector< std::pair< unsigned, SDValue >, 8 > &RegsToPass, SDValue Glue, SDValue Chain, SDValue &Callee, int SPDiff, const PPCSubtarget &Subtarget)
static cl::opt< bool > DisableInnermostLoopAlign32("disable-ppc-innermost-loop-align32", cl::desc("don't always align innermost loop to 32 bytes on ppc"), cl::Hidden)
static bool usePartialVectorLoads(SDNode *N, const PPCSubtarget &ST)
Returns true if we should use a direct load into vector instruction (such as lxsd or lfd),...
static SDValue getDataClassTest(SDValue Op, FPClassTest Mask, const SDLoc &Dl, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
static void fixupShuffleMaskForPermutedSToV(SmallVectorImpl< int > &ShuffV, int LHSFirstElt, int LHSLastElt, int RHSFirstElt, int RHSLastElt, int HalfVec, unsigned LHSNumValidElts, unsigned RHSNumValidElts, const PPCSubtarget &Subtarget)
static SDValue AdjustLength(SDValue Val, unsigned Bits, bool Left, SelectionDAG &DAG)
static cl::opt< bool > DisableSCO("disable-ppc-sco", cl::desc("disable sibling call optimization on ppc"), cl::Hidden)
static std::optional< LXVKQPattern > getPatternInfo(const APInt &FullVal)
static void fixupFuncForFI(SelectionDAG &DAG, int FrameIdx, EVT VT)
static cl::opt< bool > DisablePPCPreinc("disable-ppc-preinc", cl::desc("disable preincrement load/store generation on PPC"), cl::Hidden)
static SDValue ConvertSETCCToXori(SDNode *N, SelectionDAG &DAG)
static Intrinsic::ID getIntrinsicForAtomicRMWBinOp128(AtomicRMWInst::BinOp BinOp)
static SDValue convertFPToInt(SDValue Op, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
static unsigned CalculateStackSlotSize(EVT ArgVT, ISD::ArgFlagsTy Flags, unsigned PtrByteSize)
CalculateStackSlotSize - Calculates the size reserved for this argument on the stack.
static int CalculateTailCallSPDiff(SelectionDAG &DAG, bool isTailCall, unsigned ParamSize)
CalculateTailCallSPDiff - Get the amount the stack pointer has to be adjusted to accommodate the argu...
static Instruction * callIntrinsic(IRBuilderBase &Builder, Intrinsic::ID Id)
static void prepareIndirectCall(SelectionDAG &DAG, SDValue &Callee, SDValue &Glue, SDValue &Chain, const SDLoc &dl)
static SDValue LowerLabelRef(SDValue HiPart, SDValue LoPart, bool isPIC, SelectionDAG &DAG)
static SDValue isScalarToVec(SDValue Op)
static SDValue widenVec(SelectionDAG &DAG, SDValue Vec, const SDLoc &dl)
static cl::opt< bool > DisablePerfectShuffle("ppc-disable-perfect-shuffle", cl::desc("disable vector permute decomposition"), cl::init(true), cl::Hidden)
bool isValidMtVsrBmi(APInt &BitMask, BuildVectorSDNode &BVN, bool IsLittleEndian)
static bool getVectorCompareInfo(SDValue Intrin, int &CompareOpc, bool &isDot, const PPCSubtarget &Subtarget)
getVectorCompareInfo - Given an intrinsic, return false if it is not a vector comparison.
static unsigned invertFMAOpcode(unsigned Opc)
static SDValue combineADDToSUB(SDNode *N, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
static const SDValue * getNormalLoadInput(const SDValue &Op, bool &IsPermuted)
static bool canConvertSETCCToXori(SDNode *N)
static cl::opt< unsigned > PPCMinimumJumpTableEntries("ppc-min-jump-table-entries", cl::init(64), cl::Hidden, cl::desc("Set minimum number of entries to use a jump table on PPC"))
static bool isValidSplatLoad(const PPCSubtarget &Subtarget, const SDValue &Op, unsigned &Opcode)
static SDValue ConvertCarryValueToCarryFlag(EVT SumType, SDValue Value, SelectionDAG &DAG, const PPCSubtarget &STI)
static SDValue convertIntToFP(SDValue Op, SDValue Src, SelectionDAG &DAG, const PPCSubtarget &Subtarget, SDValue Chain=SDValue())
static void PrepareTailCall(SelectionDAG &DAG, SDValue &InGlue, SDValue &Chain, const SDLoc &dl, int SPDiff, unsigned NumBytes, SDValue LROp, SDValue FPOp, SmallVectorImpl< TailCallArgumentInfo > &TailCallArguments)
static SDValue EmitTailCallStoreFPAndRetAddr(SelectionDAG &DAG, SDValue Chain, SDValue OldRetAddr, SDValue OldFP, int SPDiff, const SDLoc &dl)
EmitTailCallStoreFPAndRetAddr - Move the frame pointer and return address to the appropriate stack sl...
static SDValue BuildVSLDOI(SDValue LHS, SDValue RHS, unsigned Amt, EVT VT, SelectionDAG &DAG, const SDLoc &dl)
BuildVSLDOI - Return a VECTOR_SHUFFLE that is a vsldoi of the specified amount.
static SDValue combineBVZEXTLOAD(SDNode *N, SelectionDAG &DAG)
static SDValue truncateScalarIntegerArg(ISD::ArgFlagsTy Flags, EVT ValVT, SelectionDAG &DAG, SDValue ArgValue, MVT LocVT, const SDLoc &dl)
static void computeFlagsForAddressComputation(SDValue N, unsigned &FlagSet, SelectionDAG &DAG)
Given a node, compute flags that are used for address computation when selecting load and store instr...
SDValue convertTwoLoadsAndCmpToVCMPEQUB(SelectionDAG &DAG, SDNode *N, const SDLoc &DL)
static SDValue getOutputChainFromCallSeq(SDValue CallSeqStart)
static bool CalculateStackSlotUsed(EVT ArgVT, EVT OrigVT, ISD::ArgFlagsTy Flags, unsigned PtrByteSize, unsigned LinkageSize, unsigned ParamAreaSize, unsigned &ArgOffset, unsigned &AvailableFPRs, unsigned &AvailableVRs)
CalculateStackSlotUsed - Return whether this argument will use its stack slot (instead of being passe...
static cl::opt< unsigned > PPCAIXTLSModelOptUseIEForLDLimit("ppc-aix-shared-lib-tls-model-opt-limit", cl::init(1), cl::Hidden, cl::desc("Set inclusive limit count of TLS local-dynamic access(es) in a " "function to use initial-exec"))
static unsigned getPPCStrictOpcode(unsigned Opc)
static void prepareDescriptorIndirectCall(SelectionDAG &DAG, SDValue &Callee, SDValue &Glue, SDValue &Chain, SDValue CallSeqStart, const CallBase *CB, const SDLoc &dl, bool hasNest, const PPCSubtarget &Subtarget)
static cl::opt< bool > DisableP10StoreForward("disable-p10-store-forward", cl::desc("disable P10 store forward-friendly conversion"), cl::Hidden, cl::init(false))
static bool isXXBRShuffleMaskHelper(ShuffleVectorSDNode *N, int Width)
static bool isFunctionGlobalAddress(const GlobalValue *CalleeGV)
static bool isSplatBV(SDValue Op)
static SDValue combineBVOfVecSExt(SDNode *N, SelectionDAG &DAG)
static cl::opt< bool > DisableILPPref("disable-ppc-ilp-pref", cl::desc("disable setting the node scheduling preference to ILP on PPC"), cl::Hidden)
static bool isNByteElemShuffleMask(ShuffleVectorSDNode *, unsigned, int)
Check that the mask is shuffling N byte elements.
static SDValue combineBVOfConsecutiveLoads(SDNode *N, SelectionDAG &DAG)
Reduce the number of loads when building a vector.
static bool isValidPCRelNode(SDValue N)
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
pre isel intrinsic Pre ISel Intrinsic Lowering
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
SI optimize exec mask operations pre RA
static const MCExpr * MaskShift(const MCExpr *Val, uint32_t Mask, uint32_t Shift, MCContext &Ctx)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, const SparcSubtarget *Subtarget)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
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")
This file describes how to lower LLVM code to machine code.
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmTowardZero
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & PPCDoubleDouble()
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
void clearBit(unsigned BitPosition)
Set a given bit to 0.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
uint64_t getZExtValue() const
Get zero extended value.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
APInt abs() const
Get the absolute value.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isNegative() const
Determine sign of this APInt.
void clearAllBits()
Set every bit to 0.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
LLVM_ABI void insertBits(const APInt &SubBits, unsigned bitPosition)
Insert the bits from a smaller APInt starting at bitPosition.
bool getBoolValue() const
Convert APInt to a boolean value.
double bitsToDouble() const
Converts APInt bits to a double.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
LLVM_ABI APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getNewValOperand()
an instruction that atomically reads a memory location, combines it with another value,...
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ UDecWrap
Decrement one until a minimum value or zero.
BinOp getOperation() const
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
int64_t getOffset() const
const BlockAddress * getBlockAddress() const
static BranchProbability getOne()
static BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
CCState - This class holds information needed while lowering arguments and return values.
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool isStrictFP() const
Determine if the call requires strict floating point semantics.
CallingConv::ID getCallingConv() const
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getCalledOperand() const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
This class represents a function call, abstracting a target machine's calling convention.
ConstantFP - Floating Point Values [float, double].
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
LLVM_ABI unsigned getLargestLegalIntTypeSizeInBits() const
Returns the size of largest legal integer type size, or 0 if none are set.
LLVM_ABI IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
int64_t getOffset() const
unsigned getTargetFlags() const
const GlobalValue * getGlobal() const
LLVM_ABI const GlobalObject * getAliaseeObject() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
void setThreadLocalMode(ThreadLocalMode Val)
bool hasHiddenVisibility() const
LLVM_ABI StringRef getSection() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Type * getValueType() const
bool hasProtectedVisibility() const
Common base class shared among various IRBuilders.
LLVM_ABI bool hasAtomicLoad() const LLVM_READONLY
Return true if this atomic instruction loads from memory.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
This is an important class for using LLVM in a threaded context.
Base class for LoadSDNode and StoreSDNode.
Tracks which library functions to use for a particular subtarget.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
TypeSize getValue() const
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
Wrapper class representing physical registers. Should be passed by value.
MCSymbolXCOFF * getQualNameSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
@ INVALID_SIMPLE_VALUE_TYPE
uint64_t getScalarSizeInBits() const
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.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
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.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
MCSymbol * getPICBaseSymbol() const
getPICBaseSymbol - Return a function-local symbol to represent the PIC base.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
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.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateImm(int64_t Val)
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getBasePtr() const
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
uint64_t getReturnSaveOffset() const
getReturnSaveOffset - Return the previous frame offset to save the return address.
unsigned getLinkageSize() const
getLinkageSize - Return the size of the PowerPC ABI linkage area.
uint64_t getTOCSaveOffset() const
getTOCSaveOffset - Return the previous frame offset to save the TOC register – 64-bit SVR4 ABI only.
PPCFunctionInfo - This class is derived from MachineFunction private PowerPC target-specific informat...
void setVarArgsNumFPR(unsigned Num)
void setReturnAddrSaveIndex(int idx)
bool isAIXFuncUseTLSIEForLD() const
int getReturnAddrSaveIndex() const
unsigned getVarArgsNumFPR() const
void setAIXFuncUseTLSIEForLD()
int getFramePointerSaveIndex() const
void setVarArgsNumGPR(unsigned Num)
void appendParameterType(ParamType Type)
int getVarArgsFrameIndex() const
void setLRStoreRequired()
bool isAIXFuncTLSModelOptInitDone() const
void setTailCallSPDelta(int size)
void setAIXFuncTLSModelOptInitDone()
bool isLRStoreRequired() const
void setMinReservedArea(unsigned size)
unsigned getVarArgsNumGPR() const
unsigned getMinReservedArea() const
void setVarArgsStackOffset(int Offset)
void setVarArgsFrameIndex(int Index)
void addLiveInAttr(Register VReg, ISD::ArgFlagsTy Flags)
This function associates attributes for each live-in virtual register.
int getVarArgsStackOffset() const
void setFramePointerSaveIndex(int Idx)
static bool hasPCRelFlag(unsigned TF)
bool is32BitELFABI() const
unsigned descriptorTOCAnchorOffset() const
MVT getScalarIntVT() const
const PPCFrameLowering * getFrameLowering() const override
bool isUsingPCRelativeCalls() const
bool usesFunctionDescriptors() const
True if the ABI is descriptor based.
MCRegister getEnvironmentPointerRegister() const
bool isLittleEndian() const
MCRegister getTOCPointerRegister() const
MCRegister getStackPointerRegister() const
bool is64BitELFABI() const
const PPCTargetMachine & getTargetMachine() const
const PPCRegisterInfo * getRegisterInfo() const override
unsigned descriptorEnvironmentPointerOffset() const
MachineBasicBlock * emitEHSjLjLongJmp(MachineInstr &MI, MachineBasicBlock *MBB) const
CCAssignFn * ccAssignFnForCall(CallingConv::ID CC, bool Return, bool IsVarArg) const
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
bool isTruncateFree(Type *Ty1, Type *Ty2) const override
isTruncateFree - Return true if it's free to truncate a value of type Ty1 to type Ty2.
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isFPExtFree(EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation is free (for instance, because single-precision floating-point numb...
PPC::AddrMode SelectForceXFormMode(SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG) const
SelectForceXFormMode - Given the specified address, force it to be represented as an indexed [r+r] op...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool hasInlineStackProbe(const MachineFunction &MF) const override
MachineBasicBlock * emitEHSjLjSetJmp(MachineInstr &MI, MachineBasicBlock *MBB) const
bool supportsTailCallFor(const CallBase *CB) const
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
MachineBasicBlock * emitProbedAlloca(MachineInstr &MI, MachineBasicBlock *MBB) const
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
MachineBasicBlock * EmitPartwordAtomicBinary(MachineInstr &MI, MachineBasicBlock *MBB, bool is8bit, unsigned Opcode, unsigned CmpOpcode=0, unsigned CmpPred=0) const
SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, NegatibleCost &Cost, unsigned Depth=0) const override
Return the newly negated expression if the cost is not expensive and set the cost in Cost to indicate...
bool SelectAddressRegImm(SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG, MaybeAlign EncodingAlignment) const
SelectAddressRegImm - Returns true if the address N can be represented by a base register plus a sign...
SDValue expandVSXLoadForLE(SDNode *N, DAGCombinerInfo &DCI) const
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
bool hasMultipleConditionRegisters(EVT VT) const override
Does the target have multiple (allocatable) condition registers that can be used to store the results...
Align getByValTypeAlignment(Type *Ty, const DataLayout &DL) const override
getByValTypeAlignment - Return the desired alignment for ByVal aggregate function arguments in the ca...
bool SelectAddressRegReg(SDValue N, SDValue &Base, SDValue &Index, SelectionDAG &DAG, MaybeAlign EncodingAlignment=std::nullopt) const
SelectAddressRegReg - Given the specified addressed, check to see if it can be more efficiently repre...
MachineBasicBlock * EmitAtomicBinary(MachineInstr &MI, MachineBasicBlock *MBB, unsigned AtomicSize, unsigned BinOpcode, unsigned CmpOpcode=0, unsigned CmpPred=0) const
SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const override
Targets may override this function to provide custom SDIV lowering for power-of-2 denominators.
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool SelectAddressRegRegOnly(SDValue N, SDValue &Base, SDValue &Index, SelectionDAG &DAG) const
SelectAddressRegRegOnly - Given the specified addressed, force it to be represented as an indexed [r+...
bool useSoftFloat() const override
SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override
Returns relocation base for the given PIC jumptable.
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
const MCPhysReg * getScratchRegisters(CallingConv::ID CC) const override
Returns a 0 terminated array of registers that can be safely used as scratch registers.
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
FastISel * createFastISel(FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo, const LibcallLoweringInfo *LibcallLowering) const override
createFastISel - This method returns a target-specific FastISel object, or null if the target does no...
bool isProfitableToHoist(Instruction *I) const override
isProfitableToHoist - Check if it is profitable to hoist instruction I to its dominator block.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint, return the type of constraint it is for this target.
const MCExpr * getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const override
This returns the relocation base for the given PIC jumptable, the same as getPICJumpTableRelocBase,...
bool shallExtractConstSplatVectorElementToStore(Type *VectorTy, unsigned ElemSizeInBits, unsigned &Index) const override
Return true if the target shall perform extract vector element and store given that the vector is kno...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
It returns EVT::Other if the type should be determined using generic target-independent logic.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue expandVSXStoreForLE(SDNode *N, DAGCombinerInfo &DCI) const
void CollectTargetIntrinsicOperands(const CallInst &I, SmallVectorImpl< SDValue > &Ops, SelectionDAG &DAG) const override
unsigned getStackProbeSize(const MachineFunction &MF) const
PPCTargetLowering(const PPCTargetMachine &TM, const PPCSubtarget &STI)
bool useLoadStackGuardNode(const Module &M) const override
Override to support customized stack guard loading.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
isFMAFasterThanFMulAndFAdd - Return true if an FMA operation is faster than a pair of fmul and fadd i...
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Is unaligned memory access allowed for the given type, and is it fast relative to software emulation.
bool shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override
bool SelectAddressRegImm34(SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG) const
Similar to the 16-bit case but for instructions that take a 34-bit displacement field (prefixed loads...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
bool isJumpTableRelative() const override
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
LowerOperation - Provide custom lowering hooks for some operations.
PPC::AddrMode SelectOptimalAddrMode(const SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG, MaybeAlign Align) const
SelectOptimalAddrMode - Based on a node N and it's Parent (a MemSDNode), compute the address flags of...
bool SelectAddressPCRel(SDValue N, SDValue &Base) const
SelectAddressPCRel - Represent the specified address as pc relative to be represented as [pc+imm].
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the ISD::SETCC ValueType
bool SelectAddressEVXRegReg(SDValue N, SDValue &Base, SDValue &Index, SelectionDAG &DAG) const
SelectAddressEVXRegReg - Given the specified addressed, check to see if it can be more efficiently re...
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
bool isAccessedAsGotIndirect(SDValue N) const
Align getPrefLoopAlignment(MachineLoop *ML) const override
Return the preferred loop alignment.
bool shouldInlineQuadwordAtomics() const
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
Common code between 32-bit and 64-bit PowerPC targets.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
This class provides iterator support for SDUse operands that use a specific SDNode.
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
LLVM_ABI void dump() const
Dump this node, for debugging.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
iterator_range< value_op_iterator > op_values() const
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const
Return true if there are exactly NUSES uses of the indicated value.
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
static use_iterator use_end()
Represents a use of a SDNode.
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
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
static SectionKind getMetadata()
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
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 SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
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 getRegister(Register Reg, EVT VT)
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,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
LLVM_ABI Align getEVTAlign(EVT MemoryVT) const
Compute the default alignment value for the given type.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
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 getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
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...
const DataLayout & getDataLayout() const
SDValue getTargetFrameIndex(int FI, EVT VT)
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const
Return true if loads are next to each other and can be merged.
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.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI SDValue getMDNode(const MDNode *MD)
Return an MDNodeSDNode which holds an MDNode.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
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)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
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 getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT)
Convert Op, which must be of integer type, to the integer type VT, by using an extension appropriate ...
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=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)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
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 getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
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...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue getMCSymbol(MCSymbol *Sym, EVT VT)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Class to represent struct types.
Information about stack frame layout on the target.
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
TargetInstrInfo - Interface to description of machine instruction set.
Provides information about what library functions are available for the current target.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
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...
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual bool shouldExpandBuildVectorWithShuffles(EVT, unsigned DefinedValues) const
void setMinimumBitTestCmps(unsigned Val)
Set the minimum of largest of number of comparisons to generate BitTest.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
MVT getVectorIdxTy(const DataLayout &DL) const
Returns the type to be used for the index operand of: ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT...
const TargetMachine & getTargetMachine() const
unsigned MaxLoadsPerMemcmp
Specify maximum number of load instructions per memcmp call.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
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...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
bool hasBigEndianPartOrdering(EVT VT, const DataLayout &DL) const
When splitting a value of the specified type into parts, does the Lo or Hi part come first?
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const
Returns the type for the shift amount of a shift opcode.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr) const
Return the preferred loop alignment.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
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 ...
virtual bool isJumpTableRelative() const
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setMinimumJumpTableEntries(unsigned Val)
Indicate the minimum number of blocks to generate jump tables.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
unsigned MaxLoadsPerMemcmpOptSize
Likewise for functions with the OptSize attribute.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
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/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
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...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
unsigned GatherAllAliasesMaxDepth
Depth that GatherAllAliases should continue looking for chain dependencies when trying to find a more...
NegatibleCost
Enum that specifies when a float negation is beneficial.
virtual bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const
Returns true if arguments should be sign-extended in lib calls.
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
void setJumpIsExpensive(bool isExpensive=true)
Tells the code generator not to expand logic operations on comparison predicates into separate sequen...
virtual MCSymbol * getFunctionEntryPointSymbol(const GlobalValue *Func, const TargetMachine &TM) const
If supported, return the function entry point symbol.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual const MCExpr * getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const
This returns the relocation base for the given PIC jumptable, the same as getPICJumpTableRelocBase,...
SDValue lowerCmpEqZeroToCtlzSrl(SDValue Op, SelectionDAG &DAG) const
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
SDValue getCheaperNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, unsigned Depth=0) const
This is the helper function to return the newly negated expression only when the cost is cheaper.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, NegatibleCost &Cost, unsigned Depth=0) const
Return the newly negated expression if the cost is not expensive and set the cost in Cost to indicate...
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
virtual SDValue getSqrtInputTest(SDValue Operand, SelectionDAG &DAG, const DenormalMode &Mode) const
Return a target-dependent comparison result if the input operand is suitable for use with a square ro...
virtual SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const
Returns relocation base for the given PIC jumptable.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
TargetLowering(const TargetLowering &)=delete
bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, SDValue &Chain) const
Check whether a given call node is in tail position within its function.
virtual SDValue getSqrtResultForDenormInput(SDValue Operand, SelectionDAG &DAG) const
Return a target-dependent result if the input operand is not suitable for use with a square root esti...
virtual bool useLoadStackGuardNode(const Module &M) const
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
virtual unsigned combineRepeatedFPDivisors() const
Indicate whether this target prefers to combine FDIVs with the same divisor.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
virtual bool isGAPlusOffset(SDNode *N, const GlobalValue *&GA, int64_t &Offset) const
Returns true (and the GlobalValue and the offset) if the node is a GlobalAddress + offset.
virtual unsigned getJumpTableEncoding() const
Return the entry encoding for a jump table in the current function.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual TargetLoweringObjectFile * getObjFileLowering() const
Reloc::Model getRelocationModel() const
Returns the code generation relocation model.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
bool getFunctionSections() const
Return true if functions should be emitted into their own section, corresponding to -ffunction-sectio...
unsigned NoInfsFPMath
NoInfsFPMath - This flag is enabled when the -enable-no-infs-fp-math flag is specified on the command...
unsigned PPCGenScalarMASSEntries
Enables scalar MASS conversions.
unsigned NoNaNsFPMath
NoNaNsFPMath - This flag is enabled when the -enable-no-nans-fp-math flag is specified on the command...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI bool isEmptyTy() const
Return true if this type is empty, that is, it has no elements or all of its elements are empty.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
@ FloatTyID
32-bit floating point type
@ DoubleTyID
64-bit floating point type
@ FP128TyID
128-bit floating point type (112-bit significand)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFunctionTy() const
True if this is an instance of FunctionType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
const ParentTy * getParent() const
self_iterator getIterator()
#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 char Args[]
Key for Kernel::Metadata::mArgs.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ 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...
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ 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.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ INIT_TRAMPOLINE
INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ 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.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ 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.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ 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.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ 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 ...
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ CALLSEQ_START
CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of a call sequence,...
@ GET_DYNAMIC_AREA_OFFSET
GET_DYNAMIC_AREA_OFFSET - get offset from native SP to the address of the most recent dynamic alloca.
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ ADJUST_TRAMPOLINE
ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isUnsignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs an unsigned comparison when used with intege...
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ MO_TLSLDM_FLAG
MO_TLSLDM_FLAG - on AIX the ML relocation type is only valid for a reference to a TOC symbol from the...
@ MO_PIC_LO_FLAG
MO_PIC_LO_FLAG = MO_PIC_FLAG | MO_LO.
@ MO_TPREL_PCREL_FLAG
MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TPREL_FLAG.
@ MO_GOT_TPREL_PCREL_FLAG
MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
@ MO_GOT_PCREL_FLAG
MO_GOT_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG.
@ MO_TLSGDM_FLAG
MO_TLSGDM_FLAG - If this bit is set the symbol reference is relative to the region handle of TLS Gene...
@ MO_PCREL_FLAG
MO_PCREL_FLAG - If this bit is set, the symbol reference is relative to the current instruction addre...
@ MO_TLSLD_FLAG
MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to TLS Local Dynamic model.
@ MO_TLS_PCREL_FLAG
MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TLS.
@ MO_PLT
On PPC, the 12 bits are not enough for all target operand flags.
@ MO_TLS
Symbol for VK_TLS fixup attached to an ADD instruction.
@ MO_TPREL_FLAG
MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to the thread pointer and the sy...
@ MO_LO
MO_LO, MO_HA - lo16(symbol) and ha16(symbol)
@ MO_GOT_TLSLD_PCREL_FLAG
MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
@ MO_PIC_HA_FLAG
MO_PIC_HA_FLAG = MO_PIC_FLAG | MO_HA.
@ MO_TLSGD_FLAG
MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to TLS General Dynamic model for ...
@ MO_GOT_TLSGD_PCREL_FLAG
MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
@ MO_PIC_FLAG
MO_PIC_FLAG - If this bit is set, the symbol reference is relative to the function's picbase,...
@ MFOCRF
R32 = MFOCRF(CRREG, INFLAG) - Represents the MFOCRF instruction.
@ VADD_SPLAT
VRRC = VADD_SPLAT Elt, EltSize - Temporary node to be expanded during instruction selection to optimi...
@ PPC32_PICGOT
GPRC = address of GLOBAL_OFFSET_TABLE.
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
@ SRA_ADDZE
The combination of sra[wd]i and addze used to implemented signed integer division by a power of 2.
Define some predicates that are used for node matching.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
SDValue get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG)
get_VSPLTI_elt - If this is a build_vector of constants which can be formed by using a vspltis[bhw] i...
bool isXXBRDShuffleMask(ShuffleVectorSDNode *N)
isXXBRDShuffleMask - Return true if this is a shuffle mask suitable for a XXBRD instruction.
bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, unsigned ShuffleKind, SelectionDAG &DAG)
isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for a VRGH* instruction with the ...
bool isVPKUDUMShuffleMask(ShuffleVectorSDNode *N, unsigned ShuffleKind, SelectionDAG &DAG)
isVPKUDUMShuffleMask - Return true if this is the shuffle mask for a VPKUDUM instruction.
bool isVMRGEOShuffleMask(ShuffleVectorSDNode *N, bool CheckEven, unsigned ShuffleKind, SelectionDAG &DAG)
isVMRGEOShuffleMask - Return true if this is a shuffle mask suitable for a VMRGEW or VMRGOW instructi...
bool isXXBRQShuffleMask(ShuffleVectorSDNode *N)
isXXBRQShuffleMask - Return true if this is a shuffle mask suitable for a XXBRQ instruction.
bool isXXBRWShuffleMask(ShuffleVectorSDNode *N)
isXXBRWShuffleMask - Return true if this is a shuffle mask suitable for a XXBRW instruction.
bool isXXPERMDIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, bool &Swap, bool IsLE)
isXXPERMDIShuffleMask - Return true if this is a shuffle mask suitable for a XXPERMDI instruction.
bool isXXBRHShuffleMask(ShuffleVectorSDNode *N)
isXXBRHShuffleMask - Return true if this is a shuffle mask suitable for a XXBRH instruction.
unsigned getSplatIdxForPPCMnemonics(SDNode *N, unsigned EltSize, SelectionDAG &DAG)
getSplatIdxForPPCMnemonics - Return the splat index as a value that is appropriate for PPC mnemonics ...
bool isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, bool &Swap, bool IsLE)
isXXSLDWIShuffleMask - Return true if this is a shuffle mask suitable for a XXSLDWI instruction.
FastISel * createFastISel(FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo, const LibcallLoweringInfo *LibcallLowering)
int isVSLDOIShuffleMask(SDNode *N, unsigned ShuffleKind, SelectionDAG &DAG)
isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift amount, otherwise return -1.
bool isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, unsigned ShuffleKind, SelectionDAG &DAG)
isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for a VRGL* instruction with the ...
bool isXXINSERTWMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, unsigned &InsertAtByte, bool &Swap, bool IsLE)
isXXINSERTWMask - Return true if this VECTOR_SHUFFLE can be handled by the XXINSERTW instruction intr...
bool isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize)
isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand specifies a splat of a singl...
bool isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, unsigned ShuffleKind, SelectionDAG &DAG)
isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a VPKUWUM instruction.
bool isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, unsigned ShuffleKind, SelectionDAG &DAG)
isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a VPKUHUM instruction.
Invariant opcodes: All instruction sets have these as their low opcodes.
@ XTY_ER
External reference.
initializer< Ty > init(const Ty &Val)
constexpr uint64_t PointerSize
aarch64 pointer size.
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
static bool isIndirectCall(const MachineInstr &MI)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool checkConvertToNonDenormSingle(APFloat &ArgAPFloat)
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
bool isIntS16Immediate(SDNode *N, int16_t &Imm)
isIntS16Immediate - This method tests to see if the node is either a 32-bit or 64-bit immediate,...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
static bool isRunOfOnes64(uint64_t Val, unsigned &MB, unsigned &ME)
bool isa_and_nonnull(const Y &Val)
bool RetCC_PPC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool CC_PPC64_ELF(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool convertToNonDenormSingle(APInt &ArgAPInt)
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
bool CC_PPC32_SVR4_ByVal(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool CC_PPC32_SVR4(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr RegState getDefRegState(bool B)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool RetCC_PPC_Cold(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
@ Success
The lock was released successfully.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
bool isIntS34Immediate(SDNode *N, int64_t &Imm)
isIntS34Immediate - This method tests if value of node given can be accurately represented as a sign ...
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
DWARFExpression::Operation Op
bool isPhysRegUsedAfter(Register Reg, MachineBasicBlock::iterator MBI)
Check if physical register Reg is used after MBI.
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
constexpr unsigned BitWidth
bool CC_PPC32_SVR4_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME)
Returns true iff Val consists of one contiguous run of 1s with any number of 0s on either side.
@ Increment
Incrementally increasing token ID.
@ Enabled
Convert any .debug_str_offsets tables to DWARF64 if needed.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This is used by foldLoadsRecursive() to capture a Root Load node which is of type or(load,...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Represent subnormal handling kind for floating point instruction inputs and outputs.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
LLVM_ABI std::string getEVTString() const
This function returns value type as a string, e.g. "i32".
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isExtended() const
Test if the given EVT is extended (as opposed to being simple).
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
unsigned getByValSize() const
void setByValSize(unsigned S)
Align getNonZeroByValAlign() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
bool isConstant() const
Returns true if we know the value of all bits.
void resetAll()
Resets the known state of all bits.
const APInt & getConstant() const
Returns the value when all bits have a known value.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Structure that collects some common arguments that get passed around between the functions for call l...
const CallingConv::ID CallConv
These are IR-level optimization flags that may be propagated to SDNodes.
void setNoFPExcept(bool b)
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setIsPostTypeLegalization(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setTailCall(bool Value=true)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
bool isBeforeLegalizeOps() const
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.