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()) {
801 if (Subtarget.hasAltivec()) {
802 for (
MVT VT : { MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
817 if (VT.getSizeInBits() <= 128 && VT.getScalarSizeInBits() <= 64) {
830 if (Subtarget.hasVSX()) {
836 if (Subtarget.hasP8Altivec() && (VT.SimpleTy != MVT::v1i128)) {
846 if (Subtarget.hasP9Altivec() && (VT.SimpleTy != MVT::v1i128))
920 if (!Subtarget.hasP8Vector()) {
962 if (Subtarget.hasAltivec())
963 for (
auto VT : {MVT::v4i32, MVT::v8i16, MVT::v16i8})
966 if (Subtarget.hasP8Altivec())
977 if (Subtarget.hasVSX()) {
983 if (Subtarget.hasP8Altivec())
988 if (Subtarget.isISA3_1()) {
1034 if (Subtarget.hasVSX()) {
1037 if (Subtarget.hasP8Vector()) {
1041 if (Subtarget.hasDirectMove() && isPPC64) {
1090 if (Subtarget.hasP8Vector())
1099 if (Subtarget.hasP8Altivec()) {
1126 if (Subtarget.isISA3_1())
1229 if (Subtarget.hasP8Altivec()) {
1234 if (Subtarget.hasP9Vector()) {
1239 if (Subtarget.useCRBits()) {
1299 }
else if (Subtarget.hasVSX()) {
1324 for (
MVT VT : {MVT::f32, MVT::f64}) {
1343 if (Subtarget.hasP9Altivec()) {
1344 if (Subtarget.isISA3_1()) {
1367 if (Subtarget.hasP10Vector()) {
1372 if (Subtarget.pairedVectorMemops()) {
1377 if (Subtarget.hasMMA()) {
1378 if (Subtarget.isISAFuture()) {
1394 if (Subtarget.has64BitSupport())
1397 if (Subtarget.isISA3_1())
1415 if (Subtarget.hasAltivec()) {
1432 if (Subtarget.hasFPCVT())
1435 if (Subtarget.useCRBits())
1444 if (Subtarget.useCRBits()) {
1450 if (Subtarget.useCRBits()) {
1466 auto CPUDirective = Subtarget.getCPUDirective();
1467 switch (CPUDirective) {
1490 if (Subtarget.enableMachineScheduler())
1564void PPCTargetLowering::initializeAddrModeMap() {
1615 if (MaxAlign == MaxMaxAlign)
1618 if (MaxMaxAlign >= 32 &&
1619 VTy->getPrimitiveSizeInBits().getFixedValue() >= 256)
1620 MaxAlign =
Align(32);
1621 else if (VTy->getPrimitiveSizeInBits().getFixedValue() >= 128 &&
1623 MaxAlign =
Align(16);
1627 if (EltAlign > MaxAlign)
1628 MaxAlign = EltAlign;
1630 for (
auto *EltTy : STy->elements()) {
1633 if (EltAlign > MaxAlign)
1634 MaxAlign = EltAlign;
1635 if (MaxAlign == MaxMaxAlign)
1648 if (Subtarget.hasAltivec())
1654 return Subtarget.useSoftFloat();
1658 return Subtarget.hasSPE();
1666 Type *VectorTy,
unsigned ElemSizeInBits,
unsigned &Index)
const {
1667 if (!Subtarget.isPPC64() || !Subtarget.hasVSX())
1671 if (VTy->getScalarType()->isIntegerTy()) {
1673 if (ElemSizeInBits == 32) {
1674 Index = Subtarget.isLittleEndian() ? 2 : 1;
1677 if (ElemSizeInBits == 64) {
1678 Index = Subtarget.isLittleEndian() ? 1 : 0;
1689 return Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
1706 return CFP->getValueAPF().isZero();
1711 return CFP->getValueAPF().isZero();
1719 return Op < 0 ||
Op == Val;
1731 if (ShuffleKind == 0) {
1734 for (
unsigned i = 0; i != 16; ++i)
1737 }
else if (ShuffleKind == 2) {
1740 for (
unsigned i = 0; i != 16; ++i)
1743 }
else if (ShuffleKind == 1) {
1744 unsigned j = IsLE ? 0 : 1;
1745 for (
unsigned i = 0; i != 8; ++i)
1762 if (ShuffleKind == 0) {
1765 for (
unsigned i = 0; i != 16; i += 2)
1769 }
else if (ShuffleKind == 2) {
1772 for (
unsigned i = 0; i != 16; i += 2)
1776 }
else if (ShuffleKind == 1) {
1777 unsigned j = IsLE ? 0 : 2;
1778 for (
unsigned i = 0; i != 8; i += 2)
1799 if (!Subtarget.hasP8Vector())
1803 if (ShuffleKind == 0) {
1806 for (
unsigned i = 0; i != 16; i += 4)
1812 }
else if (ShuffleKind == 2) {
1815 for (
unsigned i = 0; i != 16; i += 4)
1821 }
else if (ShuffleKind == 1) {
1822 unsigned j = IsLE ? 0 : 4;
1823 for (
unsigned i = 0; i != 8; i += 4)
1840 unsigned LHSStart,
unsigned RHSStart) {
1841 if (
N->getValueType(0) != MVT::v16i8)
1843 assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) &&
1844 "Unsupported merge size!");
1846 for (
unsigned i = 0; i != 8/UnitSize; ++i)
1847 for (
unsigned j = 0; j != UnitSize; ++j) {
1849 LHSStart+j+i*UnitSize) ||
1851 RHSStart+j+i*UnitSize))
1866 if (ShuffleKind == 1)
1868 else if (ShuffleKind == 2)
1873 if (ShuffleKind == 1)
1875 else if (ShuffleKind == 0)
1891 if (ShuffleKind == 1)
1893 else if (ShuffleKind == 2)
1898 if (ShuffleKind == 1)
1900 else if (ShuffleKind == 0)
1950 unsigned RHSStartValue) {
1951 if (
N->getValueType(0) != MVT::v16i8)
1954 for (
unsigned i = 0; i < 2; ++i)
1955 for (
unsigned j = 0; j < 4; ++j)
1957 i*RHSStartValue+j+IndexOffset) ||
1959 i*RHSStartValue+j+IndexOffset+8))
1981 unsigned indexOffset = CheckEven ? 4 : 0;
1982 if (ShuffleKind == 1)
1984 else if (ShuffleKind == 2)
1990 unsigned indexOffset = CheckEven ? 0 : 4;
1991 if (ShuffleKind == 1)
1993 else if (ShuffleKind == 0)
2009 if (
N->getValueType(0) != MVT::v16i8)
2016 for (i = 0; i != 16 && SVOp->
getMaskElt(i) < 0; ++i)
2019 if (i == 16)
return -1;
2024 if (ShiftAmt < i)
return -1;
2029 if ((ShuffleKind == 0 && !isLE) || (ShuffleKind == 2 && isLE)) {
2031 for (++i; i != 16; ++i)
2034 }
else if (ShuffleKind == 1) {
2036 for (++i; i != 16; ++i)
2043 ShiftAmt = 16 - ShiftAmt;
2052 EVT VT =
N->getValueType(0);
2053 if (VT == MVT::v2i64 || VT == MVT::v2f64)
2054 return EltSize == 8 &&
N->getMaskElt(0) ==
N->getMaskElt(1);
2057 EltSize <= 8 &&
"Can only handle 1,2,4,8 byte element sizes");
2061 if (
N->getMaskElt(0) % EltSize != 0)
2066 unsigned ElementBase =
N->getMaskElt(0);
2069 if (ElementBase >= 16)
2074 for (
unsigned i = 1; i != EltSize; ++i)
2075 if (
N->getMaskElt(i) < 0 ||
N->getMaskElt(i) != (
int)(i+ElementBase))
2078 for (
unsigned i = EltSize, e = 16; i != e; i += EltSize) {
2080 if (
N->getMaskElt(i) < 0) {
2081 for (
unsigned j = 1; j != EltSize; ++j)
2082 if (
N->getMaskElt(i + j) >= 0)
2085 for (
unsigned j = 0; j != EltSize; ++j)
2086 if (
N->getMaskElt(i + j) !=
N->getMaskElt(j))
2103 assert((Width == 2 || Width == 4 || Width == 8 || Width == 16) &&
2104 "Unexpected element width.");
2105 assert((StepLen == 1 || StepLen == -1) &&
"Unexpected element width.");
2107 unsigned NumOfElem = 16 / Width;
2108 unsigned MaskVal[16];
2109 for (
unsigned i = 0; i < NumOfElem; ++i) {
2110 MaskVal[0] =
N->getMaskElt(i * Width);
2111 if ((StepLen == 1) && (MaskVal[0] % Width)) {
2113 }
else if ((StepLen == -1) && ((MaskVal[0] + 1) % Width)) {
2117 for (
unsigned int j = 1; j < Width; ++j) {
2118 MaskVal[j] =
N->getMaskElt(i * Width + j);
2119 if (MaskVal[j] != MaskVal[j-1] + StepLen) {
2129 unsigned &InsertAtByte,
bool &Swap,
bool IsLE) {
2134 unsigned M0 =
N->getMaskElt(0) / 4;
2135 unsigned M1 =
N->getMaskElt(4) / 4;
2136 unsigned M2 =
N->getMaskElt(8) / 4;
2137 unsigned M3 =
N->getMaskElt(12) / 4;
2138 unsigned LittleEndianShifts[] = { 2, 1, 0, 3 };
2139 unsigned BigEndianShifts[] = { 3, 0, 1, 2 };
2144 if ((
M0 > 3 &&
M1 == 1 && M2 == 2 && M3 == 3) ||
2145 (
M0 < 4 &&
M1 == 5 && M2 == 6 && M3 == 7)) {
2146 ShiftElts = IsLE ? LittleEndianShifts[
M0 & 0x3] : BigEndianShifts[
M0 & 0x3];
2147 InsertAtByte = IsLE ? 12 : 0;
2152 if ((
M1 > 3 &&
M0 == 0 && M2 == 2 && M3 == 3) ||
2153 (
M1 < 4 &&
M0 == 4 && M2 == 6 && M3 == 7)) {
2154 ShiftElts = IsLE ? LittleEndianShifts[
M1 & 0x3] : BigEndianShifts[
M1 & 0x3];
2155 InsertAtByte = IsLE ? 8 : 4;
2160 if ((M2 > 3 &&
M0 == 0 &&
M1 == 1 && M3 == 3) ||
2161 (M2 < 4 &&
M0 == 4 &&
M1 == 5 && M3 == 7)) {
2162 ShiftElts = IsLE ? LittleEndianShifts[M2 & 0x3] : BigEndianShifts[M2 & 0x3];
2163 InsertAtByte = IsLE ? 4 : 8;
2168 if ((M3 > 3 &&
M0 == 0 &&
M1 == 1 && M2 == 2) ||
2169 (M3 < 4 &&
M0 == 4 &&
M1 == 5 && M2 == 6)) {
2170 ShiftElts = IsLE ? LittleEndianShifts[M3 & 0x3] : BigEndianShifts[M3 & 0x3];
2171 InsertAtByte = IsLE ? 0 : 12;
2178 if (
N->getOperand(1).isUndef()) {
2181 unsigned XXINSERTWSrcElem = IsLE ? 2 : 1;
2182 if (
M0 == XXINSERTWSrcElem &&
M1 == 1 && M2 == 2 && M3 == 3) {
2183 InsertAtByte = IsLE ? 12 : 0;
2186 if (
M0 == 0 &&
M1 == XXINSERTWSrcElem && M2 == 2 && M3 == 3) {
2187 InsertAtByte = IsLE ? 8 : 4;
2190 if (
M0 == 0 &&
M1 == 1 && M2 == XXINSERTWSrcElem && M3 == 3) {
2191 InsertAtByte = IsLE ? 4 : 8;
2194 if (
M0 == 0 &&
M1 == 1 && M2 == 2 && M3 == XXINSERTWSrcElem) {
2195 InsertAtByte = IsLE ? 0 : 12;
2204 bool &Swap,
bool IsLE) {
2205 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2211 unsigned M0 =
N->getMaskElt(0) / 4;
2212 unsigned M1 =
N->getMaskElt(4) / 4;
2213 unsigned M2 =
N->getMaskElt(8) / 4;
2214 unsigned M3 =
N->getMaskElt(12) / 4;
2218 if (
N->getOperand(1).isUndef()) {
2219 assert(
M0 < 4 &&
"Indexing into an undef vector?");
2220 if (
M1 != (
M0 + 1) % 4 || M2 != (
M1 + 1) % 4 || M3 != (M2 + 1) % 4)
2223 ShiftElts = IsLE ? (4 -
M0) % 4 :
M0;
2229 if (
M1 != (
M0 + 1) % 8 || M2 != (
M1 + 1) % 8 || M3 != (M2 + 1) % 8)
2233 if (
M0 == 0 ||
M0 == 7 ||
M0 == 6 ||
M0 == 5) {
2238 ShiftElts = (8 -
M0) % 8;
2239 }
else if (
M0 == 4 ||
M0 == 3 ||
M0 == 2 ||
M0 == 1) {
2244 ShiftElts = (4 -
M0) % 4;
2249 if (
M0 == 0 ||
M0 == 1 ||
M0 == 2 ||
M0 == 3) {
2254 }
else if (
M0 == 4 ||
M0 == 5 ||
M0 == 6 ||
M0 == 7) {
2266 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2271 for (
int i = 0; i < 16; i += Width)
2272 if (
N->getMaskElt(i) != i + Width - 1)
2303 bool &Swap,
bool IsLE) {
2304 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2310 unsigned M0 =
N->getMaskElt(0) / 8;
2311 unsigned M1 =
N->getMaskElt(8) / 8;
2312 assert(((
M0 |
M1) < 4) &&
"A mask element out of bounds?");
2316 if (
N->getOperand(1).isUndef()) {
2317 if ((
M0 |
M1) < 2) {
2318 DM = IsLE ? (((
~M1) & 1) << 1) + ((~
M0) & 1) : (
M0 << 1) + (
M1 & 1);
2326 if (
M0 > 1 &&
M1 < 2) {
2336 DM = (((
~M1) & 1) << 1) + ((~
M0) & 1);
2341 }
else if (
M0 > 1 &&
M1 < 2) {
2349 DM = (
M0 << 1) + (
M1 & 1);
2364 if (VT == MVT::v2i64 || VT == MVT::v2f64)
2369 return (16 / EltSize) - 1 - (SVOp->
getMaskElt(0) / EltSize);
2385 unsigned EltSize = 16/
N->getNumOperands();
2386 if (EltSize < ByteSize) {
2387 unsigned Multiple = ByteSize/EltSize;
2389 assert(Multiple > 1 && Multiple <= 4 &&
"How can this happen?");
2392 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
2393 if (
N->getOperand(i).isUndef())
continue;
2397 if (!UniquedVals[i&(Multiple-1)].
getNode())
2398 UniquedVals[i&(Multiple-1)] =
N->getOperand(i);
2399 else if (UniquedVals[i&(Multiple-1)] !=
N->getOperand(i))
2409 bool LeadingZero =
true;
2410 bool LeadingOnes =
true;
2411 for (
unsigned i = 0; i != Multiple-1; ++i) {
2412 if (!UniquedVals[i].
getNode())
continue;
2419 if (!UniquedVals[Multiple-1].
getNode())
2426 if (!UniquedVals[Multiple-1].
getNode())
2437 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
2438 if (
N->getOperand(i).isUndef())
continue;
2440 OpVal =
N->getOperand(i);
2441 else if (OpVal !=
N->getOperand(i))
2447 unsigned ValSizeInBytes = EltSize;
2450 Value = CN->getZExtValue();
2452 assert(CN->getValueType(0) == MVT::f32 &&
"Only one legal FP vector type!");
2459 if (ValSizeInBytes < ByteSize)
return SDValue();
2470 if (MaskVal == 0)
return SDValue();
2490 Imm = (int16_t)
N->getAsZExtVal();
2491 if (
N->getValueType(0) == MVT::i32)
2492 return Imm == (int32_t)
N->getAsZExtVal();
2494 return Imm == (int64_t)
N->getAsZExtVal();
2512 return (~(LHSKnown.
Zero | RHSKnown.
Zero) == 0);
2520 for (
SDNode *U :
N->users()) {
2522 if (Memop->getMemoryVT() == MVT::f64) {
2523 Base =
N.getOperand(0);
2524 Index =
N.getOperand(1);
2567 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm)))
2569 if (
N.getOperand(1).getOpcode() == PPCISD::Lo)
2572 Base =
N.getOperand(0);
2573 Index =
N.getOperand(1);
2575 }
else if (
N.getOpcode() ==
ISD::OR) {
2577 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm)))
2589 if (~(LHSKnown.
Zero | RHSKnown.
Zero) == 0) {
2590 Base =
N.getOperand(0);
2591 Index =
N.getOperand(1);
2661 (!EncodingAlignment ||
isAligned(*EncodingAlignment, imm))) {
2667 Base =
N.getOperand(0);
2670 }
else if (
N.getOperand(1).getOpcode() == PPCISD::Lo) {
2672 assert(!
N.getOperand(1).getConstantOperandVal(1) &&
2673 "Cannot handle constant offsets yet!");
2674 Disp =
N.getOperand(1).getOperand(0);
2679 Base =
N.getOperand(0);
2682 }
else if (
N.getOpcode() ==
ISD::OR) {
2685 (!EncodingAlignment ||
isAligned(*EncodingAlignment, imm))) {
2699 Base =
N.getOperand(0);
2712 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm))) {
2715 CN->getValueType(0));
2720 if ((CN->getValueType(0) == MVT::i32 ||
2721 (int64_t)CN->getZExtValue() == (
int)CN->getZExtValue()) &&
2722 (!EncodingAlignment ||
2723 isAligned(*EncodingAlignment, CN->getZExtValue()))) {
2724 int Addr = (int)CN->getZExtValue();
2731 unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8;
2752 if (
N.getValueType() != MVT::i64)
2765 Base =
N.getOperand(0);
2781 Base =
N.getOperand(0);
2814 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
2815 Base =
N.getOperand(0);
2816 Index =
N.getOperand(1);
2838 if (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR)
2859 EVT MemVT = LD->getMemoryVT();
2866 if (!ST.hasP8Vector())
2871 if (!ST.hasP9Vector())
2883 if (
Use.getResNo() == 0 &&
2885 Use.
getUser()->getOpcode() != PPCISD::SCALAR_TO_VECTOR_PERMUTED)
2905 Ptr = LD->getBasePtr();
2906 VT = LD->getMemoryVT();
2907 Alignment = LD->getAlign();
2909 Ptr = ST->getBasePtr();
2910 VT = ST->getMemoryVT();
2911 Alignment = ST->getAlign();
2950 if (VT != MVT::i64) {
2955 if (Alignment <
Align(4))
2965 if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 &&
2982 unsigned &HiOpFlags,
unsigned &LoOpFlags,
3024 EVT VT = Subtarget.getScalarIntVT();
3026 : Subtarget.isAIXABI()
3031 PPCISD::TOC_ENTRY, dl, DAG.
getVTList(VT, MVT::Other),
Ops, VT,
3038 EVT PtrVT =
Op.getValueType();
3044 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3045 if (Subtarget.isUsingPCRelativeCalls()) {
3050 return DAG.
getNode(PPCISD::MAT_PCREL_ADDR,
DL, Ty, ConstPool);
3054 return getTOCEntry(DAG, SDLoc(CP), GA);
3057 unsigned MOHiFlag, MOLoFlag;
3061 if (IsPIC && Subtarget.isSVR4ABI()) {
3064 return getTOCEntry(DAG, SDLoc(CP), GA);
3087 if (Subtarget.isPPC64() || Subtarget.isAIXABI())
3094 if (!Subtarget.isPPC64() || Subtarget.isAIXABI())
3111 if (!Subtarget.isPPC64() || Subtarget.isAIXABI())
3124 EVT PtrVT =
Op.getValueType();
3142 return getTOCEntry(DAG,
SDLoc(JT), GA);
3145 unsigned MOHiFlag, MOLoFlag;
3149 if (IsPIC && Subtarget.isSVR4ABI()) {
3152 return getTOCEntry(DAG, SDLoc(GA), GA);
3162 EVT PtrVT =
Op.getValueType();
3167 if (Subtarget.isUsingPCRelativeCalls()) {
3178 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3181 return getTOCEntry(DAG, SDLoc(BASDN), GA);
3190 unsigned MOHiFlag, MOLoFlag;
3200 if (Subtarget.isAIXABI())
3201 return LowerGlobalTLSAddressAIX(
Op, DAG);
3203 return LowerGlobalTLSAddressLinux(
Op, DAG);
3225 if (
I.getOpcode() == Instruction::Call)
3227 if (
Function *CF = CI->getCalledFunction())
3228 if (CF->isDeclaration() &&
3229 CF->getIntrinsicID() == Intrinsic::threadlocal_address)
3237 unsigned TLSGVCnt = TLSGV.
size();
3247 <<
" function is using the TLS-IE model for TLS-LD access.\n");
3260 const GlobalValue *GV = GA->
getGlobal();
3262 bool Is64Bit = Subtarget.isPPC64();
3266 if (Subtarget.hasAIXShLibTLSModelOpt())
3276 bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS();
3277 bool HasAIXSmallTLSGlobalAttr =
false;
3280 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3284 if (GVar->hasAttribute(
"aix-small-tls"))
3285 HasAIXSmallTLSGlobalAttr =
true;
3304 if ((HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr) &&
3305 IsTLSLocalExecModel) {
3310 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA, TLSReg);
3320 TLSReg = DAG.
getNode(PPCISD::GET_TPOINTER, dl, PtrVT);
3325 if (HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr)
3327 "currently only supported on AIX (64-bit mode).");
3329 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
3333 bool HasAIXSmallLocalDynamicTLS = Subtarget.hasAIXSmallLocalDynamicTLS();
3337 if (!Is64Bit && HasAIXSmallLocalDynamicTLS)
3339 "currently only supported on AIX (64-bit mode).");
3347 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3350 GlobalVariable *TLSGV =
3354 assert(TLSGV &&
"Not able to create GV for _$TLSML.");
3357 SDValue ModuleHandleTOC = getTOCEntry(DAG, dl, ModuleHandleTGA);
3359 DAG.
getNode(PPCISD::TLSLD_AIX, dl, PtrVT, ModuleHandleTOC);
3368 if (HasAIXSmallLocalDynamicTLS) {
3373 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA,
3377 return DAG.
getNode(
ISD::ADD, dl, PtrVT, ModuleHandle, VariableOffset);
3390 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3391 SDValue RegionHandle = getTOCEntry(DAG, dl, RegionHandleTGA);
3392 return DAG.
getNode(PPCISD::TLSGD_AIX, dl, PtrVT, VariableOffset,
3407 const GlobalValue *GV = GA->
getGlobal();
3409 bool is64bit = Subtarget.isPPC64();
3417 if (Subtarget.isUsingPCRelativeCalls()) {
3422 DAG.
getNode(PPCISD::TLS_LOCAL_EXEC_MAT_ADDR, dl, PtrVT, TGA);
3423 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, MatAddr);
3434 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, TGALo,
Hi);
3438 bool IsPCRel = Subtarget.isUsingPCRelativeCalls();
3445 SDValue MatPCRel = DAG.
getNode(PPCISD::MAT_PCREL_ADDR, dl, PtrVT, TGA);
3447 MachinePointerInfo());
3454 DAG.
getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl, PtrVT, GOTReg, TGA);
3456 if (!TM.isPositionIndependent())
3457 GOTPtr = DAG.
getNode(PPCISD::PPC32_GOT, dl, PtrVT);
3463 TPOffset = DAG.
getNode(PPCISD::LD_GOT_TPREL_L, dl, PtrVT, TGA, GOTPtr);
3465 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TPOffset, TGATLS);
3469 if (Subtarget.isUsingPCRelativeCalls()) {
3472 return DAG.
getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3480 GOTPtr = DAG.
getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT,
3488 return DAG.
getNode(PPCISD::ADDI_TLSGD_L_ADDR, dl, PtrVT,
3493 if (Subtarget.isUsingPCRelativeCalls()) {
3497 DAG.
getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3498 return DAG.
getNode(PPCISD::PADDI_DTPREL, dl, PtrVT, MatPCRel, TGA);
3506 GOTPtr = DAG.
getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT,
3515 PtrVT, GOTPtr, TGA, TGA);
3517 PtrVT, TLSAddr, TGA);
3518 return DAG.
getNode(PPCISD::ADDI_DTPREL_L, dl, PtrVT, DtvOffsetHi, TGA);
3526 EVT PtrVT =
Op.getValueType();
3529 const GlobalValue *GV = GSDN->
getGlobal();
3533 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3534 if (Subtarget.isUsingPCRelativeCalls()) {
3541 MachinePointerInfo());
3546 return DAG.
getNode(PPCISD::MAT_PCREL_ADDR,
DL, Ty, GA);
3551 return getTOCEntry(DAG,
DL, GA);
3554 unsigned MOHiFlag, MOLoFlag;
3558 if (IsPIC && Subtarget.isSVR4ABI()) {
3562 return getTOCEntry(DAG,
DL, GA);
3574 bool IsStrict =
Op->isStrictFPOpcode();
3580 EVT LHSVT =
LHS.getValueType();
3584 if (LHSVT == MVT::f128) {
3585 assert(!Subtarget.hasP9Vector() &&
3586 "SETCC for f128 is already legal under Power9!");
3597 assert(!IsStrict &&
"Don't know how to handle STRICT_FSETCC!");
3599 if (
Op.getValueType() == MVT::v2i64) {
3602 if (
LHS.getValueType() == MVT::v2i64) {
3608 dl, MVT::v4i32, DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
LHS),
3609 DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32,
RHS), CC);
3610 int ShuffV[] = {1, 0, 3, 2};
3615 dl, MVT::v4i32, Shuff, SetCC32));
3632 if (
C->isAllOnes() ||
C->isZero())
3642 EVT VT =
Op.getValueType();
3650 SDNode *
Node =
Op.getNode();
3651 EVT VT =
Node->getValueType(0);
3658 assert(!Subtarget.isPPC64() &&
"LowerVAARG is PPC32 only");
3662 VAListPtr, MachinePointerInfo(SV), MVT::i8);
3665 if (VT == MVT::i64) {
3684 FprPtr, MachinePointerInfo(SV), MVT::i8);
3695 DAG.
getLoad(MVT::i32, dl, InChain, OverflowAreaPtr, MachinePointerInfo());
3696 InChain = OverflowArea.
getValue(1);
3699 DAG.
getLoad(MVT::i32, dl, InChain, RegSaveAreaPtr, MachinePointerInfo());
3729 MachinePointerInfo(SV), MVT::i8);
3742 InChain = DAG.
getTruncStore(InChain, dl, OverflowArea, OverflowAreaPtr,
3743 MachinePointerInfo(), MVT::i32);
3745 return DAG.
getLoad(VT, dl, InChain, Result, MachinePointerInfo());
3749 assert(!Subtarget.isPPC64() &&
"LowerVACOPY is PPC32 only");
3755 false,
true,
nullptr, std::nullopt,
3756 MachinePointerInfo(), MachinePointerInfo());
3761 return Op.getOperand(0);
3766 PPCFunctionInfo &MFI = *MF.
getInfo<PPCFunctionInfo>();
3768 assert((
Op.getOpcode() == ISD::INLINEASM ||
3769 Op.getOpcode() == ISD::INLINEASM_BR) &&
3770 "Expecting Inline ASM node.");
3780 if (
Op.getOperand(
NumOps - 1).getValueType() == MVT::Glue)
3785 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(i));
3786 unsigned NumVals =
Flags.getNumOperandRegisters();
3789 switch (
Flags.getKind()) {
3800 for (; NumVals; --NumVals, ++i) {
3802 if (
Reg != PPC::LR &&
Reg != PPC::LR8)
3825 if (Subtarget.isAIXABI()) {
3829 uint64_t
PointerSize = Subtarget.isPPC64() ? 8 : 4;
3830 MaybeAlign PointerAlign(PointerSize);
3831 auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
3834 : MachineMemOperand::MONone;
3841 const Value *TrampolineAddr =
3851 DAG.
getLoad(PtrVT, dl, Chain, FPtr, MachinePointerInfo(Func, 0),
3852 PointerAlign, MMOFlags);
3854 OutChains[0] = DAG.
getStore(EPLoadChain, dl, LoadEntryPoint, Trmp,
3855 MachinePointerInfo(TrampolineAddr, 0));
3859 SDValue TOCFromDescriptorPtr =
3861 SDValue TOCReg = DAG.
getLoad(PtrVT, dl, Chain, TOCFromDescriptorPtr,
3862 MachinePointerInfo(Func, TOCPointerOffset),
3863 PointerAlign, MMOFlags);
3864 SDValue TrampolineTOCPointer =
3868 DAG.
getStore(TOCLoadChain, dl, TOCReg, TrampolineTOCPointer,
3869 MachinePointerInfo(TrampolineAddr, TOCPointerOffset));
3875 DAG.
getStore(Chain, dl, Nest, EnvPointer,
3876 MachinePointerInfo(TrampolineAddr, EnvPointerOffset));
3883 bool isPPC64 = (PtrVT == MVT::i64);
3887 Args.emplace_back(Trmp, IntPtrTy);
3890 DAG.
getConstant(isPPC64 ? 48 : 40, dl, Subtarget.getScalarIntVT()),
3892 Args.emplace_back(FPtr, IntPtrTy);
3893 Args.emplace_back(Nest, IntPtrTy);
3896 TargetLowering::CallLoweringInfo CLI(DAG);
3897 CLI.setDebugLoc(dl).setChain(Chain).setLibCallee(
3901 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3902 return CallResult.second;
3907 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
3912 if (Subtarget.isPPC64() || Subtarget.isAIXABI()) {
3917 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
3918 MachinePointerInfo(SV));
3952 uint64_t FrameOffset = PtrVT.getSizeInBits()/8;
3955 uint64_t StackOffset = PtrVT.getSizeInBits()/8 - 1;
3958 uint64_t FPROffset = 1;
3966 MachinePointerInfo(SV), MVT::i8);
3967 uint64_t nextOffset = FPROffset;
3974 MachinePointerInfo(SV, nextOffset), MVT::i8);
3975 nextOffset += StackOffset;
3976 nextPtr = DAG.
getNode(
ISD::ADD, dl, PtrVT, nextPtr, ConstStackOffset);
3979 SDValue thirdStore = DAG.
getStore(secondStore, dl, StackOffsetFI, nextPtr,
3980 MachinePointerInfo(SV, nextOffset));
3981 nextOffset += FrameOffset;
3982 nextPtr = DAG.
getNode(
ISD::ADD, dl, PtrVT, nextPtr, ConstFrameOffset);
3985 return DAG.
getStore(thirdStore, dl, FR, nextPtr,
3986 MachinePointerInfo(SV, nextOffset));
3991static const MCPhysReg FPR[] = {PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5,
3992 PPC::F6, PPC::F7, PPC::F8, PPC::F9, PPC::F10,
3993 PPC::F11, PPC::F12, PPC::F13};
3998 unsigned PtrByteSize) {
4000 if (Flags.isByVal())
4001 ArgSize = Flags.getByValSize();
4005 if (!Flags.isInConsecutiveRegs())
4006 ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4015 unsigned PtrByteSize) {
4016 Align Alignment(PtrByteSize);
4019 if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 ||
4020 ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 ||
4021 ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 ||
4022 ArgVT == MVT::v1i128 || ArgVT == MVT::f128)
4023 Alignment =
Align(16);
4026 if (Flags.isByVal()) {
4027 auto BVAlign = Flags.getNonZeroByValAlign();
4028 if (BVAlign > PtrByteSize) {
4029 if (BVAlign.value() % PtrByteSize != 0)
4031 "ByVal alignment is not a multiple of the pointer size");
4033 Alignment = BVAlign;
4038 if (Flags.isInConsecutiveRegs()) {
4042 if (Flags.isSplit() && OrigVT != MVT::ppcf128)
4056 unsigned PtrByteSize,
unsigned LinkageSize,
4057 unsigned ParamAreaSize,
unsigned &ArgOffset,
4058 unsigned &AvailableFPRs,
4059 unsigned &AvailableVRs) {
4060 bool UseMemory =
false;
4065 ArgOffset =
alignTo(ArgOffset, Alignment);
4068 if (ArgOffset >= LinkageSize + ParamAreaSize)
4073 if (Flags.isInConsecutiveRegsLast())
4074 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4077 if (ArgOffset > LinkageSize + ParamAreaSize)
4082 if (!Flags.isByVal()) {
4083 if (ArgVT == MVT::f32 || ArgVT == MVT::f64)
4084 if (AvailableFPRs > 0) {
4088 if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 ||
4089 ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 ||
4090 ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 ||
4091 ArgVT == MVT::v1i128 || ArgVT == MVT::f128)
4092 if (AvailableVRs > 0) {
4104 unsigned NumBytes) {
4108SDValue PPCTargetLowering::LowerFormalArguments(
4112 if (Subtarget.isAIXABI())
4113 return LowerFormalArguments_AIX(Chain, CallConv, isVarArg, Ins, dl, DAG,
4115 if (Subtarget.is64BitELFABI())
4116 return LowerFormalArguments_64SVR4(Chain, CallConv, isVarArg, Ins, dl, DAG,
4118 assert(Subtarget.is32BitELFABI());
4119 return LowerFormalArguments_32SVR4(Chain, CallConv, isVarArg, Ins, dl, DAG,
4123SDValue PPCTargetLowering::LowerFormalArguments_32SVR4(
4159 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
4165 const Align PtrAlign(4);
4173 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
4174 CCInfo.AllocateStack(LinkageSize, PtrAlign);
4177 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4178 CCValAssign &VA = ArgLocs[i];
4182 const TargetRegisterClass *RC;
4190 RC = &PPC::GPRCRegClass;
4193 if (Subtarget.hasP8Vector())
4194 RC = &PPC::VSSRCRegClass;
4195 else if (Subtarget.hasSPE())
4196 RC = &PPC::GPRCRegClass;
4198 RC = &PPC::F4RCRegClass;
4201 if (Subtarget.hasVSX())
4202 RC = &PPC::VSFRCRegClass;
4203 else if (Subtarget.hasSPE())
4205 RC = &PPC::GPRCRegClass;
4207 RC = &PPC::F8RCRegClass;
4212 RC = &PPC::VRRCRegClass;
4215 RC = &PPC::VRRCRegClass;
4219 RC = &PPC::VRRCRegClass;
4226 if (VA.
getLocVT() == MVT::f64 && Subtarget.hasSPE()) {
4227 assert(i + 1 < e &&
"No second half of double precision argument");
4232 if (!Subtarget.isLittleEndian())
4234 ArgValue = DAG.
getNode(PPCISD::BUILD_SPE64, dl, MVT::f64, ArgValueLo,
4239 ValVT == MVT::i1 ? MVT::i32 : ValVT);
4240 if (ValVT == MVT::i1)
4255 ArgOffset += ArgSize - ObjSize;
4273 CCByValInfo.AllocateStack(CCInfo.getStackSize(), PtrAlign);
4278 unsigned MinReservedArea = CCByValInfo.getStackSize();
4279 MinReservedArea = std::max(MinReservedArea, LinkageSize);
4295 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
4296 PPC::R7, PPC::R8, PPC::R9, PPC::R10,
4298 const unsigned NumGPArgRegs = std::size(GPArgRegs);
4301 PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
4304 unsigned NumFPArgRegs = std::size(FPArgRegs);
4313 int Depth = NumGPArgRegs * PtrVT.getSizeInBits()/8 +
4314 NumFPArgRegs * MVT(MVT::f64).getSizeInBits()/8;
4317 PtrVT.getSizeInBits() / 8, CCInfo.getStackSize(),
true));
4330 VReg = MF.
addLiveIn(GPArgReg, &PPC::GPRCRegClass);
4345 for (
unsigned FPRIndex = 0; FPRIndex != NumFPArgRegs; ++FPRIndex) {
4349 VReg = MF.
addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass);
4362 if (!MemOps.
empty())
4373 const SDLoc &dl)
const {
4377 else if (
Flags.isZExt())
4384SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
4390 bool isELFv2ABI = Subtarget.isELFv2ABI();
4391 bool isLittleEndian = Subtarget.isLittleEndian();
4394 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
4397 "fastcc not supported on varargs functions");
4403 unsigned PtrByteSize = 8;
4404 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
4407 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
4408 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
4411 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
4412 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
4415 const unsigned Num_GPR_Regs = std::size(GPR);
4417 const unsigned Num_VR_Regs = std::size(VR);
4425 bool HasParameterArea = !isELFv2ABI || isVarArg;
4426 unsigned ParamAreaSize = Num_GPR_Regs * PtrByteSize;
4427 unsigned NumBytes = LinkageSize;
4428 unsigned AvailableFPRs = Num_FPR_Regs;
4429 unsigned AvailableVRs = Num_VR_Regs;
4430 for (
const ISD::InputArg &In : Ins) {
4431 if (
In.Flags.isNest())
4435 LinkageSize, ParamAreaSize, NumBytes,
4436 AvailableFPRs, AvailableVRs))
4437 HasParameterArea =
true;
4444 unsigned ArgOffset = LinkageSize;
4445 unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
4448 unsigned CurArgIdx = 0;
4449 for (
unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
4451 bool needsLoad =
false;
4452 EVT ObjectVT = Ins[ArgNo].VT;
4453 EVT OrigVT = Ins[ArgNo].ArgVT;
4455 unsigned ArgSize = ObjSize;
4456 ISD::ArgFlagsTy
Flags = Ins[ArgNo].Flags;
4457 if (Ins[ArgNo].isOrigArg()) {
4458 std::advance(FuncArg, Ins[ArgNo].getOrigArgIndex() - CurArgIdx);
4459 CurArgIdx = Ins[ArgNo].getOrigArgIndex();
4464 unsigned CurArgOffset;
4466 auto ComputeArgOffset = [&]() {
4470 ArgOffset =
alignTo(ArgOffset, Alignment);
4471 CurArgOffset = ArgOffset;
4478 GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
4479 GPR_idx = std::min(GPR_idx, Num_GPR_Regs);
4484 if (
Flags.isByVal()) {
4485 assert(Ins[ArgNo].isOrigArg() &&
"Byval arguments cannot be implicit");
4491 ObjSize =
Flags.getByValSize();
4492 ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4514 if (HasParameterArea ||
4515 ArgSize + ArgOffset > LinkageSize + Num_GPR_Regs * PtrByteSize)
4522 if (ObjSize < PtrByteSize) {
4526 if (!isLittleEndian) {
4532 if (GPR_idx != Num_GPR_Regs) {
4539 MachinePointerInfo(&*FuncArg), ObjType);
4544 ArgOffset += PtrByteSize;
4553 for (
unsigned j = 0;
j < ArgSize;
j += PtrByteSize) {
4554 if (GPR_idx == Num_GPR_Regs)
4565 unsigned StoreSizeInBits = std::min(PtrByteSize, (ObjSize - j)) * 8;
4569 MachinePointerInfo(&*FuncArg, j), ObjType);
4573 ArgOffset += ArgSize;
4582 if (
Flags.isNest()) {
4587 if (ObjectVT == MVT::i32 || ObjectVT == MVT::i1)
4588 ArgVal = extendArgForPPC64(Flags, ObjectVT, DAG, ArgVal, dl);
4596 if (GPR_idx != Num_GPR_Regs) {
4601 if (ObjectVT == MVT::i32 || ObjectVT == MVT::i1)
4604 ArgVal = extendArgForPPC64(Flags, ObjectVT, DAG, ArgVal, dl);
4610 ArgSize = PtrByteSize;
4621 if (FPR_idx != Num_FPR_Regs) {
4624 if (ObjectVT == MVT::f32)
4626 Subtarget.hasP8Vector()
4627 ? &PPC::VSSRCRegClass
4628 : &PPC::F4RCRegClass);
4631 ? &PPC::VSFRCRegClass
4632 : &PPC::F8RCRegClass);
4647 if (ObjectVT == MVT::f32) {
4648 if ((ArgOffset % PtrByteSize) == (isLittleEndian ? 4 : 0))
4654 ArgVal = DAG.
getNode(ISD::BITCAST, dl, ObjectVT, ArgVal);
4666 ArgSize =
Flags.isInConsecutiveRegs() ? ObjSize : PtrByteSize;
4667 ArgOffset += ArgSize;
4668 if (
Flags.isInConsecutiveRegsLast())
4669 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4683 if (VR_idx != Num_VR_Regs) {
4700 if (ObjSize < ArgSize && !isLittleEndian)
4701 CurArgOffset += ArgSize - ObjSize;
4704 ArgVal = DAG.
getLoad(ObjectVT, dl, Chain, FIN, MachinePointerInfo());
4711 unsigned MinReservedArea;
4712 if (HasParameterArea)
4713 MinReservedArea = std::max(ArgOffset, LinkageSize + 8 * PtrByteSize);
4715 MinReservedArea = LinkageSize;
4732 int Depth = ArgOffset;
4741 for (GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
4742 GPR_idx < Num_GPR_Regs; ++GPR_idx) {
4754 if (!MemOps.
empty())
4763 unsigned ParamSize) {
4765 if (!isTailCall)
return 0;
4769 int SPDiff = (int)CallerMinReservedArea - (
int)ParamSize;
4771 if (SPDiff < FI->getTailCallSPDelta())
4787 "PC Relative callers do not have a TOC and cannot share a TOC Base");
4846 Caller->hasComdat() || CalleeGV->
getSection() != Caller->getSection())
4849 if (
F->getSectionPrefix() != Caller->getSectionPrefix())
4861 const unsigned PtrByteSize = 8;
4865 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
4866 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
4869 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
4870 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
4873 const unsigned NumGPRs = std::size(GPR);
4874 const unsigned NumFPRs = 13;
4875 const unsigned NumVRs = std::size(VR);
4876 const unsigned ParamAreaSize = NumGPRs * PtrByteSize;
4878 unsigned NumBytes = LinkageSize;
4879 unsigned AvailableFPRs = NumFPRs;
4880 unsigned AvailableVRs = NumVRs;
4883 if (Param.Flags.isNest())
continue;
4886 LinkageSize, ParamAreaSize, NumBytes,
4887 AvailableFPRs, AvailableVRs))
4898 auto CalleeArgEnd = CB.
arg_end();
4901 for (; CalleeArgIter != CalleeArgEnd; ++CalleeArgIter, ++CallerArgIter) {
4902 const Value* CalleeArg = *CalleeArgIter;
4903 const Value* CallerArg = &(*CallerArgIter);
4904 if (CalleeArg == CallerArg)
4930 if (!isTailCallableCC(CallerCC) || !isTailCallableCC(CalleeCC))
4940bool PPCTargetLowering::IsEligibleForTailCallOptimization_64SVR4(
4945 bool isCalleeExternalSymbol)
const {
4948 if (
DisableSCO && !TailCallOpt)
return false;
4951 if (isVarArg)
return false;
4958 if (
any_of(Ins, [](
const ISD::InputArg &IA) {
return IA.Flags.isByVal(); }))
4994 if (!Subtarget.isUsingPCRelativeCalls() &&
4999 if (!Subtarget.isUsingPCRelativeCalls() &&
5027bool PPCTargetLowering::IsEligibleForTailCallOptimization(
5040 if (
any_of(Ins, [](
const ISD::InputArg &IA) {
return IA.Flags.isByVal(); }))
5061 if (!
C)
return nullptr;
5063 int Addr =
C->getZExtValue();
5064 if ((Addr & 3) != 0 ||
5070 (
int)
C->getZExtValue() >> 2,
SDLoc(
Op),
5077struct TailCallArgumentInfo {
5082 TailCallArgumentInfo() =
default;
5092 for (
unsigned i = 0, e = TailCallArgs.
size(); i != e; ++i) {
5093 SDValue Arg = TailCallArgs[i].Arg;
5094 SDValue FIN = TailCallArgs[i].FrameIdxOp;
5095 int FI = TailCallArgs[i].FrameIdx;
5098 Chain, dl, Arg, FIN,
5107 int SPDiff,
const SDLoc &dl) {
5113 int SlotSize = Subtarget.isPPC64() ? 8 : 4;
5114 int NewRetAddrLoc = SPDiff + FL->getReturnSaveOffset();
5116 NewRetAddrLoc,
true);
5119 Chain = DAG.
getStore(Chain, dl, OldRetAddr, NewRetAddrFrIdx,
5129 int SPDiff,
unsigned ArgOffset,
5131 int Offset = ArgOffset + SPDiff;
5134 EVT VT = IsPPC64 ? MVT::i64 : MVT::i32;
5136 TailCallArgumentInfo
Info;
5138 Info.FrameIdxOp = FIN;
5146SDValue PPCTargetLowering::EmitTailCallLoadFPAndRetAddr(
5151 LROpOut = getReturnAddrFrameIndex(DAG);
5152 LROpOut = DAG.
getLoad(Subtarget.getScalarIntVT(), dl, Chain, LROpOut,
5153 MachinePointerInfo());
5170 Chain, dl, Dst, Src, SizeNode, Flags.getNonZeroByValAlign(),
false,
false,
5178 SDValue PtrOff,
int SPDiff,
unsigned ArgOffset,
bool isPPC64,
5202 const SDLoc &dl,
int SPDiff,
unsigned NumBytes,
SDValue LROp,
5212 if (!MemOpChains2.
empty())
5236SDValue PPCTargetLowering::LowerCallResult(
5244 CCRetInfo.AnalyzeCallResult(
5250 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
5251 CCValAssign &VA = RVLocs[i];
5256 if (Subtarget.hasSPE() && VA.
getLocVT() == MVT::f64) {
5266 if (!Subtarget.isLittleEndian())
5268 Val = DAG.
getNode(PPCISD::BUILD_SPE64, dl, MVT::f64,
Lo,
Hi);
5334 bool IsStrictFPCall =
false) {
5336 return PPCISD::TC_RETURN;
5338 unsigned RetOpc = 0;
5353 RetOpc = PPCISD::CALL_NOTOC;
5368 RetOpc = PPCISD::CALL;
5369 if (IsStrictFPCall) {
5373 case PPCISD::BCTRL_LOAD_TOC:
5374 RetOpc = PPCISD::BCTRL_LOAD_TOC_RM;
5377 RetOpc = PPCISD::BCTRL_RM;
5379 case PPCISD::CALL_NOTOC:
5380 RetOpc = PPCISD::CALL_NOTOC_RM;
5383 RetOpc = PPCISD::CALL_RM;
5385 case PPCISD::CALL_NOP:
5386 RetOpc = PPCISD::CALL_NOP_RM;
5400 auto isLocalCallee = [&]() {
5416 const auto getAIXFuncEntryPointSymbolSDNode = [&](
const GlobalValue *GV) {
5433 return getAIXFuncEntryPointSymbolSDNode(GV);
5440 const char *SymName = S->getSymbol();
5447 return getAIXFuncEntryPointSymbolSDNode(
F);
5453 const auto getExternalFunctionEntryPointSymbol = [&](
StringRef SymName) {
5461 SymName = getExternalFunctionEntryPointSymbol(SymName)->getName().data();
5468 assert(Callee.getNode() &&
"What no callee?");
5474 "Expected a CALLSEQ_STARTSDNode.");
5491 SDValue MTCTROps[] = {Chain, Callee, Glue};
5492 EVT ReturnTypes[] = {MVT::Other, MVT::Glue};
5493 Chain = DAG.
getNode(PPCISD::MTCTR, dl, ReturnTypes,
5533 auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
5552 SDValue LoadFuncPtr = DAG.
getLoad(RegVT, dl, LDChain, Callee, MPI,
5553 Alignment, MMOFlags);
5560 DAG.
getLoad(RegVT, dl, LDChain, AddTOC,
5567 DAG.
getLoad(RegVT, dl, LDChain, AddPtr,
5579 "Nest parameter is not supported on AIX.");
5595 SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass,
5598 const bool IsPPC64 = Subtarget.isPPC64();
5603 Ops.push_back(Chain);
5607 Ops.push_back(Callee);
5627 Ops.push_back(AddTOC);
5638 Ops.push_back(DAG.
getRegister(IsPPC64 ? PPC::CTR8 : PPC::CTR, RegVT));
5647 for (
const auto &[
Reg,
N] : RegsToPass)
5665 assert(Mask &&
"Missing call preserved mask for calling convention");
5670 Ops.push_back(Glue);
5673SDValue PPCTargetLowering::FinishCall(
5680 if ((Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls()) ||
5681 Subtarget.isAIXABI())
5688 if (!CFlags.IsIndirect)
5690 else if (Subtarget.usesFunctionDescriptors())
5692 dl, CFlags.HasNest, Subtarget);
5702 if (CFlags.IsTailCall) {
5710 (CFlags.IsIndirect && Subtarget.isUsingPCRelativeCalls())) &&
5711 "Expecting a global address, external symbol, absolute value, "
5712 "register or an indirect tail call when PC Relative calls are "
5715 assert(CallOpc == PPCISD::TC_RETURN &&
5716 "Unexpected call opcode for a tail call.");
5723 std::array<EVT, 2> ReturnTypes = {{MVT::Other, MVT::Glue}};
5724 Chain = DAG.
getNode(CallOpc, dl, ReturnTypes,
Ops);
5736 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, BytesCalleePops, Glue, dl);
5739 return LowerCallResult(Chain, Glue, CFlags.CallConv, CFlags.IsVarArg, Ins, dl,
5759 return isEligibleForTCO(CalleeGV, CalleeCC, CallerCC, CB,
5760 CalleeFunc->
isVarArg(), Outs, Ins, CallerFunc,
5764bool PPCTargetLowering::isEligibleForTCO(
5769 bool isCalleeExternalSymbol)
const {
5773 if (Subtarget.
isSVR4ABI() && Subtarget.isPPC64())
5774 return IsEligibleForTailCallOptimization_64SVR4(
5775 CalleeGV, CalleeCC, CallerCC, CB, isVarArg, Outs, Ins, CallerFunc,
5776 isCalleeExternalSymbol);
5778 return IsEligibleForTailCallOptimization(CalleeGV, CalleeCC, CallerCC,
5806 isEligibleForTCO(GV, CallConv, CallerCC, CB, isVarArg, Outs, Ins,
5821 "Callee should be an llvm::Function object.");
5824 <<
"\nTCO callee: ");
5831 "site marked musttail");
5838 Callee = LowerGlobalAddress(Callee, DAG);
5841 CallConv, isTailCall, isVarArg, isPatchPoint,
5844 Subtarget.is64BitELFABI() &&
5848 if (Subtarget.isAIXABI())
5849 return LowerCall_AIX(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5852 assert(Subtarget.isSVR4ABI());
5853 if (Subtarget.isPPC64())
5854 return LowerCall_64SVR4(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5856 return LowerCall_32SVR4(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5860SDValue PPCTargetLowering::LowerCall_32SVR4(
5871 const bool IsVarArg = CFlags.IsVarArg;
5872 const bool IsTailCall = CFlags.IsTailCall;
5878 const Align PtrAlign(4);
5889 MF.
getInfo<PPCFunctionInfo>()->setHasFastCall();
5897 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.
getContext());
5900 CCInfo.AllocateStack(Subtarget.getFrameLowering()->getLinkageSize(),
5907 unsigned NumArgs = Outs.
size();
5909 for (
unsigned i = 0; i != NumArgs; ++i) {
5910 MVT ArgVT = Outs[i].VT;
5911 ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
5916 Outs[i].OrigTy, CCInfo);
5919 ArgFlags, Outs[i].OrigTy, CCInfo);
5924 errs() <<
"Call operand #" << i <<
" has unhandled type "
5937 CCState CCByValInfo(CallConv, IsVarArg, MF, ByValArgLocs, *DAG.
getContext());
5940 CCByValInfo.AllocateStack(CCInfo.getStackSize(), PtrAlign);
5947 unsigned NumBytes = CCByValInfo.getStackSize();
5961 Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, dl);
5972 bool seenFloatArg =
false;
5977 for (
unsigned i = 0, RealArgIdx = 0, j = 0, e = ArgLocs.
size();
5979 ++i, ++RealArgIdx) {
5980 CCValAssign &VA = ArgLocs[i];
5981 SDValue Arg = OutVals[RealArgIdx];
5982 ISD::ArgFlagsTy
Flags = Outs[RealArgIdx].Flags;
5984 if (
Flags.isByVal()) {
5989 assert((j < ByValArgLocs.
size()) &&
"Index out of bounds!");
5990 CCValAssign &ByValVA = ByValArgLocs[
j++];
6012 Chain = CallSeqStart = NewCallSeqStart;
6031 if (Subtarget.hasSPE() && Arg.
getValueType() == MVT::f64) {
6032 bool IsLE = Subtarget.isLittleEndian();
6033 SDValue SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
6036 SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
6038 RegsToPass.
push_back(std::make_pair(ArgLocs[++i].getLocReg(),
6053 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
6062 if (!MemOpChains.
empty())
6068 for (
const auto &[
Reg,
N] : RegsToPass) {
6076 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
6079 Chain = DAG.
getNode(seenFloatArg ? PPCISD::CR6SET : PPCISD::CR6UNSET, dl,
6089 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
6090 Callee, SPDiff, NumBytes, Ins, InVals, CB);
6095SDValue PPCTargetLowering::createMemcpyOutsideCallSeq(
6107 return NewCallSeqStart;
6110SDValue PPCTargetLowering::LowerCall_64SVR4(
6117 bool isELFv2ABI = Subtarget.isELFv2ABI();
6118 bool isLittleEndian = Subtarget.isLittleEndian();
6120 bool IsSibCall =
false;
6124 unsigned PtrByteSize = 8;
6137 MF.
getInfo<PPCFunctionInfo>()->setHasFastCall();
6139 assert(!(IsFastCall && CFlags.IsVarArg) &&
6140 "fastcc not supported on varargs functions");
6146 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
6147 unsigned NumBytes = LinkageSize;
6148 unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
6151 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6152 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
6155 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
6156 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
6159 const unsigned NumGPRs = std::size(GPR);
6161 const unsigned NumVRs = std::size(VR);
6167 bool HasParameterArea = !isELFv2ABI || CFlags.IsVarArg || IsFastCall;
6168 if (!HasParameterArea) {
6169 unsigned ParamAreaSize = NumGPRs * PtrByteSize;
6170 unsigned AvailableFPRs = NumFPRs;
6171 unsigned AvailableVRs = NumVRs;
6172 unsigned NumBytesTmp = NumBytes;
6173 for (
unsigned i = 0; i !=
NumOps; ++i) {
6174 if (Outs[i].
Flags.isNest())
continue;
6176 PtrByteSize, LinkageSize, ParamAreaSize,
6177 NumBytesTmp, AvailableFPRs, AvailableVRs))
6178 HasParameterArea =
true;
6184 unsigned NumGPRsUsed = 0, NumFPRsUsed = 0, NumVRsUsed = 0;
6189 HasParameterArea =
false;
6192 for (
unsigned i = 0; i !=
NumOps; ++i) {
6193 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
6194 EVT ArgVT = Outs[i].VT;
6195 EVT OrigVT = Outs[i].ArgVT;
6201 if (
Flags.isByVal()) {
6202 NumGPRsUsed += (
Flags.getByValSize()+7)/8;
6203 if (NumGPRsUsed > NumGPRs)
6204 HasParameterArea =
true;
6211 if (++NumGPRsUsed <= NumGPRs)
6221 if (++NumVRsUsed <= NumVRs)
6225 if (++NumVRsUsed <= NumVRs)
6230 if (++NumFPRsUsed <= NumFPRs)
6234 HasParameterArea =
true;
6241 NumBytes =
alignTo(NumBytes, Alignement);
6244 if (
Flags.isInConsecutiveRegsLast())
6245 NumBytes = ((NumBytes + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
6248 unsigned NumBytesActuallyUsed = NumBytes;
6258 if (HasParameterArea)
6259 NumBytes = std::max(NumBytes, LinkageSize + 8 * PtrByteSize);
6261 NumBytes = LinkageSize;
6276 if (CFlags.IsTailCall)
6288 Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, dl);
6299 unsigned ArgOffset = LinkageSize;
6305 for (
unsigned i = 0; i !=
NumOps; ++i) {
6307 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
6308 EVT ArgVT = Outs[i].VT;
6309 EVT OrigVT = Outs[i].ArgVT;
6318 auto ComputePtrOff = [&]() {
6322 ArgOffset =
alignTo(ArgOffset, Alignment);
6333 GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
6334 GPR_idx = std::min(GPR_idx, NumGPRs);
6341 Arg = DAG.
getNode(ExtOp, dl, MVT::i64, Arg);
6347 if (
Flags.isByVal()) {
6365 EVT VT = (
Size==1) ? MVT::i8 : ((
Size==2) ? MVT::i16 : MVT::i32);
6366 if (GPR_idx != NumGPRs) {
6368 MachinePointerInfo(), VT);
6370 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6372 ArgOffset += PtrByteSize;
6377 if (GPR_idx == NumGPRs &&
Size < 8) {
6379 if (!isLittleEndian) {
6384 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, AddPtr,
6387 ArgOffset += PtrByteSize;
6396 if ((NumGPRs - GPR_idx) * PtrByteSize <
Size)
6397 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, PtrOff,
6402 if (
Size < 8 && GPR_idx != NumGPRs) {
6412 if (!isLittleEndian) {
6416 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, AddPtr,
6422 DAG.
getLoad(PtrVT, dl, Chain, PtrOff, MachinePointerInfo());
6424 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6427 ArgOffset += PtrByteSize;
6433 for (
unsigned j=0;
j<
Size;
j+=PtrByteSize) {
6436 if (GPR_idx != NumGPRs) {
6437 unsigned LoadSizeInBits = std::min(PtrByteSize, (
Size - j)) * 8;
6440 MachinePointerInfo(), ObjType);
6443 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6444 ArgOffset += PtrByteSize;
6446 ArgOffset += ((
Size -
j + PtrByteSize-1)/PtrByteSize)*PtrByteSize;
6458 if (
Flags.isNest()) {
6460 RegsToPass.
push_back(std::make_pair(PPC::X11, Arg));
6467 if (GPR_idx != NumGPRs) {
6468 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Arg));
6473 assert(HasParameterArea &&
6474 "Parameter area must exist to pass an argument in memory.");
6476 true, CFlags.IsTailCall,
false, MemOpChains,
6477 TailCallArguments, dl);
6479 ArgOffset += PtrByteSize;
6482 ArgOffset += PtrByteSize;
6495 bool NeedGPROrStack = CFlags.IsVarArg || FPR_idx == NumFPRs;
6496 bool NeededLoad =
false;
6499 if (FPR_idx != NumFPRs)
6500 RegsToPass.
push_back(std::make_pair(
FPR[FPR_idx++], Arg));
6503 if (!NeedGPROrStack)
6505 else if (GPR_idx != NumGPRs && !IsFastCall) {
6516 ArgVal = DAG.
getNode(ISD::BITCAST, dl, MVT::i64, Arg);
6519 }
else if (!
Flags.isInConsecutiveRegs()) {
6520 ArgVal = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Arg);
6525 }
else if (ArgOffset % PtrByteSize != 0) {
6527 Lo = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, OutVals[i - 1]);
6528 Hi = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Arg);
6529 if (!isLittleEndian)
6534 }
else if (
Flags.isInConsecutiveRegsLast()) {
6535 ArgVal = DAG.
getNode(ISD::BITCAST, dl, MVT::i32, Arg);
6537 if (!isLittleEndian)
6547 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], ArgVal));
6555 !isLittleEndian && !
Flags.isInConsecutiveRegs()) {
6560 assert(HasParameterArea &&
6561 "Parameter area must exist to pass an argument in memory.");
6563 true, CFlags.IsTailCall,
false, MemOpChains,
6564 TailCallArguments, dl);
6571 if (!IsFastCall || NeededLoad) {
6573 Flags.isInConsecutiveRegs()) ? 4 : 8;
6574 if (
Flags.isInConsecutiveRegsLast())
6575 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
6595 if (CFlags.IsVarArg) {
6596 assert(HasParameterArea &&
6597 "Parameter area must exist if we have a varargs call.");
6601 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
6603 if (VR_idx != NumVRs) {
6605 DAG.
getLoad(MVT::v4f32, dl, Store, PtrOff, MachinePointerInfo());
6607 RegsToPass.
push_back(std::make_pair(VR[VR_idx++], Load));
6610 for (
unsigned i=0; i<16; i+=PtrByteSize) {
6611 if (GPR_idx == NumGPRs)
6616 DAG.
getLoad(PtrVT, dl, Store, Ix, MachinePointerInfo());
6618 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6624 if (VR_idx != NumVRs) {
6625 RegsToPass.
push_back(std::make_pair(VR[VR_idx++], Arg));
6630 assert(HasParameterArea &&
6631 "Parameter area must exist to pass an argument in memory.");
6633 true, CFlags.IsTailCall,
true, MemOpChains,
6634 TailCallArguments, dl);
6645 assert((!HasParameterArea || NumBytesActuallyUsed == ArgOffset) &&
6646 "mismatch in size of parameter area");
6647 (void)NumBytesActuallyUsed;
6649 if (!MemOpChains.
empty())
6655 if (CFlags.IsIndirect) {
6659 assert(!CFlags.IsTailCall &&
"Indirect tails calls not supported");
6664 unsigned TOCSaveOffset = Subtarget.getFrameLowering()->getTOCSaveOffset();
6674 if (isELFv2ABI && !CFlags.IsPatchPoint)
6675 RegsToPass.
push_back(std::make_pair((
unsigned)PPC::X12, Callee));
6681 for (
const auto &[
Reg,
N] : RegsToPass) {
6686 if (CFlags.IsTailCall && !IsSibCall)
6690 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
6691 Callee, SPDiff, NumBytes, Ins, InVals, CB);
6698 "Required alignment greater than stack alignment.");
6718 return RequiredAlign <= 8;
6723 return RequiredAlign <= 4;
6731 State.getMachineFunction().getSubtarget());
6732 const bool IsPPC64 = Subtarget.isPPC64();
6733 const unsigned PtrSize = IsPPC64 ? 8 : 4;
6734 const Align PtrAlign(PtrSize);
6735 const Align StackAlign(16);
6738 if (ValVT == MVT::f128)
6742 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
6743 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
6745 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6746 PPC::X7, PPC::X8, PPC::X9, PPC::X10};
6749 PPC::V2, PPC::V3, PPC::V4, PPC::V5,
6750 PPC::V6, PPC::V7, PPC::V8, PPC::V9,
6751 PPC::V10, PPC::V11, PPC::V12, PPC::V13};
6756 MCRegister EnvReg = State.AllocateReg(IsPPC64 ? PPC::X11 : PPC::R11);
6765 if (ByValAlign > StackAlign)
6767 "16 are not supported.");
6770 const Align ObjAlign = ByValAlign > PtrAlign ? ByValAlign : PtrAlign;
6774 if (ByValSize == 0) {
6776 State.getStackSize(), RegVT, LocInfo));
6781 unsigned NextReg = State.getFirstUnallocated(GPRs);
6782 while (NextReg != GPRs.
size() &&
6787 State.AllocateStack(PtrSize, PtrAlign);
6788 assert(
Reg &&
"Alocating register unexpectedly failed.");
6790 NextReg = State.getFirstUnallocated(GPRs);
6793 const unsigned StackSize =
alignTo(ByValSize, ObjAlign);
6794 unsigned Offset = State.AllocateStack(StackSize, ObjAlign);
6814 assert(IsPPC64 &&
"PPC32 should have split i64 values.");
6818 const unsigned Offset = State.AllocateStack(PtrSize, PtrAlign);
6837 State.AllocateStack(IsPPC64 ? 8 : StoreSize,
Align(4));
6843 for (
unsigned I = 0;
I < StoreSize;
I += PtrSize) {
6845 assert(FReg &&
"An FPR should be available when a GPR is reserved.");
6846 if (State.isVarArg()) {
6878 const unsigned VecSize = 16;
6879 const Align VecAlign(VecSize);
6881 if (!State.isVarArg()) {
6884 if (
MCRegister VReg = State.AllocateReg(VR)) {
6891 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6896 unsigned NextRegIndex = State.getFirstUnallocated(GPRs);
6899 while (NextRegIndex != GPRs.
size() &&
6903 State.AllocateStack(PtrSize, PtrAlign);
6904 assert(
Reg &&
"Allocating register unexpectedly failed.");
6906 NextRegIndex = State.getFirstUnallocated(GPRs);
6914 if (
MCRegister VReg = State.AllocateReg(VR)) {
6917 for (
unsigned I = 0;
I != VecSize;
I += PtrSize)
6918 State.AllocateReg(GPRs);
6919 State.AllocateStack(VecSize, VecAlign);
6923 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6929 if (NextRegIndex == GPRs.
size()) {
6930 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6938 if (GPRs[NextRegIndex] == PPC::R9) {
6939 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6943 const MCRegister FirstReg = State.AllocateReg(PPC::R9);
6944 const MCRegister SecondReg = State.AllocateReg(PPC::R10);
6945 assert(FirstReg && SecondReg &&
6946 "Allocating R9 or R10 unexpectedly failed.");
6957 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
6960 for (
unsigned I = 0;
I != VecSize;
I += PtrSize) {
6962 assert(
Reg &&
"Failed to allocated register for vararg vector argument");
6977 assert((IsPPC64 || SVT != MVT::i64) &&
6978 "i64 should have been split for 32-bit codegen.");
6986 return IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
6988 return HasP8Vector ? &PPC::VSSRCRegClass : &PPC::F4RCRegClass;
6990 return HasVSX ? &PPC::VSFRCRegClass : &PPC::F8RCRegClass;
6998 return &PPC::VRRCRegClass;
7011 else if (Flags.isZExt())
7023 "Reg must be a valid argument register!");
7024 return LASize + 4 * (
Reg - PPC::R3);
7029 "Reg must be a valid argument register!");
7030 return LASize + 8 * (
Reg - PPC::X3);
7076SDValue PPCTargetLowering::LowerFormalArguments_AIX(
7083 "Unexpected calling convention!");
7091 const PPCSubtarget &Subtarget = DAG.
getSubtarget<PPCSubtarget>();
7093 const bool IsPPC64 = Subtarget.isPPC64();
7094 const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
7100 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
7101 CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.
getContext());
7105 const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
7106 CCInfo.AllocateStack(LinkageSize,
Align(PtrByteSize));
7107 uint64_t SaveStackPos = CCInfo.getStackSize();
7109 CCInfo.AnalyzeFormalArguments(Ins,
CC_AIX);
7113 for (
size_t I = 0, End = ArgLocs.
size();
I != End; ) {
7114 CCValAssign &VA = ArgLocs[
I++];
7119 EVT ArgVT = Ins[VA.
getValNo()].ArgVT;
7120 bool ArgSignExt = Ins[VA.
getValNo()].Flags.isSExt();
7132 LocVT.
SimpleTy, IsPPC64, Subtarget.hasP8Vector(), Subtarget.hasVSX());
7134 MVT SaveVT = RegClass == &PPC::G8RCRegClass ? MVT::i64 : LocVT;
7140 MachinePointerInfo(),
Align(PtrByteSize));
7146 unsigned StoreSize =
7148 SaveStackPos =
alignTo(SaveStackPos + StoreSize, PtrByteSize);
7151 auto HandleMemLoc = [&]() {
7154 assert((ValSize <= LocSize) &&
7155 "Object size is larger than size of MemLoc");
7158 if (LocSize > ValSize)
7159 CurArgOffset += LocSize - ValSize;
7161 const bool IsImmutable =
7167 DAG.
getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo());
7201 assert(isVarArg &&
"Only use custom memloc for vararg.");
7204 const unsigned OriginalValNo = VA.
getValNo();
7205 (void)OriginalValNo;
7207 auto HandleCustomVecRegLoc = [&]() {
7208 assert(
I != End && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7209 "Missing custom RegLoc.");
7212 "Unexpected Val type for custom RegLoc.");
7214 "ValNo mismatch between custom MemLoc and RegLoc.");
7218 Subtarget.hasVSX()));
7225 HandleCustomVecRegLoc();
7226 HandleCustomVecRegLoc();
7230 if (
I != End && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom()) {
7232 "Only 2 custom RegLocs expected for 64-bit codegen.");
7233 HandleCustomVecRegLoc();
7234 HandleCustomVecRegLoc();
7278 const unsigned Size =
7290 if (
Flags.isByVal()) {
7294 const PPCFrameLowering *FL = Subtarget.getFrameLowering();
7296 const unsigned StackSize =
alignTo(
Flags.getByValSize(), PtrByteSize);
7304 const TargetRegisterClass *RegClass =
7305 IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
7307 auto HandleRegLoc = [&, RegClass, LocVT](
const MCPhysReg PhysReg,
7320 CopyFrom.
getValue(1), dl, CopyFrom,
7330 for (;
Offset != StackSize && ArgLocs[
I].isRegLoc();
7333 "RegLocs should be for ByVal argument.");
7335 const CCValAssign RL = ArgLocs[
I++];
7340 if (
Offset != StackSize) {
7342 "Expected MemLoc for remaining bytes.");
7343 assert(ArgLocs[
I].isMemLoc() &&
"Expected MemLoc for remaining bytes.");
7357 Subtarget.hasVSX()));
7374 const unsigned MinParameterSaveArea = 8 * PtrByteSize;
7376 unsigned CallerReservedArea = std::max<unsigned>(
7377 CCInfo.getStackSize(), LinkageSize + MinParameterSaveArea);
7383 CallerReservedArea =
7392 static const MCPhysReg GPR_32[] = {PPC::R3, PPC::R4, PPC::R5, PPC::R6,
7393 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
7395 static const MCPhysReg GPR_64[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6,
7396 PPC::X7, PPC::X8, PPC::X9, PPC::X10};
7397 const unsigned NumGPArgRegs = std::size(IsPPC64 ? GPR_64 : GPR_32);
7402 for (
unsigned GPRIndex =
7403 (CCInfo.getStackSize() - LinkageSize) / PtrByteSize;
7404 GPRIndex < NumGPArgRegs; ++GPRIndex) {
7407 IsPPC64 ? MF.
addLiveIn(GPR_64[GPRIndex], &PPC::G8RCRegClass)
7408 : MF.
addLiveIn(GPR_32[GPRIndex], &PPC::GPRCRegClass);
7420 if (!MemOps.
empty())
7426SDValue PPCTargetLowering::LowerCall_AIX(
7439 "Unexpected calling convention!");
7441 if (CFlags.IsPatchPoint)
7444 const PPCSubtarget &Subtarget = DAG.
getSubtarget<PPCSubtarget>();
7448 CCState CCInfo(CFlags.CallConv, CFlags.IsVarArg, MF, ArgLocs,
7455 const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
7456 const bool IsPPC64 = Subtarget.isPPC64();
7458 const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
7459 CCInfo.AllocateStack(LinkageSize,
Align(PtrByteSize));
7460 CCInfo.AnalyzeCallOperands(Outs,
CC_AIX);
7468 const unsigned MinParameterSaveAreaSize = 8 * PtrByteSize;
7469 const unsigned NumBytes = std::max<unsigned>(
7470 LinkageSize + MinParameterSaveAreaSize, CCInfo.getStackSize());
7486 for (
unsigned I = 0,
E = ArgLocs.
size();
I !=
E;) {
7487 const unsigned ValNo = ArgLocs[
I].getValNo();
7489 ISD::ArgFlagsTy
Flags = Outs[ValNo].Flags;
7491 if (
Flags.isByVal()) {
7492 const unsigned ByValSize =
Flags.getByValSize();
7500 auto GetLoad = [&](EVT VT,
unsigned LoadOffset) {
7506 MachinePointerInfo(), VT);
7509 unsigned LoadOffset = 0;
7512 while (LoadOffset + PtrByteSize <= ByValSize && ArgLocs[
I].isRegLoc()) {
7515 LoadOffset += PtrByteSize;
7516 const CCValAssign &ByValVA = ArgLocs[
I++];
7518 "Unexpected location for pass-by-value argument.");
7522 if (LoadOffset == ByValSize)
7526 assert(ArgLocs[
I].getValNo() == ValNo &&
7527 "Expected additional location for by-value argument.");
7529 if (ArgLocs[
I].isMemLoc()) {
7530 assert(LoadOffset < ByValSize &&
"Unexpected memloc for by-val arg.");
7531 const CCValAssign &ByValVA = ArgLocs[
I++];
7532 ISD::ArgFlagsTy MemcpyFlags =
Flags;
7535 Chain = CallSeqStart = createMemcpyOutsideCallSeq(
7541 CallSeqStart, MemcpyFlags, DAG, dl);
7550 const unsigned ResidueBytes = ByValSize % PtrByteSize;
7551 assert(ResidueBytes != 0 && LoadOffset + PtrByteSize > ByValSize &&
7552 "Unexpected register residue for by-value argument.");
7554 for (
unsigned Bytes = 0; Bytes != ResidueBytes;) {
7558 : ((
N == 2) ? MVT::i16 : (
N == 4 ? MVT::i32 : MVT::i64));
7568 "Unexpected load emitted during handling of pass-by-value "
7576 ResidueVal = ResidueVal ? DAG.
getNode(
ISD::OR, dl, PtrVT, ResidueVal,
7581 const CCValAssign &ByValVA = ArgLocs[
I++];
7586 CCValAssign &VA = ArgLocs[
I++];
7611 assert(CFlags.IsVarArg &&
"Custom MemLocs only used for Vector args.");
7617 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
7619 const unsigned OriginalValNo = VA.
getValNo();
7621 unsigned LoadOffset = 0;
7622 auto HandleCustomVecRegLoc = [&]() {
7623 assert(
I !=
E &&
"Unexpected end of CCvalAssigns.");
7624 assert(ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7625 "Expected custom RegLoc.");
7626 CCValAssign RegVA = ArgLocs[
I++];
7628 "Custom MemLoc ValNo and custom RegLoc ValNo must match.");
7634 LoadOffset += PtrByteSize;
7640 HandleCustomVecRegLoc();
7641 HandleCustomVecRegLoc();
7643 if (
I !=
E && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7644 ArgLocs[
I].getValNo() == OriginalValNo) {
7646 "Only 2 custom RegLocs expected for 64-bit codegen.");
7647 HandleCustomVecRegLoc();
7648 HandleCustomVecRegLoc();
7659 DAG.
getStore(Chain, dl, Arg, PtrOff,
7661 Subtarget.getFrameLowering()->getStackAlign()));
7668 "Unexpected register handling for calling convention.");
7674 "Custom register handling only expected for VarArg.");
7679 if (Arg.getValueType().getStoreSize() == LocVT.
getStoreSize())
7683 else if (Arg.getValueType().getFixedSizeInBits() <
7691 assert(Arg.getValueType() == MVT::f64 && CFlags.IsVarArg && !IsPPC64 &&
7692 "Unexpected custom register for argument!");
7693 CCValAssign &GPR1 = VA;
7702 CCValAssign &PeekArg = ArgLocs[
I];
7705 CCValAssign &GPR2 = ArgLocs[
I++];
7713 if (!MemOpChains.
empty())
7718 if (CFlags.IsIndirect) {
7719 assert(!CFlags.IsTailCall &&
"Indirect tail-calls not supported.");
7720 const MCRegister TOCBaseReg = Subtarget.getTOCPointerRegister();
7721 const MCRegister StackPtrReg = Subtarget.getStackPointerRegister();
7722 const MVT PtrVT = Subtarget.getScalarIntVT();
7723 const unsigned TOCSaveOffset =
7724 Subtarget.getFrameLowering()->getTOCSaveOffset();
7739 for (
auto Reg : RegsToPass) {
7744 const int SPDiff = 0;
7745 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
7746 Callee, SPDiff, NumBytes, Ins, InVals, CB);
7754 const Type *RetTy)
const {
7756 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
7757 return CCInfo.CheckReturn(
7772 CCInfo.AnalyzeReturn(Outs,
7781 for (
unsigned i = 0, RealResIdx = 0; i != RVLocs.
size(); ++i, ++RealResIdx) {
7782 CCValAssign &VA = RVLocs[i];
7785 SDValue Arg = OutVals[RealResIdx];
7800 if (Subtarget.hasSPE() && VA.
getLocVT() == MVT::f64) {
7801 bool isLittleEndian = Subtarget.isLittleEndian();
7804 DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
7808 SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
7823 RetOps.push_back(Glue);
7825 return DAG.
getNode(PPCISD::RET_GLUE, dl, MVT::Other, RetOps);
7829PPCTargetLowering::LowerGET_DYNAMIC_AREA_OFFSET(
SDValue Op,
7834 EVT IntVT =
Op.getValueType();
7838 SDValue FPSIdx = getFramePointerFrameIndex(DAG);
7842 return DAG.
getNode(PPCISD::DYNAREAOFFSET, dl, VTs,
Ops);
7854 bool isPPC64 = Subtarget.isPPC64();
7855 unsigned SP = isPPC64 ? PPC::X1 : PPC::R1;
7864 DAG.
getLoad(PtrVT, dl, Chain, StackPtr, MachinePointerInfo());
7870 return DAG.
getStore(Chain, dl, LoadLinkSP, StackPtr, MachinePointerInfo());
7875 bool isPPC64 = Subtarget.isPPC64();
7880 PPCFunctionInfo *FI = MF.
getInfo<PPCFunctionInfo>();
7886 int LROffset = Subtarget.getFrameLowering()->getReturnSaveOffset();
7896PPCTargetLowering::getFramePointerFrameIndex(
SelectionDAG & DAG)
const {
7898 bool isPPC64 = Subtarget.isPPC64();
7903 PPCFunctionInfo *FI = MF.
getInfo<PPCFunctionInfo>();
7909 int FPOffset = Subtarget.getFrameLowering()->getFramePointerSaveOffset();
7932 SDValue FPSIdx = getFramePointerFrameIndex(DAG);
7934 SDVTList VTs = DAG.
getVTList(PtrVT, MVT::Other);
7936 return DAG.
getNode(PPCISD::PROBED_ALLOCA, dl, VTs,
Ops);
7937 return DAG.
getNode(PPCISD::DYNALLOC, dl, VTs,
Ops);
7944 bool isPPC64 = Subtarget.isPPC64();
7954 return DAG.
getNode(PPCISD::EH_SJLJ_SETJMP,
DL,
7956 Op.getOperand(0),
Op.getOperand(1));
7962 return DAG.
getNode(PPCISD::EH_SJLJ_LONGJMP,
DL, MVT::Other,
7963 Op.getOperand(0),
Op.getOperand(1));
7967 if (
Op.getValueType().isVector())
7968 return LowerVectorLoad(
Op, DAG);
7970 assert(
Op.getValueType() == MVT::i1 &&
7971 "Custom lowering only for i1 loads");
7980 MachineMemOperand *MMO =
LD->getMemOperand();
7984 BasePtr, MVT::i8, MMO);
7992 if (
Op.getOperand(1).getValueType().isVector())
7993 return LowerVectorStore(
Op, DAG);
7995 assert(
Op.getOperand(1).getValueType() == MVT::i1 &&
7996 "Custom lowering only for i1 stores");
8006 MachineMemOperand *MMO =
ST->getMemOperand();
8015 assert(
Op.getValueType() == MVT::i1 &&
8016 "Custom lowering only for i1 results");
8044 EVT TrgVT =
Op.getValueType();
8068 if (SrcSize == 256) {
8079 Op1 = SrcSize == 128 ? N1 :
widenVec(DAG, N1,
DL);
8085 SmallVector<int, 16> ShuffV;
8086 if (Subtarget.isLittleEndian())
8087 for (
unsigned i = 0; i < TrgNumElts; ++i)
8090 for (
unsigned i = 1; i <= TrgNumElts; ++i)
8094 for (
unsigned i = TrgNumElts; i < WideNumElts; ++i)
8098 Op1 = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Op1);
8099 Op2 = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Op2);
8107 EVT ResVT =
Op.getValueType();
8108 EVT CmpVT =
Op.getOperand(0).getValueType();
8110 SDValue TV =
Op.getOperand(2), FV =
Op.getOperand(3);
8116 if (!Subtarget.hasP9Vector() && CmpVT == MVT::f128) {
8129 SDNodeFlags
Flags =
Op.getNode()->getFlags();
8133 if (Subtarget.hasP9Vector() &&
LHS == TV &&
RHS == FV) {
8165 if (
LHS.getValueType() == MVT::f32)
8167 Sel1 = DAG.
getNode(PPCISD::FSEL, dl, ResVT,
LHS, TV, FV);
8169 Sel1 = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Sel1);
8170 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8171 DAG.
getNode(ISD::FNEG, dl, MVT::f64,
LHS), Sel1, FV);
8178 if (
LHS.getValueType() == MVT::f32)
8180 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
LHS, TV, FV);
8187 if (
LHS.getValueType() == MVT::f32)
8189 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8190 DAG.
getNode(ISD::FNEG, dl, MVT::f64,
LHS), TV, FV);
8201 if (
Cmp.getValueType() == MVT::f32)
8202 Cmp = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp);
8203 Sel1 = DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8205 Sel1 = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Sel1);
8206 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8207 DAG.
getNode(ISD::FNEG, dl, MVT::f64, Cmp), Sel1, FV);
8211 if (
Cmp.getValueType() == MVT::f32)
8212 Cmp = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp);
8213 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV);
8217 if (
Cmp.getValueType() == MVT::f32)
8218 Cmp = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp);
8219 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8223 if (
Cmp.getValueType() == MVT::f32)
8224 Cmp = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp);
8225 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV);
8229 if (
Cmp.getValueType() == MVT::f32)
8230 Cmp = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp);
8231 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8240 case PPCISD::FCTIDZ:
8241 return PPCISD::STRICT_FCTIDZ;
8242 case PPCISD::FCTIWZ:
8243 return PPCISD::STRICT_FCTIWZ;
8244 case PPCISD::FCTIDUZ:
8245 return PPCISD::STRICT_FCTIDUZ;
8246 case PPCISD::FCTIWUZ:
8247 return PPCISD::STRICT_FCTIWUZ;
8249 return PPCISD::STRICT_FCFID;
8250 case PPCISD::FCFIDU:
8251 return PPCISD::STRICT_FCFIDU;
8252 case PPCISD::FCFIDS:
8253 return PPCISD::STRICT_FCFIDS;
8254 case PPCISD::FCFIDUS:
8255 return PPCISD::STRICT_FCFIDUS;
8262 bool IsStrict =
Op->isStrictFPOpcode();
8271 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8273 MVT DestTy =
Op.getSimpleValueType();
8274 assert(Src.getValueType().isFloatingPoint() &&
8275 (DestTy == MVT::i8 || DestTy == MVT::i16 || DestTy == MVT::i32 ||
8276 DestTy == MVT::i64) &&
8277 "Invalid FP_TO_INT types");
8278 if (Src.getValueType() == MVT::f32) {
8282 DAG.
getVTList(MVT::f64, MVT::Other), {Chain, Src}, Flags);
8285 Src = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Src);
8287 if ((DestTy == MVT::i8 || DestTy == MVT::i16) && Subtarget.hasP9Vector())
8293 Opc = IsSigned ? PPCISD::FCTIWZ
8294 : (Subtarget.hasFPCVT() ? PPCISD::FCTIWUZ : PPCISD::FCTIDZ);
8297 assert((IsSigned || Subtarget.hasFPCVT()) &&
8298 "i64 FP_TO_UINT is supported only with FPCVT");
8299 Opc = IsSigned ? PPCISD::FCTIDZ : PPCISD::FCTIDUZ;
8301 EVT ConvTy = Src.getValueType() == MVT::f128 ? MVT::f128 : MVT::f64;
8313void PPCTargetLowering::LowerFP_TO_INTForReuse(
SDValue Op, ReuseLoadInfo &RLI,
8315 const SDLoc &dl)
const {
8319 bool IsStrict =
Op->isStrictFPOpcode();
8322 bool i32Stack =
Op.getValueType() == MVT::i32 && Subtarget.hasSTFIWX() &&
8323 (IsSigned || Subtarget.hasFPCVT());
8326 MachinePointerInfo MPI =
8334 Alignment =
Align(4);
8335 MachineMemOperand *MMO =
8341 Chain = DAG.
getStore(Chain, dl, Tmp, FIPtr, MPI, Alignment);
8345 if (
Op.getValueType() == MVT::i32 && !i32Stack &&
8346 !Subtarget.isLittleEndian()) {
8355 RLI.Alignment = Alignment;
8363 const SDLoc &dl)
const {
8366 if (
Op->isStrictFPOpcode())
8373 const SDLoc &dl)
const {
8374 bool IsStrict =
Op->isStrictFPOpcode();
8377 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8378 EVT SrcVT = Src.getValueType();
8379 EVT DstVT =
Op.getValueType();
8382 if (SrcVT == MVT::f128)
8383 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8387 if (SrcVT == MVT::ppcf128) {
8388 if (DstVT == MVT::i32) {
8393 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8404 {Op.getOperand(0), Lo, Hi}, Flags);
8407 {Res.getValue(1), Res}, Flags);
8413 const uint64_t TwoE31[] = {0x41e0000000000000LL, 0};
8437 {Chain, Src, FltOfs}, Flags);
8441 {Chain, Val}, Flags);
8444 dl, DstVT, Sel, DAG.
getConstant(0, dl, DstVT), SignMask);
8462 if (Subtarget.hasDirectMove() && Subtarget.isPPC64())
8463 return LowerFP_TO_INTDirectMove(
Op, DAG, dl);
8466 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8468 return DAG.
getLoad(
Op.getValueType(), dl, RLI.Chain, RLI.Ptr, RLI.MPI,
8469 RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo, RLI.Ranges);
8480bool PPCTargetLowering::canReuseLoadAddress(
SDValue Op,
EVT MemVT,
8485 if (
Op->isStrictFPOpcode())
8490 (Subtarget.hasFPCVT() ||
Op.getValueType() == MVT::i32);
8494 Op.getOperand(0).getValueType())) {
8496 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8501 if (!LD ||
LD->getExtensionType() != ET ||
LD->isVolatile() ||
8502 LD->isNonTemporal())
8504 if (
LD->getMemoryVT() != MemVT)
8514 RLI.Ptr =
LD->getBasePtr();
8515 if (
LD->isIndexed() && !
LD->getOffset().isUndef()) {
8517 "Non-pre-inc AM on PPC?");
8522 RLI.Chain =
LD->getChain();
8523 RLI.MPI =
LD->getPointerInfo();
8524 RLI.IsDereferenceable =
LD->isDereferenceable();
8525 RLI.IsInvariant =
LD->isInvariant();
8526 RLI.Alignment =
LD->getAlign();
8527 RLI.AAInfo =
LD->getAAInfo();
8528 RLI.Ranges =
LD->getRanges();
8530 RLI.ResChain =
SDValue(LD,
LD->isIndexed() ? 2 : 1);
8537bool PPCTargetLowering::directMoveIsProfitable(
const SDValue &
Op)
const {
8538 SDNode *Origin =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0).getNode();
8545 if (!Subtarget.hasP9Vector() &&
8549 for (SDUse &Use : Origin->
uses()) {
8552 if (
Use.getResNo() != 0)
8579 bool IsSingle =
Op.getValueType() == MVT::f32 && Subtarget.hasFPCVT();
8580 unsigned ConvOpc = IsSingle ? (IsSigned ? PPCISD::FCFIDS : PPCISD::FCFIDUS)
8581 : (IsSigned ? PPCISD::FCFID : PPCISD::FCFIDU);
8582 EVT ConvTy = IsSingle ? MVT::f32 : MVT::f64;
8583 if (
Op->isStrictFPOpcode()) {
8585 Chain =
Op.getOperand(0);
8587 DAG.
getVTList(ConvTy, MVT::Other), {Chain, Src}, Flags);
8589 return DAG.
getNode(ConvOpc, dl, ConvTy, Src);
8597 const SDLoc &dl)
const {
8598 assert((
Op.getValueType() == MVT::f32 ||
8599 Op.getValueType() == MVT::f64) &&
8600 "Invalid floating point type as target of conversion");
8601 assert(Subtarget.hasFPCVT() &&
8602 "Int to FP conversions with direct moves require FPCVT");
8603 SDValue Src =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0);
8604 bool WordInt = Src.getSimpleValueType().SimpleTy == MVT::i32;
8607 unsigned MovOpc = (WordInt && !
Signed) ? PPCISD::MTVSRZ : PPCISD::MTVSRA;
8626 for (
unsigned i = 1; i < NumConcat; ++i)
8633 const SDLoc &dl)
const {
8634 bool IsStrict =
Op->isStrictFPOpcode();
8635 unsigned Opc =
Op.getOpcode();
8636 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8639 "Unexpected conversion type");
8640 assert((
Op.getValueType() == MVT::v2f64 ||
Op.getValueType() == MVT::v4f32) &&
8641 "Supports conversions to v2f64/v4f32 only.");
8645 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8648 bool FourEltRes =
Op.getValueType() == MVT::v4f32;
8653 MVT IntermediateVT = FourEltRes ? MVT::v4i32 : MVT::v2i64;
8655 SmallVector<int, 16> ShuffV;
8656 for (
unsigned i = 0; i < WideNumElts; ++i)
8659 int Stride = FourEltRes ? WideNumElts / 4 : WideNumElts / 2;
8660 int SaveElts = FourEltRes ? 4 : 2;
8661 if (Subtarget.isLittleEndian())
8662 for (
int i = 0; i < SaveElts; i++)
8663 ShuffV[i * Stride] = i;
8665 for (
int i = 1; i <= SaveElts; i++)
8666 ShuffV[i * Stride - 1] = i - 1;
8674 Arrange = DAG.
getBitcast(IntermediateVT, Arrange);
8675 EVT ExtVT = Src.getValueType();
8676 if (Subtarget.hasP9Altivec())
8683 Extend = DAG.
getNode(ISD::BITCAST, dl, IntermediateVT, Arrange);
8687 {Op.getOperand(0), Extend}, Flags);
8689 return DAG.
getNode(
Opc, dl,
Op.getValueType(), Extend);
8697 bool IsStrict =
Op->isStrictFPOpcode();
8698 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8703 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8705 EVT InVT = Src.getValueType();
8706 EVT OutVT =
Op.getValueType();
8709 return LowerINT_TO_FPVector(
Op, DAG, dl);
8712 if (
Op.getValueType() == MVT::f128)
8713 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8716 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
8719 if (Src.getValueType() == MVT::i1) {
8731 if (Subtarget.hasDirectMove() && directMoveIsProfitable(
Op) &&
8732 Subtarget.isPPC64() && Subtarget.hasFPCVT())
8733 return LowerINT_TO_FPDirectMove(
Op, DAG, dl);
8735 assert((IsSigned || Subtarget.hasFPCVT()) &&
8736 "UINT_TO_FP is supported only with FPCVT");
8738 if (Src.getValueType() == MVT::i64) {
8753 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT() &&
8754 !
Op->getFlags().hasApproximateFuncs()) {
8794 if (canReuseLoadAddress(SINT, MVT::i64, RLI, DAG)) {
8795 Bits = DAG.
getLoad(MVT::f64, dl, RLI.Chain, RLI.Ptr, RLI.MPI,
8796 RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo, RLI.Ranges);
8799 }
else if (Subtarget.hasLFIWAX() &&
8800 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::SEXTLOAD)) {
8801 MachineMemOperand *MMO =
8803 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8807 Ops, MVT::i32, MMO);
8810 }
else if (Subtarget.hasFPCVT() &&
8811 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::ZEXTLOAD)) {
8812 MachineMemOperand *MMO =
8814 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8818 Ops, MVT::i32, MMO);
8821 }
else if (((Subtarget.hasLFIWAX() &&
8823 (Subtarget.hasFPCVT() &&
8838 "Expected an i32 store");
8844 RLI.Alignment =
Align(4);
8846 MachineMemOperand *MMO =
8848 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8851 PPCISD::LFIWZX : PPCISD::LFIWAX,
8852 dl, DAG.
getVTList(MVT::f64, MVT::Other),
8853 Ops, MVT::i32, MMO);
8854 Chain =
Bits.getValue(1);
8856 Bits = DAG.
getNode(ISD::BITCAST, dl, MVT::f64, SINT);
8862 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
8866 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)},
8875 assert(Src.getValueType() == MVT::i32 &&
8876 "Unhandled INT_TO_FP type in custom expander!");
8886 if (Subtarget.hasLFIWAX() || Subtarget.hasFPCVT()) {
8889 if (!(ReusingLoad = canReuseLoadAddress(Src, MVT::i32, RLI, DAG))) {
8899 "Expected an i32 store");
8905 RLI.Alignment =
Align(4);
8908 MachineMemOperand *MMO =
8910 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8916 if (ReusingLoad && RLI.ResChain) {
8920 assert(Subtarget.isPPC64() &&
8921 "i32->FP without LFIWAX supported only on PPC64");
8930 Chain, dl, Ext64, FIdx,
8936 MVT::f64, dl, Chain, FIdx,
8945 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
8949 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)}, Flags);
8966 uint64_t
Mode = CVal->getZExtValue();
8967 assert(
Mode < 4 &&
"Unsupported rounding mode!");
8968 unsigned InternalRnd =
Mode ^ (~(
Mode >> 1) & 1);
8969 if (Subtarget.isISA3_0())
8972 PPC::MFFSCRNI, Dl, {MVT::f64, MVT::Other},
8973 {DAG.getConstant(InternalRnd, Dl, MVT::i32, true), Chain}),
8976 (InternalRnd & 2) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
8977 {DAG.
getConstant(30, Dl, MVT::i32,
true), Chain});
8979 (InternalRnd & 1) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
8997 if (!Subtarget.isISA3_0()) {
8998 MFFS = DAG.
getNode(PPCISD::MFFS, Dl, {MVT::f64, MVT::Other}, Chain);
9002 if (Subtarget.isPPC64()) {
9003 if (Subtarget.isISA3_0()) {
9008 PPC::RLDIMI, Dl, MVT::i64,
9009 {DAG.
getNode(ISD::BITCAST, Dl, MVT::i64, MFFS),
9013 NewFPSCR =
SDValue(InsertRN, 0);
9015 NewFPSCR = DAG.
getNode(ISD::BITCAST, Dl, MVT::f64, NewFPSCR);
9020 SDValue Addr = Subtarget.isLittleEndian()
9024 if (Subtarget.isISA3_0()) {
9025 Chain = DAG.
getStore(Chain, Dl, DstFlag, Addr, MachinePointerInfo());
9027 Chain = DAG.
getStore(Chain, Dl, MFFS, StackSlot, MachinePointerInfo());
9029 DAG.
getLoad(MVT::i32, Dl, Chain, Addr, MachinePointerInfo());
9032 PPC::RLWIMI, Dl, MVT::i32,
9033 {Tmp, DstFlag, DAG.getTargetConstant(0, Dl, MVT::i32),
9034 DAG.getTargetConstant(30, Dl, MVT::i32),
9035 DAG.getTargetConstant(31, Dl, MVT::i32)}),
9037 Chain = DAG.
getStore(Chain, Dl, Tmp, Addr, MachinePointerInfo());
9040 DAG.
getLoad(MVT::f64, Dl, Chain, StackSlot, MachinePointerInfo());
9043 if (Subtarget.isISA3_0())
9049 PPC::MTFSF, Dl, MVT::Other,
9077 EVT VT =
Op.getValueType();
9082 SDValue MFFS = DAG.
getNode(PPCISD::MFFS, dl, {MVT::f64, MVT::Other}, Chain);
9088 DAG.
getNode(ISD::BITCAST, dl, MVT::i64, MFFS));
9093 Chain = DAG.
getStore(Chain, dl, MFFS, StackSlot, MachinePointerInfo());
9097 "Stack slot adjustment is valid only on big endian subtargets!");
9100 CWD = DAG.
getLoad(MVT::i32, dl, Chain, Addr, MachinePointerInfo());
9127 EVT VT =
Op.getValueType();
9131 VT ==
Op.getOperand(1).getValueType() &&
9151 SDValue OutOps[] = { OutLo, OutHi };
9156 EVT VT =
Op.getValueType();
9160 VT ==
Op.getOperand(1).getValueType() &&
9180 SDValue OutOps[] = { OutLo, OutHi };
9186 EVT VT =
Op.getValueType();
9189 VT ==
Op.getOperand(1).getValueType() &&
9209 SDValue OutOps[] = { OutLo, OutHi };
9216 EVT VT =
Op.getValueType();
9223 EVT AmtVT =
Z.getValueType();
9233 X = DAG.
getNode(PPCISD::SHL, dl, VT,
X, IsFSHL ? Z : SubZ);
9234 Y = DAG.
getNode(PPCISD::SRL, dl, VT,
Y, IsFSHL ? SubZ : Z);
9246 static const MVT VTys[] = {
9247 MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
9250 EVT ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1];
9253 if (Val == ((1LLU << (SplatSize * 8)) - 1)) {
9258 EVT CanonicalVT = VTys[SplatSize-1];
9271 const SDLoc &dl,
EVT DestVT = MVT::Other) {
9272 if (DestVT == MVT::Other) DestVT =
Op.getValueType();
9281 EVT DestVT = MVT::Other) {
9282 if (DestVT == MVT::Other) DestVT =
LHS.getValueType();
9291 EVT DestVT = MVT::Other) {
9294 DAG.
getConstant(IID, dl, MVT::i32), Op0, Op1, Op2);
9306 for (
unsigned i = 0; i != 16; ++i)
9309 return DAG.
getNode(ISD::BITCAST, dl, VT,
T);
9327 EVT VecVT = V->getValueType(0);
9328 bool RightType = VecVT == MVT::v2f64 ||
9329 (HasP8Vector && VecVT == MVT::v4f32) ||
9330 (HasDirectMove && (VecVT == MVT::v2i64 || VecVT == MVT::v4i32));
9334 bool IsSplat =
true;
9335 bool IsLoad =
false;
9341 if (V->isConstant())
9343 for (
int i = 0, e = V->getNumOperands(); i < e; ++i) {
9344 if (V->getOperand(i).isUndef())
9348 if (V->getOperand(i).getOpcode() == ISD::LOAD ||
9350 V->getOperand(i).getOperand(0).getOpcode() == ISD::LOAD) ||
9352 V->getOperand(i).getOperand(0).getOpcode() == ISD::LOAD) ||
9354 V->getOperand(i).getOperand(0).getOpcode() == ISD::LOAD))
9358 if (V->getOperand(i) != Op0 ||
9359 (!IsLoad && !V->isOnlyUserOf(V->getOperand(i).getNode())))
9362 return !(IsSplat && IsLoad);
9372 (
Op.getValueType() != MVT::f128))
9377 if ((
Lo.getValueType() != MVT::i64) || (
Hi.getValueType() != MVT::i64))
9380 if (!Subtarget.isLittleEndian())
9383 return DAG.
getNode(PPCISD::BUILD_FP128, dl, MVT::f128,
Lo,
Hi);
9388 while (InputLoad->
getOpcode() == ISD::BITCAST)
9391 InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED) {
9392 IsPermuted = InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED;
9395 if (InputLoad->
getOpcode() != ISD::LOAD)
9405 APFloat APFloatToConvert = ArgAPFloat;
9406 bool LosesInfo =
true;
9411 ArgAPFloat = APFloatToConvert;
9433 APFloat APFloatToConvert = ArgAPFloat;
9434 bool LosesInfo =
true;
9438 return (!LosesInfo && !APFloatToConvert.
isDenormal());
9447 EVT Ty =
Op->getValueType(0);
9450 if ((Ty == MVT::v2f64 || Ty == MVT::v4f32 || Ty == MVT::v4i32) &&
9459 if ((Ty == MVT::v8i16 || Ty == MVT::v16i8) &&
ISD::isEXTLoad(InputNode) &&
9463 if (Ty == MVT::v2i64) {
9466 if (MemVT == MVT::i32) {
9468 Opcode = PPCISD::ZEXT_LD_SPLAT;
9470 Opcode = PPCISD::SEXT_LD_SPLAT;
9478 bool IsLittleEndian) {
9484 APInt ConstValue(VTSize, 0);
9488 unsigned BitPos = 0;
9496 ConstValue.
insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth),
9497 IsLittleEndian ? BitPos : VTSize - EltWidth - BitPos);
9501 for (
unsigned J = 0; J < 16; ++J) {
9503 if (ExtractValue != 0x00 && ExtractValue != 0xFF)
9505 if (ExtractValue == 0xFF)
9520 assert(BVN &&
"Expected a BuildVectorSDNode in LowerBUILD_VECTOR");
9522 if (Subtarget.hasP10Vector()) {
9523 APInt BitMask(32, 0);
9529 BitMask != 0 && BitMask != 0xffff) {
9531 MachineSDNode *MSDNode =
9537 SDV = DAG.
getNode(ISD::BITCAST, dl, DVT, SDV);
9543 if (
SDValue VecPat = combineBVLoadsSpecialValue(
Op, DAG))
9547 APInt APSplatBits, APSplatUndef;
9548 unsigned SplatBitSize;
9550 bool BVNIsConstantSplat =
9552 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
9558 if (BVNIsConstantSplat && (SplatBitSize == 64) &&
9559 Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
9562 if ((
Op->getValueType(0) == MVT::v2f64) &&
9565 PPCISD::XXSPLTI_SP_TO_DP, dl, MVT::v2f64,
9581 PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9587 DAG.
getNode(PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9595 bool IsSplat64 =
false;
9596 uint64_t SplatBits = 0;
9597 int32_t SextVal = 0;
9598 if (BVNIsConstantSplat && SplatBitSize <= 64) {
9600 if (SplatBitSize <= 32) {
9602 }
else if (SplatBitSize == 64 && Subtarget.hasP8Altivec()) {
9603 int64_t Splat64Val =
static_cast<int64_t
>(SplatBits);
9604 bool P9Vector = Subtarget.hasP9Vector();
9605 int32_t
Hi = P9Vector ? 127 : 15;
9606 int32_t
Lo = P9Vector ? -128 : -16;
9607 IsSplat64 = Splat64Val >=
Lo && Splat64Val <=
Hi;
9608 SextVal =
static_cast<int32_t
>(SplatBits);
9612 if (!BVNIsConstantSplat || (SplatBitSize > 32 && !IsSplat64)) {
9613 unsigned NewOpcode = PPCISD::LD_SPLAT;
9619 const SDValue *InputLoad = &
Op.getOperand(0);
9624 unsigned MemorySize =
LD->getMemoryVT().getScalarSizeInBits();
9625 unsigned ElementSize =
9626 MemorySize * ((NewOpcode == PPCISD::LD_SPLAT) ? 1 : 2);
9628 assert(((ElementSize == 2 * MemorySize)
9629 ? (NewOpcode == PPCISD::ZEXT_LD_SPLAT ||
9630 NewOpcode == PPCISD::SEXT_LD_SPLAT)
9631 : (NewOpcode == PPCISD::LD_SPLAT)) &&
9632 "Unmatched element size and opcode!\n");
9637 unsigned NumUsesOfInputLD = 128 / ElementSize;
9639 if (BVInOp.isUndef())
9654 if (NumUsesOfInputLD == 1 &&
9655 (
Op->getValueType(0) == MVT::v2i64 && NewOpcode != PPCISD::LD_SPLAT &&
9656 !Subtarget.isLittleEndian() && Subtarget.hasVSX() &&
9657 Subtarget.hasLFIWAX()))
9665 if (NumUsesOfInputLD == 1 && Subtarget.isLittleEndian() &&
9666 Subtarget.isISA3_1() && ElementSize <= 16)
9669 assert(NumUsesOfInputLD > 0 &&
"No uses of input LD of a build_vector?");
9671 Subtarget.hasVSX()) {
9678 NewOpcode, dl, DAG.
getVTList(
Op.getValueType(), MVT::Other),
Ops,
9679 LD->getMemoryVT(),
LD->getMemOperand());
9691 if (Subtarget.hasVSX() && Subtarget.isPPC64() &&
9693 Subtarget.hasP8Vector()))
9699 unsigned SplatSize = SplatBitSize / 8;
9704 if (SplatBits == 0) {
9706 if (
Op.getValueType() != MVT::v4i32 || HasAnyUndefs) {
9708 Op = DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Z);
9718 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 2)
9720 Op.getValueType(), DAG, dl);
9722 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 4)
9727 if (Subtarget.hasP9Vector() && SplatSize == 1)
9733 if (SextVal >= -16 && SextVal <= 15) {
9736 unsigned UseSize = SplatSize == 8 ? 4 : SplatSize;
9746 if (Subtarget.hasP9Vector() && SextVal >= -128 && SextVal <= 127) {
9752 switch (SplatSize) {
9756 IID = Intrinsic::ppc_altivec_vupklsb;
9760 IID = Intrinsic::ppc_altivec_vextsb2w;
9764 IID = Intrinsic::ppc_altivec_vextsb2d;
9771 assert(!IsSplat64 &&
"Unhandled 64-bit splat pattern");
9780 if (SextVal >= -32 && SextVal <= 31) {
9785 EVT VT = (SplatSize == 1 ? MVT::v16i8 :
9786 (SplatSize == 2 ? MVT::v8i16 : MVT::v4i32));
9789 if (VT ==
Op.getValueType())
9792 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), RetVal);
9798 if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) {
9808 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Res);
9812 static const signed char SplatCsts[] = {
9813 -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
9814 -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
9817 for (
unsigned idx = 0; idx < std::size(SplatCsts); ++idx) {
9820 int i = SplatCsts[idx];
9824 unsigned TypeShiftAmt = i & (SplatBitSize-1);
9827 if (SextVal == (
int)((
unsigned)i << TypeShiftAmt)) {
9829 static const unsigned IIDs[] = {
9830 Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
9831 Intrinsic::ppc_altivec_vslw
9834 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Res);
9838 if (SextVal == (
int)((
unsigned)i >> TypeShiftAmt)) {
9840 static const unsigned IIDs[] = {
9841 Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
9842 Intrinsic::ppc_altivec_vsrw
9845 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Res);
9849 if (SextVal == (
int)(((
unsigned)i << TypeShiftAmt) |
9850 ((
unsigned)i >> (SplatBitSize-TypeShiftAmt)))) {
9852 static const unsigned IIDs[] = {
9853 Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0,
9854 Intrinsic::ppc_altivec_vrlw
9857 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Res);
9861 if (SextVal == (
int)(((
unsigned)i << 8) | (i < 0 ? 0xFF : 0))) {
9863 unsigned Amt = Subtarget.isLittleEndian() ? 15 : 1;
9867 if (SextVal == (
int)(((
unsigned)i << 16) | (i < 0 ? 0xFFFF : 0))) {
9869 unsigned Amt = Subtarget.isLittleEndian() ? 14 : 2;
9873 if (SextVal == (
int)(((
unsigned)i << 24) | (i < 0 ? 0xFFFFFF : 0))) {
9875 unsigned Amt = Subtarget.isLittleEndian() ? 13 : 3;
9888 unsigned OpNum = (PFEntry >> 26) & 0x0F;
9889 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
9890 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
9906 if (LHSID == (1*9+2)*9+3)
return LHS;
9907 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
9919 ShufIdxs[ 0] = 0; ShufIdxs[ 1] = 1; ShufIdxs[ 2] = 2; ShufIdxs[ 3] = 3;
9920 ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19;
9921 ShufIdxs[ 8] = 4; ShufIdxs[ 9] = 5; ShufIdxs[10] = 6; ShufIdxs[11] = 7;
9922 ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23;
9925 ShufIdxs[ 0] = 8; ShufIdxs[ 1] = 9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11;
9926 ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27;
9927 ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15;
9928 ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31;
9931 for (
unsigned i = 0; i != 16; ++i)
9932 ShufIdxs[i] = (i&3)+0;
9935 for (
unsigned i = 0; i != 16; ++i)
9936 ShufIdxs[i] = (i&3)+4;
9939 for (
unsigned i = 0; i != 16; ++i)
9940 ShufIdxs[i] = (i&3)+8;
9943 for (
unsigned i = 0; i != 16; ++i)
9944 ShufIdxs[i] = (i&3)+12;
9954 OpLHS = DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, OpLHS);
9955 OpRHS = DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, OpRHS);
9957 return DAG.
getNode(ISD::BITCAST, dl, VT,
T);
9965 const unsigned BytesInVector = 16;
9966 bool IsLE = Subtarget.isLittleEndian();
9970 unsigned ShiftElts = 0, InsertAtByte = 0;
9974 unsigned LittleEndianShifts[] = {8, 7, 6, 5, 4, 3, 2, 1,
9975 0, 15, 14, 13, 12, 11, 10, 9};
9976 unsigned BigEndianShifts[] = {9, 10, 11, 12, 13, 14, 15, 0,
9977 1, 2, 3, 4, 5, 6, 7, 8};
9979 ArrayRef<int>
Mask =
N->getMask();
9980 int OriginalOrder[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
9992 bool FoundCandidate =
false;
9996 unsigned VINSERTBSrcElem = IsLE ? 8 : 7;
9999 for (
unsigned i = 0; i < BytesInVector; ++i) {
10000 unsigned CurrentElement =
Mask[i];
10003 if (V2.
isUndef() && CurrentElement != VINSERTBSrcElem)
10006 bool OtherElementsInOrder =
true;
10009 for (
unsigned j = 0;
j < BytesInVector; ++
j) {
10016 (!V2.
isUndef() && CurrentElement < BytesInVector) ? BytesInVector : 0;
10017 if (Mask[j] != OriginalOrder[j] + MaskOffset) {
10018 OtherElementsInOrder =
false;
10025 if (OtherElementsInOrder) {
10032 ShiftElts = IsLE ? LittleEndianShifts[CurrentElement & 0xF]
10033 : BigEndianShifts[CurrentElement & 0xF];
10034 Swap = CurrentElement < BytesInVector;
10036 InsertAtByte = IsLE ? BytesInVector - (i + 1) : i;
10037 FoundCandidate =
true;
10042 if (!FoundCandidate)
10052 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10054 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8, V1, Shl,
10057 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8, V1, V2,
10066 const unsigned NumHalfWords = 8;
10067 const unsigned BytesInVector = NumHalfWords * 2;
10072 bool IsLE = Subtarget.isLittleEndian();
10076 unsigned ShiftElts = 0, InsertAtByte = 0;
10080 unsigned LittleEndianShifts[] = {4, 3, 2, 1, 0, 7, 6, 5};
10081 unsigned BigEndianShifts[] = {5, 6, 7, 0, 1, 2, 3, 4};
10084 uint32_t OriginalOrderLow = 0x1234567;
10085 uint32_t OriginalOrderHigh = 0x89ABCDEF;
10088 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10089 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10106 bool FoundCandidate =
false;
10109 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10110 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10112 uint32_t MaskOtherElts = ~(0xF <<
MaskShift);
10113 uint32_t TargetOrder = 0x0;
10120 unsigned VINSERTHSrcElem = IsLE ? 4 : 3;
10121 TargetOrder = OriginalOrderLow;
10125 if (MaskOneElt == VINSERTHSrcElem &&
10126 (Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10127 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10128 FoundCandidate =
true;
10134 (MaskOneElt < NumHalfWords) ? OriginalOrderHigh : OriginalOrderLow;
10136 if ((Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10138 ShiftElts = IsLE ? LittleEndianShifts[MaskOneElt & 0x7]
10139 : BigEndianShifts[MaskOneElt & 0x7];
10140 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10141 Swap = MaskOneElt < NumHalfWords;
10142 FoundCandidate =
true;
10148 if (!FoundCandidate)
10160 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10163 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10165 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, Ins);
10168 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10170 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, Ins);
10183 auto ShuffleMask = SVN->
getMask();
10198 ShuffleMask = CommutedSV->
getMask();
10207 APInt APSplatValue, APSplatUndef;
10208 unsigned SplatBitSize;
10211 HasAnyUndefs, 0, !Subtarget.isLittleEndian()) ||
10223 bool IsLE = Subtarget.isLittleEndian();
10224 if ((ShuffleMask[0] == 0 && ShuffleMask[8] == 8) &&
10225 (ShuffleMask[4] % 4 == 0 && ShuffleMask[12] % 4 == 0 &&
10226 ShuffleMask[4] > 15 && ShuffleMask[12] > 15))
10228 else if ((ShuffleMask[4] == 4 && ShuffleMask[12] == 12) &&
10229 (ShuffleMask[0] % 4 == 0 && ShuffleMask[8] % 4 == 0 &&
10230 ShuffleMask[0] > 15 && ShuffleMask[8] > 15))
10238 for (; SplatBitSize < 32; SplatBitSize <<= 1)
10239 SplatVal |= (SplatVal << SplatBitSize);
10242 PPCISD::XXSPLTI32DX,
DL, MVT::v2i64, DAG.
getBitcast(MVT::v2i64,
LHS),
10244 return DAG.
getNode(ISD::BITCAST,
DL, MVT::v16i8, SplatNode);
10253 assert(
Op.getValueType() == MVT::v1i128 &&
10254 "Only set v1i128 as custom, other type shouldn't reach here!");
10259 if (SHLAmt % 8 == 0) {
10260 std::array<int, 16>
Mask;
10261 std::iota(
Mask.begin(),
Mask.end(), 0);
10262 std::rotate(
Mask.begin(),
Mask.begin() + SHLAmt / 8,
Mask.end());
10266 return DAG.
getNode(ISD::BITCAST, dl, MVT::v1i128, Shuffle);
10274 return DAG.
getNode(ISD::BITCAST, dl, MVT::v1i128, OROp);
10291 if (
SDValue NewShuffle = combineVectorShuffle(SVOp, DAG)) {
10296 V1 =
Op.getOperand(0);
10297 V2 =
Op.getOperand(1);
10299 EVT VT =
Op.getValueType();
10300 bool isLittleEndian = Subtarget.isLittleEndian();
10302 unsigned ShiftElts, InsertAtByte;
10308 bool IsPermutedLoad =
false;
10310 if (InputLoad && Subtarget.hasVSX() && V2.
isUndef() &&
10320 if (IsPermutedLoad) {
10321 assert((isLittleEndian || IsFourByte) &&
10322 "Unexpected size for permuted load on big endian target");
10323 SplatIdx += IsFourByte ? 2 : 1;
10324 assert((SplatIdx < (IsFourByte ? 4 : 2)) &&
10325 "Splat of a value outside of the loaded memory");
10330 if ((IsFourByte && Subtarget.hasP9Vector()) || !IsFourByte) {
10333 Offset = isLittleEndian ? (3 - SplatIdx) * 4 : SplatIdx * 4;
10335 Offset = isLittleEndian ? (1 - SplatIdx) * 8 : SplatIdx * 8;
10339 if (
LD->getValueType(0).getSizeInBits() == (IsFourByte ? 32 : 64))
10352 DAG.
getVTList(IsFourByte ? MVT::v4i32 : MVT::v2i64, MVT::Other);
10355 Ops,
LD->getMemoryVT(),
LD->getMemOperand());
10364 if (VT == MVT::v2i64 || VT == MVT::v2f64)
10367 if (Subtarget.hasP9Vector() &&
10377 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv2, Conv2,
10379 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Shl,
10381 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, Ins);
10383 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Conv2,
10385 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, Ins);
10388 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
10390 if ((SplatInsertNode = lowerToXXSPLTI32DX(SVOp, DAG)))
10391 return SplatInsertNode;
10394 if (Subtarget.hasP9Altivec()) {
10396 if ((NewISDNode = lowerToVINSERTH(SVOp, DAG)))
10399 if ((NewISDNode = lowerToVINSERTB(SVOp, DAG)))
10403 if (Subtarget.hasVSX() &&
10409 DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, V2.
isUndef() ? V1 : V2);
10411 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv1, Conv2,
10413 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, Shl);
10416 if (Subtarget.hasVSX() &&
10422 DAG.
getNode(ISD::BITCAST, dl, MVT::v2i64, V2.isUndef() ? V1 : V2);
10424 SDValue PermDI = DAG.
getNode(PPCISD::XXPERMDI, dl, MVT::v2i64, Conv1, Conv2,
10426 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, PermDI);
10429 if (Subtarget.hasP9Vector()) {
10433 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, ReveHWord);
10437 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, ReveWord);
10441 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, ReveDWord);
10445 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, ReveQWord);
10449 if (Subtarget.hasVSX()) {
10456 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8,
Splat);
10462 SDValue Swap = DAG.
getNode(PPCISD::SWAP_NO_CHAIN, dl, MVT::v2f64, Conv);
10463 return DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, Swap);
10470 if (V2.isUndef()) {
10483 (Subtarget.hasP8Altivec() && (
10494 unsigned int ShuffleKind = isLittleEndian ? 2 : 0;
10504 (Subtarget.hasP8Altivec() && (
10512 ArrayRef<int> PermMask = SVOp->
getMask();
10515 unsigned PFIndexes[4];
10516 bool isFourElementShuffle =
true;
10517 for (
unsigned i = 0; i != 4 && isFourElementShuffle;
10519 unsigned EltNo = 8;
10520 for (
unsigned j = 0;
j != 4; ++
j) {
10521 if (PermMask[i * 4 + j] < 0)
10524 unsigned ByteSource = PermMask[i * 4 +
j];
10525 if ((ByteSource & 3) != j) {
10526 isFourElementShuffle =
false;
10531 EltNo = ByteSource / 4;
10532 }
else if (EltNo != ByteSource / 4) {
10533 isFourElementShuffle =
false;
10537 PFIndexes[i] = EltNo;
10545 if (isFourElementShuffle) {
10547 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
10548 PFIndexes[2] * 9 + PFIndexes[3];
10551 unsigned Cost = (PFEntry >> 30);
10571 if (V2.isUndef()) V2 = V1;
10573 return LowerVPERM(
Op, DAG, PermMask, VT, V1, V2);
10579 unsigned Opcode = PPCISD::VPERM;
10582 bool NeedSwap =
false;
10583 bool isLittleEndian = Subtarget.isLittleEndian();
10584 bool isPPC64 = Subtarget.isPPC64();
10586 if (Subtarget.hasVSX() && Subtarget.hasP9Vector() &&
10588 LLVM_DEBUG(
dbgs() <<
"At least one of two input vectors are dead - using "
10589 "XXPERM instead\n");
10590 Opcode = PPCISD::XXPERM;
10598 NeedSwap = !NeedSwap;
10633 unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i];
10635 if (V1HasXXSWAPD) {
10638 else if (SrcElt < 16)
10641 if (V2HasXXSWAPD) {
10644 else if (SrcElt > 15)
10653 for (
unsigned j = 0;
j != BytesPerElement; ++
j)
10654 if (isLittleEndian)
10656 DAG.
getConstant(31 - (SrcElt * BytesPerElement + j), dl, MVT::i32));
10659 DAG.
getConstant(SrcElt * BytesPerElement + j, dl, MVT::i32));
10662 if (V1HasXXSWAPD) {
10666 if (V2HasXXSWAPD) {
10671 if (isPPC64 && (V1HasXXSWAPD || V2HasXXSWAPD)) {
10672 if (ValType != MVT::v2f64)
10678 ShufflesHandledWithVPERM++;
10682 if (Opcode == PPCISD::XXPERM) {
10683 dbgs() <<
"Emitting a XXPERM for the following shuffle:\n";
10685 dbgs() <<
"Emitting a VPERM for the following shuffle:\n";
10688 dbgs() <<
"With the following permute control vector:\n";
10692 if (Opcode == PPCISD::XXPERM)
10693 VPermMask = DAG.
getBitcast(MVT::v4i32, VPermMask);
10697 if (isLittleEndian)
10703 VPERMNode = DAG.
getBitcast(ValType, VPERMNode);
10715 switch (IntrinsicID) {
10719 case Intrinsic::ppc_altivec_vcmpbfp_p:
10723 case Intrinsic::ppc_altivec_vcmpeqfp_p:
10727 case Intrinsic::ppc_altivec_vcmpequb_p:
10731 case Intrinsic::ppc_altivec_vcmpequh_p:
10735 case Intrinsic::ppc_altivec_vcmpequw_p:
10739 case Intrinsic::ppc_altivec_vcmpequd_p:
10740 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10746 case Intrinsic::ppc_altivec_vcmpneb_p:
10747 case Intrinsic::ppc_altivec_vcmpneh_p:
10748 case Intrinsic::ppc_altivec_vcmpnew_p:
10749 case Intrinsic::ppc_altivec_vcmpnezb_p:
10750 case Intrinsic::ppc_altivec_vcmpnezh_p:
10751 case Intrinsic::ppc_altivec_vcmpnezw_p:
10752 if (Subtarget.hasP9Altivec()) {
10753 switch (IntrinsicID) {
10756 case Intrinsic::ppc_altivec_vcmpneb_p:
10759 case Intrinsic::ppc_altivec_vcmpneh_p:
10762 case Intrinsic::ppc_altivec_vcmpnew_p:
10765 case Intrinsic::ppc_altivec_vcmpnezb_p:
10768 case Intrinsic::ppc_altivec_vcmpnezh_p:
10771 case Intrinsic::ppc_altivec_vcmpnezw_p:
10779 case Intrinsic::ppc_altivec_vcmpgefp_p:
10783 case Intrinsic::ppc_altivec_vcmpgtfp_p:
10787 case Intrinsic::ppc_altivec_vcmpgtsb_p:
10791 case Intrinsic::ppc_altivec_vcmpgtsh_p:
10795 case Intrinsic::ppc_altivec_vcmpgtsw_p:
10799 case Intrinsic::ppc_altivec_vcmpgtsd_p:
10800 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10806 case Intrinsic::ppc_altivec_vcmpgtub_p:
10810 case Intrinsic::ppc_altivec_vcmpgtuh_p:
10814 case Intrinsic::ppc_altivec_vcmpgtuw_p:
10818 case Intrinsic::ppc_altivec_vcmpgtud_p:
10819 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10826 case Intrinsic::ppc_altivec_vcmpequq:
10827 case Intrinsic::ppc_altivec_vcmpgtsq:
10828 case Intrinsic::ppc_altivec_vcmpgtuq:
10829 if (!Subtarget.isISA3_1())
10831 switch (IntrinsicID) {
10834 case Intrinsic::ppc_altivec_vcmpequq:
10837 case Intrinsic::ppc_altivec_vcmpgtsq:
10840 case Intrinsic::ppc_altivec_vcmpgtuq:
10847 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10848 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10849 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
10850 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
10851 case Intrinsic::ppc_vsx_xvcmpgesp_p:
10852 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
10853 if (Subtarget.hasVSX()) {
10854 switch (IntrinsicID) {
10855 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10858 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10861 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
10864 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
10867 case Intrinsic::ppc_vsx_xvcmpgesp_p:
10870 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
10880 case Intrinsic::ppc_altivec_vcmpbfp:
10883 case Intrinsic::ppc_altivec_vcmpeqfp:
10886 case Intrinsic::ppc_altivec_vcmpequb:
10889 case Intrinsic::ppc_altivec_vcmpequh:
10892 case Intrinsic::ppc_altivec_vcmpequw:
10895 case Intrinsic::ppc_altivec_vcmpequd:
10896 if (Subtarget.hasP8Altivec())
10901 case Intrinsic::ppc_altivec_vcmpneb:
10902 case Intrinsic::ppc_altivec_vcmpneh:
10903 case Intrinsic::ppc_altivec_vcmpnew:
10904 case Intrinsic::ppc_altivec_vcmpnezb:
10905 case Intrinsic::ppc_altivec_vcmpnezh:
10906 case Intrinsic::ppc_altivec_vcmpnezw:
10907 if (Subtarget.hasP9Altivec())
10908 switch (IntrinsicID) {
10911 case Intrinsic::ppc_altivec_vcmpneb:
10914 case Intrinsic::ppc_altivec_vcmpneh:
10917 case Intrinsic::ppc_altivec_vcmpnew:
10920 case Intrinsic::ppc_altivec_vcmpnezb:
10923 case Intrinsic::ppc_altivec_vcmpnezh:
10926 case Intrinsic::ppc_altivec_vcmpnezw:
10933 case Intrinsic::ppc_altivec_vcmpgefp:
10936 case Intrinsic::ppc_altivec_vcmpgtfp:
10939 case Intrinsic::ppc_altivec_vcmpgtsb:
10942 case Intrinsic::ppc_altivec_vcmpgtsh:
10945 case Intrinsic::ppc_altivec_vcmpgtsw:
10948 case Intrinsic::ppc_altivec_vcmpgtsd:
10949 if (Subtarget.hasP8Altivec())
10954 case Intrinsic::ppc_altivec_vcmpgtub:
10957 case Intrinsic::ppc_altivec_vcmpgtuh:
10960 case Intrinsic::ppc_altivec_vcmpgtuw:
10963 case Intrinsic::ppc_altivec_vcmpgtud:
10964 if (Subtarget.hasP8Altivec())
10969 case Intrinsic::ppc_altivec_vcmpequq_p:
10970 case Intrinsic::ppc_altivec_vcmpgtsq_p:
10971 case Intrinsic::ppc_altivec_vcmpgtuq_p:
10972 if (!Subtarget.isISA3_1())
10974 switch (IntrinsicID) {
10977 case Intrinsic::ppc_altivec_vcmpequq_p:
10980 case Intrinsic::ppc_altivec_vcmpgtsq_p:
10983 case Intrinsic::ppc_altivec_vcmpgtuq_p:
10997 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11001 switch (IntrinsicID) {
11002 case Intrinsic::thread_pointer:
11004 if (Subtarget.isPPC64())
11008 case Intrinsic::ppc_rldimi: {
11009 assert(Subtarget.isPPC64() &&
"rldimi is only available in 64-bit!");
11011 APInt
Mask =
Op.getConstantOperandAPInt(4);
11013 return Op.getOperand(2);
11014 if (
Mask.isAllOnes())
11016 uint64_t SH =
Op.getConstantOperandVal(3);
11017 unsigned MB = 0, ME = 0;
11021 if (ME < 63 - SH) {
11024 }
else if (ME > 63 - SH) {
11030 {Op.getOperand(2), Src,
11031 DAG.getTargetConstant(63 - ME, dl, MVT::i32),
11032 DAG.getTargetConstant(MB, dl, MVT::i32)}),
11036 case Intrinsic::ppc_rlwimi: {
11037 APInt
Mask =
Op.getConstantOperandAPInt(4);
11039 return Op.getOperand(2);
11040 if (
Mask.isAllOnes())
11043 unsigned MB = 0, ME = 0;
11047 PPC::RLWIMI, dl, MVT::i32,
11048 {Op.getOperand(2), Op.getOperand(1), Op.getOperand(3),
11049 DAG.getTargetConstant(MB, dl, MVT::i32),
11050 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11054 case Intrinsic::ppc_rlwnm: {
11055 if (
Op.getConstantOperandVal(3) == 0)
11057 unsigned MB = 0, ME = 0;
11062 {Op.getOperand(1), Op.getOperand(2),
11063 DAG.getTargetConstant(MB, dl, MVT::i32),
11064 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11068 case Intrinsic::ppc_mma_disassemble_acc: {
11069 if (Subtarget.isISAFuture()) {
11070 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11081 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11082 Subtarget.isLittleEndian() ? Value2 :
Value,
11083 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11087 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11088 Subtarget.isLittleEndian() ? Value2 :
Value,
11089 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11093 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11094 Subtarget.isLittleEndian() ?
Value : Value2,
11095 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11099 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11100 Subtarget.isLittleEndian() ?
Value : Value2,
11101 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11108 case Intrinsic::ppc_vsx_disassemble_pair: {
11111 if (IntrinsicID == Intrinsic::ppc_mma_disassemble_acc) {
11113 WideVec = DAG.
getNode(PPCISD::XXMFACC, dl, MVT::v512i1, WideVec);
11116 for (
int VecNo = 0; VecNo < NumVecs; VecNo++) {
11118 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8, WideVec,
11119 DAG.
getConstant(Subtarget.isLittleEndian() ? NumVecs - 1 - VecNo
11127 case Intrinsic::ppc_mma_build_dmr: {
11130 for (
int i = 1; i < 9; i += 2) {
11133 if (
Hi->getOpcode() == ISD::LOAD)
11135 if (
Lo->getOpcode() == ISD::LOAD)
11138 DAG.
getNode(PPCISD::PAIR_BUILD, dl, MVT::v256i1, {Hi, Lo}));
11145 case Intrinsic::ppc_mma_dmxxextfdmr512: {
11146 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr512 requires ISA Future");
11148 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11149 "Specify P of 0 or 1 for lower or upper 512 bytes");
11150 unsigned HiLo = Idx->getSExtValue();
11154 Opcode = PPC::DMXXEXTFDMR512;
11155 Subx = PPC::sub_wacc_lo;
11157 Opcode = PPC::DMXXEXTFDMR512_HI;
11158 Subx = PPC::sub_wacc_hi;
11161 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
11165 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11169 case Intrinsic::ppc_mma_dmxxextfdmr256: {
11170 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr256 requires ISA Future");
11172 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11173 "Specify a dmr row pair 0-3");
11174 unsigned IdxVal = Idx->getSExtValue();
11178 Subx = PPC::sub_dmrrowp0;
11181 Subx = PPC::sub_dmrrowp1;
11184 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11187 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11191 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v256i1,
11197 DAG.
getMachineNode(PPC::DMXXEXTFDMR256, dl, MVT::v256i1, {Subreg, P}),
11201 case Intrinsic::ppc_mma_dmxxinstdmr512: {
11202 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr512 requires ISA Future");
11204 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11205 "Specify P of 0 or 1 for lower or upper 512 bytes");
11206 unsigned HiLo = Idx->getSExtValue();
11210 Opcode = PPC::DMXXINSTDMR512;
11211 Subx = PPC::sub_wacc_lo;
11213 Opcode = PPC::DMXXINSTDMR512_HI;
11214 Subx = PPC::sub_wacc_hi;
11224 case Intrinsic::ppc_mma_dmxxinstdmr256: {
11225 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr256 requires ISA Future");
11227 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11228 "Specify a dmr row pair 0-3");
11229 unsigned IdxVal = Idx->getSExtValue();
11233 Subx = PPC::sub_dmrrowp0;
11236 Subx = PPC::sub_dmrrowp1;
11239 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11242 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11251 Op.getOperand(1), DMRRowp,
SubReg),
11255 case Intrinsic::ppc_mma_xxmfacc:
11256 case Intrinsic::ppc_mma_xxmtacc: {
11258 if (!Subtarget.isISAFuture())
11269 case Intrinsic::ppc_unpack_longdouble: {
11271 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11272 "Argument of long double unpack must be 0 or 1!");
11275 Idx->getValueType(0)));
11278 case Intrinsic::ppc_compare_exp_lt:
11279 case Intrinsic::ppc_compare_exp_gt:
11280 case Intrinsic::ppc_compare_exp_eq:
11281 case Intrinsic::ppc_compare_exp_uo: {
11283 switch (IntrinsicID) {
11284 case Intrinsic::ppc_compare_exp_lt:
11287 case Intrinsic::ppc_compare_exp_gt:
11290 case Intrinsic::ppc_compare_exp_eq:
11293 case Intrinsic::ppc_compare_exp_uo:
11299 PPC::SELECT_CC_I4, dl, MVT::i32,
11300 {SDValue(DAG.getMachineNode(PPC::XSCMPEXPDP, dl, MVT::i32,
11301 Op.getOperand(1), Op.getOperand(2)),
11303 DAG.getConstant(1, dl, MVT::i32), DAG.getConstant(0, dl, MVT::i32),
11304 DAG.getTargetConstant(Pred, dl, MVT::i32)}),
11307 case Intrinsic::ppc_test_data_class: {
11308 EVT OpVT =
Op.getOperand(1).getValueType();
11309 unsigned CmprOpc = OpVT == MVT::f128 ? PPC::XSTSTDCQP
11310 : (OpVT == MVT::f64 ? PPC::XSTSTDCDP
11314 PPC::SELECT_CC_I4, dl, MVT::i32,
11315 {SDValue(DAG.getMachineNode(CmprOpc, dl, MVT::i32, Op.getOperand(2),
11318 DAG.getConstant(1, dl, MVT::i32), DAG.getConstant(0, dl, MVT::i32),
11319 DAG.getTargetConstant(PPC::PRED_EQ, dl, MVT::i32)}),
11322 case Intrinsic::ppc_fnmsub: {
11323 EVT VT =
Op.getOperand(1).getValueType();
11324 if (!Subtarget.hasVSX() || (!Subtarget.hasFloat128() && VT == MVT::f128))
11328 DAG.
getNode(ISD::FNEG, dl, VT,
Op.getOperand(3))));
11329 return DAG.
getNode(PPCISD::FNMSUB, dl, VT,
Op.getOperand(1),
11330 Op.getOperand(2),
Op.getOperand(3));
11332 case Intrinsic::ppc_convert_f128_to_ppcf128:
11333 case Intrinsic::ppc_convert_ppcf128_to_f128: {
11334 RTLIB::Libcall LC = IntrinsicID == Intrinsic::ppc_convert_ppcf128_to_f128
11335 ? RTLIB::CONVERT_PPCF128_F128
11336 : RTLIB::CONVERT_F128_PPCF128;
11338 std::pair<SDValue, SDValue>
Result =
11339 makeLibCall(DAG, LC,
Op.getValueType(),
Op.getOperand(1), CallOptions,
11343 case Intrinsic::ppc_maxfe:
11344 case Intrinsic::ppc_maxfl:
11345 case Intrinsic::ppc_maxfs:
11346 case Intrinsic::ppc_minfe:
11347 case Intrinsic::ppc_minfl:
11348 case Intrinsic::ppc_minfs: {
11349 EVT VT =
Op.getValueType();
11352 [VT](
const SDUse &Use) { return Use.getValueType() == VT; }) &&
11353 "ppc_[max|min]f[e|l|s] must have uniform type arguments");
11356 if (IntrinsicID == Intrinsic::ppc_minfe ||
11357 IntrinsicID == Intrinsic::ppc_minfl ||
11358 IntrinsicID == Intrinsic::ppc_minfs)
11379 SDValue Tmp = DAG.
getNode(PPCISD::VCMP, dl,
Op.getOperand(2).getValueType(),
11380 Op.getOperand(1),
Op.getOperand(2),
11382 return DAG.
getNode(ISD::BITCAST, dl,
Op.getValueType(), Tmp);
11391 EVT VTs[] = {
Op.getOperand(2).getValueType(), MVT::Glue };
11399 switch (
Op.getConstantOperandVal(1)) {
11404 Bitx = PPC::sub_eq;
11405 SetOp = PPCISD::SETBC;
11410 Bitx = PPC::sub_eq;
11411 SetOp = PPCISD::SETBCR;
11416 Bitx = PPC::sub_lt;
11417 SetOp = PPCISD::SETBC;
11422 Bitx = PPC::sub_lt;
11423 SetOp = PPCISD::SETBCR;
11428 if (Subtarget.isISA3_1()) {
11433 CR6Reg, SubRegIdx, GlueOp),
11435 return DAG.
getNode(SetOp, dl, MVT::i32, CRBit);
11463 switch (
Op.getConstantOperandVal(ArgStart)) {
11464 case Intrinsic::ppc_cfence: {
11465 assert(ArgStart == 1 &&
"llvm.ppc.cfence must carry a chain argument.");
11466 SDValue Val =
Op.getOperand(ArgStart + 1);
11468 if (Ty == MVT::i128) {
11473 unsigned Opcode = Subtarget.isPPC64() ? PPC::CFENCE8 : PPC::CFENCE;
11476 Opcode,
DL, MVT::Other,
11481 case Intrinsic::ppc_mma_disassemble_dmr: {
11483 Op.getOperand(ArgStart + 1), MachinePointerInfo());
11494 if (!Subtarget.isPPC64())
11502 int VectorIndex = 0;
11503 if (Subtarget.isLittleEndian())
11514 assert(
Op.getOpcode() == ISD::ATOMIC_CMP_SWAP &&
11515 "Expecting an atomic compare-and-swap here.");
11518 EVT MemVT = AtomicNode->getMemoryVT();
11536 for (
int i = 0, e = AtomicNode->getNumOperands(); i < e; i++)
11537 Ops.push_back(AtomicNode->getOperand(i));
11539 MachineMemOperand *MMO = AtomicNode->getMemOperand();
11540 SDVTList Tys = DAG.
getVTList(MVT::i32, MVT::Other);
11542 (MemVT == MVT::i8) ? PPCISD::ATOMIC_CMP_SWAP_8 : PPCISD::ATOMIC_CMP_SWAP_16;
11549 EVT MemVT =
N->getMemoryVT();
11551 "Expect quadword atomic operations");
11553 unsigned Opc =
N->getOpcode();
11555 case ISD::ATOMIC_LOAD: {
11558 SDVTList Tys = DAG.
getVTList(MVT::i64, MVT::i64, MVT::Other);
11561 DAG.
getConstant(Intrinsic::ppc_atomic_load_i128, dl, MVT::i32)};
11562 for (
int I = 1,
E =
N->getNumOperands();
I <
E; ++
I)
11563 Ops.push_back(
N->getOperand(
I));
11565 Ops, MemVT,
N->getMemOperand());
11572 DAG.
getNode(
ISD::OR, dl, {MVT::i128, MVT::Other}, {ValLo, ValHi});
11576 case ISD::ATOMIC_STORE: {
11579 SDVTList Tys = DAG.
getVTList(MVT::Other);
11582 DAG.
getConstant(Intrinsic::ppc_atomic_store_i128, dl, MVT::i32)};
11588 Ops.push_back(ValLo);
11589 Ops.push_back(ValHi);
11590 Ops.push_back(
N->getOperand(2));
11592 N->getMemOperand());
11604 enum DataClassMask {
11606 DC_NEG_INF = 1 << 4,
11607 DC_POS_INF = 1 << 5,
11608 DC_NEG_ZERO = 1 << 2,
11609 DC_POS_ZERO = 1 << 3,
11610 DC_NEG_SUBNORM = 1,
11611 DC_POS_SUBNORM = 1 << 1,
11614 EVT VT =
Op.getValueType();
11616 unsigned TestOp = VT == MVT::f128 ? PPC::XSTSTDCQP
11617 : VT == MVT::f64 ? PPC::XSTSTDCDP
11628 return DAG.
getNOT(Dl, Rev, MVT::i1);
11635 TestOp, Dl, MVT::i32,
11637 DC_NEG_ZERO | DC_POS_ZERO |
11638 DC_NEG_SUBNORM | DC_POS_SUBNORM,
11644 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11650 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11655 Sign = DAG.
getNOT(Dl, Sign, MVT::i1);
11668 bool IsQuiet = Mask &
fcQNan;
11674 if (VT == MVT::f128) {
11678 QuietMask = 0x8000;
11679 }
else if (VT == MVT::f64) {
11680 if (Subtarget.isPPC64()) {
11691 QuietMask = 0x80000;
11692 }
else if (VT == MVT::f32) {
11694 QuietMask = 0x400000;
11710 unsigned NativeMask = 0;
11712 NativeMask |= DC_NAN;
11714 NativeMask |= DC_NEG_INF;
11716 NativeMask |= DC_POS_INF;
11718 NativeMask |= DC_NEG_ZERO;
11720 NativeMask |= DC_POS_ZERO;
11722 NativeMask |= DC_NEG_SUBNORM;
11724 NativeMask |= DC_POS_SUBNORM;
11727 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1,
11729 TestOp, Dl, MVT::i32,
11738 assert(Subtarget.hasP9Vector() &&
"Test data class requires Power9");
11740 uint64_t RHSC =
Op.getConstantOperandVal(1);
11743 if (
LHS.getValueType() == MVT::ppcf128) {
11767 bool Future = Subtarget.isISAFuture();
11770 "Mask predication not supported");
11773 unsigned IID = Future ? Intrinsic::ppc_vsx_lxvrl : Intrinsic::ppc_vsx_lxvl;
11774 unsigned EltBits =
Op->getValueType(0).getScalarType().getSizeInBits();
11778 SDVTList Tys = DAG.
getVTList(
Op->getValueType(0), MVT::Other);
11781 VPLD->getMemoryVT(), VPLD->getMemOperand());
11788 "Mask predication not supported");
11793 Op->getOperand(1).getValueType().getScalarType().getSizeInBits();
11794 bool Future = Subtarget.isISAFuture();
11795 unsigned IID = Future ? Intrinsic::ppc_vsx_stxvrl : Intrinsic::ppc_vsx_stxvl;
11798 VPST->getChain(), DAG.
getConstant(IID, dl, MVT::i32),
11799 DAG.
getNode(ISD::BITCAST, dl, MVT::v4i32, VPST->getOperand(1)),
11801 SDVTList Tys = DAG.
getVTList(MVT::Other);
11804 VPST->getMemoryVT(), VPST->getMemOperand());
11815 unsigned EltSize =
Op.getValueType().getScalarSizeInBits();
11817 int64_t
IntVal =
Op.getConstantOperandVal(0);
11818 if (IntVal >= -16 && IntVal <= 15)
11824 if (Subtarget.hasLFIWAX() && Subtarget.hasVSX() &&
11825 Op.getValueType() == MVT::v4i32 && Op0.
getOpcode() == ISD::LOAD &&
11829 MachineMemOperand *MMO =
11831 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
11834 PPCISD::LD_SPLAT, dl, DAG.
getVTList(MVT::v4i32, MVT::Other),
Ops,
11838 return Bits.getValue(0);
11854 !Subtarget.isLittleEndian() && ValVT.
isInteger() &&
11859 64 -
Op.getValueType().getScalarSizeInBits(), dl, ShiftAmountTy);
11866 return DAG.
getLoad(
Op.getValueType(), dl, Store, FIdx,
11867 MachinePointerInfo());
11874 return DAG.
getLoad(
Op.getValueType(), dl, Store, FIdx, MachinePointerInfo());
11880 "Should only be called for ISD::INSERT_VECTOR_ELT");
11884 EVT VT =
Op.getValueType();
11889 if (VT == MVT::v2f64 &&
C)
11892 if (Subtarget.hasP9Vector()) {
11901 if ((VT == MVT::v4f32) && (V2.
getValueType() == MVT::f32) &&
11907 BitcastLoad,
Op.getOperand(2));
11908 return DAG.
getBitcast(MVT::v4f32, InsVecElt);
11912 if (Subtarget.isISA3_1()) {
11913 if ((VT == MVT::v2i64 || VT == MVT::v2f64) && !Subtarget.isPPC64())
11917 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
11918 VT == MVT::v2i64 || VT == MVT::v4f32 || VT == MVT::v2f64)
11928 if (VT == MVT::v8i16 || VT == MVT::v16i8) {
11931 unsigned InsertAtElement =
C->getZExtValue();
11932 unsigned InsertAtByte = InsertAtElement * BytesInEachElement;
11933 if (Subtarget.isLittleEndian()) {
11934 InsertAtByte = (16 - BytesInEachElement) - InsertAtByte;
11936 return DAG.
getNode(PPCISD::VECINSERT, dl, VT, V1, Mtvsrz,
11948 EVT VT =
Op.getValueType();
11949 bool IsV1024i1 = VT == MVT::v1024i1;
11950 bool IsV2048i1 = VT == MVT::v2048i1;
11954 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
11956 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
11957 "Dense Math support required.");
11958 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
11967 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
11968 MachineMemOperand *NewMMO =
11976 DAG.
getVTList(MVT::v256i1, MVT::Other),
11977 LoadOps, MVT::v256i1, NewMMO);
11982 if (Subtarget.isLittleEndian()) {
11983 std::reverse(Loads.
begin(), Loads.
end());
11984 std::reverse(LoadChains.
begin(), LoadChains.
end());
11993 Loads[2], Loads[3]),
12009 Loads[4], Loads[5]),
12012 Loads[6], Loads[7]),
12014 const SDValue Dmr1Ops[] = {RC, Dmr1Lo, LoSub, Dmr1Hi, HiSub};
12016 DAG.
getMachineNode(PPC::REG_SEQUENCE, dl, MVT::v1024i1, Dmr1Ops), 0);
12022 const SDValue DmrPOps[] = {DmrPRC,
Value, Dmr0Sub, Dmr1Value, Dmr1Sub};
12025 DAG.
getMachineNode(PPC::REG_SEQUENCE, dl, MVT::v2048i1, DmrPOps), 0);
12038 Pairs[2], Pairs[3]),
12044 {RC, Lo, LoSub, Hi, HiSub}),
12054 EVT VT =
Op.getValueType();
12056 if (VT == MVT::v1024i1 || VT == MVT::v2048i1)
12057 return LowerDMFVectorLoad(
Op, DAG);
12059 if (VT != MVT::v256i1 && VT != MVT::v512i1)
12065 assert((VT != MVT::v512i1 || Subtarget.hasMMA()) &&
12066 "Type unsupported without MMA");
12067 assert((VT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12068 "Type unsupported without paired vector support");
12073 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12075 DAG.
getLoad(MVT::v16i8, dl, LoadChain, BasePtr,
12084 if (Subtarget.isLittleEndian()) {
12085 std::reverse(Loads.
begin(), Loads.
end());
12086 std::reverse(LoadChains.
begin(), LoadChains.
end());
12090 DAG.
getNode(VT == MVT::v512i1 ? PPCISD::ACC_BUILD : PPCISD::PAIR_BUILD,
12106 bool IsV1024i1 = VT == MVT::v1024i1;
12107 bool IsV2048i1 = VT == MVT::v2048i1;
12111 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12113 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12114 "Dense Math support required.");
12115 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12117 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12120 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12125 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12129 MachineSDNode *ExtNode =
12133 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes,
Hi);
12139 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12145 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12151 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12156 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12161 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12166 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12170 MachineSDNode *ExtNode =
12171 DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr0Lo);
12175 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr0Hi);
12178 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr1Lo);
12182 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr1Hi);
12187 if (Subtarget.isLittleEndian())
12188 std::reverse(Values.
begin(), Values.
end());
12190 SDVTList Tys = DAG.
getVTList(MVT::Other);
12192 StoreChain, DAG.
getConstant(Intrinsic::ppc_vsx_stxvp, dl, MVT::i32),
12196 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12197 MachineMemOperand *NewMMO =
12204 Ops[2] = Values[Idx];
12206 MVT::v256i1, NewMMO);
12222 EVT StoreVT =
Value.getValueType();
12224 if (StoreVT == MVT::v1024i1 || StoreVT == MVT::v2048i1)
12225 return LowerDMFVectorStore(
Op, DAG);
12227 if (StoreVT != MVT::v256i1 && StoreVT != MVT::v512i1)
12233 assert((StoreVT != MVT::v512i1 || Subtarget.hasMMA()) &&
12234 "Type unsupported without MMA");
12235 assert((StoreVT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12236 "Type unsupported without paired vector support");
12239 unsigned NumVecs = 2;
12240 if (StoreVT == MVT::v512i1) {
12241 if (Subtarget.isISAFuture()) {
12242 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12244 PPC::DMXXEXTFDMR512, dl, ReturnTypes,
Op.getOperand(1));
12247 Value2 =
SDValue(ExtNode, 1);
12252 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12253 unsigned VecNum = Subtarget.isLittleEndian() ? NumVecs - 1 - Idx : Idx;
12255 if (Subtarget.isISAFuture()) {
12256 VecNum = Subtarget.isLittleEndian() ? 1 - (Idx % 2) : (Idx % 2);
12257 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
12258 Idx > 1 ? Value2 :
Value,
12261 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
Value,
12265 DAG.
getStore(StoreChain, dl, Elt, BasePtr,
12279 if (
Op.getValueType() == MVT::v4i32) {
12291 RHSSwap = DAG.
getNode(ISD::BITCAST, dl, MVT::v8i16, RHSSwap);
12296 LHS,
RHS, DAG, dl, MVT::v4i32);
12299 LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32);
12304 }
else if (
Op.getValueType() == MVT::v16i8) {
12306 bool isLittleEndian = Subtarget.isLittleEndian();
12310 LHS,
RHS, DAG, dl, MVT::v8i16);
12311 EvenParts = DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, EvenParts);
12315 LHS,
RHS, DAG, dl, MVT::v8i16);
12316 OddParts = DAG.
getNode(ISD::BITCAST, dl, MVT::v16i8, OddParts);
12323 for (
unsigned i = 0; i != 8; ++i) {
12324 if (isLittleEndian) {
12326 Ops[i*2+1] = 2*i+16;
12329 Ops[i*2+1] = 2*i+1+16;
12332 if (isLittleEndian)
12342 bool IsStrict =
Op->isStrictFPOpcode();
12343 if (
Op.getOperand(IsStrict ? 1 : 0).getValueType() == MVT::f128 &&
12344 !Subtarget.hasP9Vector())
12353 assert(
Op.getOpcode() == ISD::FP_EXTEND &&
12354 "Should only be called for ISD::FP_EXTEND");
12358 if (
Op.getValueType() != MVT::v2f64 ||
12359 Op.getOperand(0).getValueType() != MVT::v2f32)
12371 "Node should have 2 operands with second one being a constant!");
12383 int DWord = Idx >> 1;
12386 if (Subtarget.isLittleEndian())
12389 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64,
12403 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12405 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12406 LD->getMemoryVT(),
LD->getMemOperand());
12411 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewOp,
12416 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12418 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12419 LD->getMemoryVT(),
LD->getMemOperand());
12420 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewLd,
12431 if (STI.useCRBits())
12448 PPCISD::ADDE,
DL, DAG.
getVTList(SumType, MVT::i32), Zero, Zero, Flag);
12449 if (STI.useCRBits())
12457 SDNode *
N =
Op.getNode();
12458 EVT VT =
N->getValueType(0);
12459 EVT CarryType =
N->getValueType(1);
12460 unsigned Opc =
N->getOpcode();
12462 Opc = IsAdd ? PPCISD::ADDC : PPCISD::SUBC;
12464 N->getOperand(0),
N->getOperand(1));
12476 SDNode *
N =
Op.getNode();
12477 unsigned Opc =
N->getOpcode();
12478 EVT VT =
N->getValueType(0);
12479 EVT CarryType =
N->getValueType(1);
12480 SDValue CarryOp =
N->getOperand(2);
12482 Opc = IsAdd ? PPCISD::ADDE : PPCISD::SUBE;
12488 Op.getOperand(0),
Op.getOperand(1), CarryOp);
12502 EVT VT =
Op.getNode()->getValueType(0);
12528 EVT VT =
Op.getNode()->getValueType(0);
12557 EVT OpVT =
A.getValueType();
12558 EVT ResVT =
Op.getValueType();
12564 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12582 switch (
Op.getOpcode()) {
12585 case ISD::FPOW:
return lowerPow(
Op, DAG);
12586 case ISD::FSIN:
return lowerSin(
Op, DAG);
12587 case ISD::FCOS:
return lowerCos(
Op, DAG);
12588 case ISD::FLOG:
return lowerLog(
Op, DAG);
12589 case ISD::FLOG10:
return lowerLog10(
Op, DAG);
12590 case ISD::FEXP:
return lowerExp(
Op, DAG);
12599 case ISD::INIT_TRAMPOLINE:
return LowerINIT_TRAMPOLINE(
Op, DAG);
12600 case ISD::ADJUST_TRAMPOLINE:
return LowerADJUST_TRAMPOLINE(
Op, DAG);
12602 return LowerSSUBO(
Op, DAG);
12604 return LowerSADDO(
Op, DAG);
12606 case ISD::INLINEASM:
12607 case ISD::INLINEASM_BR:
return LowerINLINEASM(
Op, DAG);
12609 case ISD::VASTART:
return LowerVASTART(
Op, DAG);
12610 case ISD::VAARG:
return LowerVAARG(
Op, DAG);
12611 case ISD::VACOPY:
return LowerVACOPY(
Op, DAG);
12613 case ISD::STACKRESTORE:
return LowerSTACKRESTORE(
Op, DAG);
12614 case ISD::DYNAMIC_STACKALLOC:
return LowerDYNAMIC_STACKALLOC(
Op, DAG);
12615 case ISD::GET_DYNAMIC_AREA_OFFSET:
12616 return LowerGET_DYNAMIC_AREA_OFFSET(
Op, DAG);
12623 case ISD::LOAD:
return LowerLOAD(
Op, DAG);
12624 case ISD::STORE:
return LowerSTORE(
Op, DAG);
12636 case ISD::SET_ROUNDING:
12637 return LowerSET_ROUNDING(
Op, DAG);
12644 case ISD::FSHL:
return LowerFunnelShift(
Op, DAG);
12645 case ISD::FSHR:
return LowerFunnelShift(
Op, DAG);
12654 case ISD::FP_EXTEND:
return LowerFP_EXTEND(
Op, DAG);
12657 return LowerFP_ROUND(
Op, DAG);
12664 case ISD::BITCAST:
return LowerBITCAST(
Op, DAG);
12671 return LowerINTRINSIC_VOID(
Op, DAG);
12673 return LowerBSWAP(
Op, DAG);
12674 case ISD::ATOMIC_CMP_SWAP:
12675 return LowerATOMIC_CMP_SWAP(
Op, DAG);
12676 case ISD::ATOMIC_STORE:
12677 return LowerATOMIC_LOAD_STORE(
Op, DAG);
12679 return LowerIS_FPCLASS(
Op, DAG);
12682 return LowerADDSUBO(
Op, DAG);
12685 return LowerADDSUBO_CARRY(
Op, DAG);
12687 return LowerUCMP(
Op, DAG);
12693 if (
Op->getFlags().hasNoFPExcept())
12697 return LowerVP_LOAD(
Op, DAG);
12698 case ISD::VP_STORE:
12699 return LowerVP_STORE(
Op, DAG);
12707 switch (
N->getOpcode()) {
12709 llvm_unreachable(
"Do not know how to custom type legalize this operation!");
12710 case ISD::ATOMIC_LOAD: {
12716 case ISD::READCYCLECOUNTER: {
12726 if (
N->getConstantOperandVal(1) != Intrinsic::loop_decrement)
12729 assert(
N->getValueType(0) == MVT::i1 &&
12730 "Unexpected result type for CTR decrement intrinsic");
12732 N->getValueType(0));
12742 switch (
N->getConstantOperandVal(0)) {
12743 case Intrinsic::ppc_pack_longdouble:
12745 N->getOperand(2),
N->getOperand(1)));
12747 case Intrinsic::ppc_maxfe:
12748 case Intrinsic::ppc_minfe:
12749 case Intrinsic::ppc_fnmsub:
12750 case Intrinsic::ppc_convert_f128_to_ppcf128:
12757 if (!Subtarget.isSVR4ABI() || Subtarget.isPPC64())
12760 EVT VT =
N->getValueType(0);
12762 if (VT == MVT::i64) {
12775 if (
N->getOperand(
N->isStrictFPOpcode() ? 1 : 0).getValueType() ==
12779 Results.push_back(LoweredValue);
12780 if (
N->isStrictFPOpcode())
12785 if (!
N->getValueType(0).isVector())
12805 case ISD::FP_EXTEND:
12818 return Builder.CreateIntrinsic(Id, {});
12824 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
12826 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
12827 "Only 8/16/32/64-bit atomic loads supported");
12833 IntID = Intrinsic::ppc_lbarx;
12834 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
12837 IntID = Intrinsic::ppc_lharx;
12838 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
12841 IntID = Intrinsic::ppc_lwarx;
12844 IntID = Intrinsic::ppc_ldarx;
12848 Builder.CreateIntrinsic(IntID, Addr,
nullptr,
"larx");
12850 return Builder.CreateTruncOrBitCast(
Call, ValueTy);
12861 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
12862 "Only 8/16/32/64-bit atomic loads supported");
12868 IntID = Intrinsic::ppc_stbcx;
12869 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
12872 IntID = Intrinsic::ppc_sthcx;
12873 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
12876 IntID = Intrinsic::ppc_stwcx;
12879 IntID = Intrinsic::ppc_stdcx;
12883 if (SZ == 8 || SZ == 16)
12884 Val = Builder.CreateZExt(Val, Builder.getInt32Ty());
12886 Value *
Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
12888 return Builder.CreateXor(
Call, Builder.getInt32(1));
12911 return Builder.CreateIntrinsic(Intrinsic::ppc_cfence, {Inst->
getType()},
12921 unsigned AtomicSize,
12922 unsigned BinOpcode,
12923 unsigned CmpOpcode,
12924 unsigned CmpPred)
const {
12928 auto LoadMnemonic = PPC::LDARX;
12929 auto StoreMnemonic = PPC::STDCX;
12930 switch (AtomicSize) {
12934 LoadMnemonic = PPC::LBARX;
12935 StoreMnemonic = PPC::STBCX;
12936 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
12939 LoadMnemonic = PPC::LHARX;
12940 StoreMnemonic = PPC::STHCX;
12941 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
12944 LoadMnemonic = PPC::LWARX;
12945 StoreMnemonic = PPC::STWCX;
12948 LoadMnemonic = PPC::LDARX;
12949 StoreMnemonic = PPC::STDCX;
12965 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
12967 F->insert(It, loopMBB);
12969 F->insert(It, loop2MBB);
12970 F->insert(It, exitMBB);
12976 Register TmpReg = (!BinOpcode) ? incr :
12977 RegInfo.createVirtualRegister( AtomicSize == 8 ? &PPC::G8RCRegClass
12978 : &PPC::GPRCRegClass);
13003 BuildMI(BB, dl,
TII->get(LoadMnemonic), dest)
13008 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13010 if (CmpOpcode == PPC::CMPW && AtomicSize < 4) {
13011 Register ExtReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13012 BuildMI(BB, dl,
TII->get(AtomicSize == 1 ? PPC::EXTSB : PPC::EXTSH),
13042 switch(
MI.getOpcode()) {
13046 return TII->isSignExtended(
MI.getOperand(1).getReg(),
13047 &
MI.getMF()->getRegInfo());
13071 case PPC::EXTSB8_32_64:
13072 case PPC::EXTSB8_rec:
13073 case PPC::EXTSB_rec:
13076 case PPC::EXTSH8_32_64:
13077 case PPC::EXTSH8_rec:
13078 case PPC::EXTSH_rec:
13080 case PPC::EXTSWSLI:
13081 case PPC::EXTSWSLI_32_64:
13082 case PPC::EXTSWSLI_32_64_rec:
13083 case PPC::EXTSWSLI_rec:
13084 case PPC::EXTSW_32:
13085 case PPC::EXTSW_32_64:
13086 case PPC::EXTSW_32_64_rec:
13087 case PPC::EXTSW_rec:
13090 case PPC::SRAWI_rec:
13091 case PPC::SRAW_rec:
13100 unsigned BinOpcode,
unsigned CmpOpcode,
unsigned CmpPred)
const {
13110 bool IsSignExtended =
13113 if (CmpOpcode == PPC::CMPW && !IsSignExtended) {
13114 Register ValueReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13115 BuildMI(*BB,
MI, dl,
TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueReg)
13116 .
addReg(
MI.getOperand(3).getReg());
13117 MI.getOperand(3).setReg(ValueReg);
13121 if (Subtarget.hasPartwordAtomics())
13129 bool is64bit = Subtarget.isPPC64();
13130 bool isLittleEndian = Subtarget.isLittleEndian();
13131 unsigned ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
13142 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13144 F->insert(It, loopMBB);
13146 F->insert(It, loop2MBB);
13147 F->insert(It, exitMBB);
13153 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13156 Register PtrReg = RegInfo.createVirtualRegister(RC);
13157 Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
13159 isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
13160 Register Incr2Reg = RegInfo.createVirtualRegister(GPRC);
13161 Register MaskReg = RegInfo.createVirtualRegister(GPRC);
13162 Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
13163 Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
13164 Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
13165 Register Tmp3Reg = RegInfo.createVirtualRegister(GPRC);
13166 Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
13167 Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
13168 Register SrwDestReg = RegInfo.createVirtualRegister(GPRC);
13171 (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(GPRC);
13198 if (ptrA != ZeroReg) {
13199 Ptr1Reg = RegInfo.createVirtualRegister(RC);
13200 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
13208 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
13209 .
addReg(Ptr1Reg, 0, is64bit ? PPC::sub_32 : 0)
13212 .
addImm(is8bit ? 28 : 27);
13213 if (!isLittleEndian)
13214 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
13216 .
addImm(is8bit ? 24 : 16);
13218 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
13223 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
13233 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
13237 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
13242 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
13246 BuildMI(BB, dl,
TII->get(BinOpcode), TmpReg)
13249 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
13256 Register SReg = RegInfo.createVirtualRegister(GPRC);
13257 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13261 unsigned ValueReg = SReg;
13262 unsigned CmpReg = Incr2Reg;
13263 if (CmpOpcode == PPC::CMPW) {
13264 ValueReg = RegInfo.createVirtualRegister(GPRC);
13265 BuildMI(BB, dl,
TII->get(PPC::SRW), ValueReg)
13268 Register ValueSReg = RegInfo.createVirtualRegister(GPRC);
13269 BuildMI(BB, dl,
TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueSReg)
13271 ValueReg = ValueSReg;
13303 .
addImm(is8bit ? 24 : 16)
13324 Register DstReg =
MI.getOperand(0).getReg();
13326 assert(
TRI->isTypeLegalForClass(*RC, MVT::i32) &&
"Invalid destination!");
13327 Register mainDstReg =
MRI.createVirtualRegister(RC);
13328 Register restoreDstReg =
MRI.createVirtualRegister(RC);
13331 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13332 "Invalid Pointer Size!");
13380 Register LabelReg =
MRI.createVirtualRegister(PtrRC);
13381 Register BufReg =
MI.getOperand(1).getReg();
13383 if (Subtarget.is64BitELFABI()) {
13396 BaseReg = Subtarget.isPPC64() ? PPC::X1 : PPC::R1;
13398 BaseReg = Subtarget.isPPC64() ? PPC::BP8 : PPC::BP;
13401 TII->get(Subtarget.isPPC64() ? PPC::STD : PPC::STW))
13424 TII->get(Subtarget.isPPC64() ? PPC::MFLR8 : PPC::MFLR), LabelReg);
13427 if (Subtarget.isPPC64()) {
13445 TII->get(PPC::PHI), DstReg)
13449 MI.eraseFromParent();
13463 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13464 "Invalid Pointer Size!");
13467 (PVT == MVT::i64) ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13470 unsigned FP = (PVT == MVT::i64) ? PPC::X31 : PPC::R31;
13471 unsigned SP = (PVT == MVT::i64) ? PPC::X1 : PPC::R1;
13485 Register BufReg =
MI.getOperand(0).getReg();
13490 if (PVT == MVT::i64) {
13502 if (PVT == MVT::i64) {
13514 if (PVT == MVT::i64) {
13526 if (PVT == MVT::i64) {
13538 if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) {
13548 TII->get(PVT == MVT::i64 ? PPC::MTCTR8 : PPC::MTCTR)).
addReg(Tmp);
13551 MI.eraseFromParent();
13567 "Unexpected stack alignment");
13571 unsigned StackProbeSize =
13574 StackProbeSize &= ~(StackAlign - 1);
13575 return StackProbeSize ? StackProbeSize : StackAlign;
13587 const bool isPPC64 = Subtarget.isPPC64();
13619 MF->
insert(MBBIter, TestMBB);
13620 MF->
insert(MBBIter, BlockMBB);
13621 MF->
insert(MBBIter, TailMBB);
13626 Register DstReg =
MI.getOperand(0).getReg();
13627 Register NegSizeReg =
MI.getOperand(1).getReg();
13629 Register FinalStackPtr =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13630 Register FramePointer =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13631 Register ActualNegSizeReg =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13637 if (!
MRI.hasOneNonDBGUse(NegSizeReg))
13639 isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_64 : PPC::PREPARE_PROBED_ALLOCA_32;
13645 ProbeOpc = isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_64
13646 : PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_32;
13648 .
addDef(ActualNegSizeReg)
13650 .
add(
MI.getOperand(2))
13651 .
add(
MI.getOperand(3));
13657 .
addReg(ActualNegSizeReg);
13660 int64_t NegProbeSize = -(int64_t)ProbeSize;
13662 Register ScratchReg =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13664 Register TempReg =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13666 .
addImm(NegProbeSize >> 16);
13670 .
addImm(NegProbeSize & 0xFFFF);
13677 Register Div =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13679 .
addReg(ActualNegSizeReg)
13681 Register Mul =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13685 Register NegMod =
MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13688 .
addReg(ActualNegSizeReg);
13697 Register CmpResult =
MRI.createVirtualRegister(&PPC::CRRCRegClass);
13698 BuildMI(TestMBB,
DL,
TII->get(isPPC64 ? PPC::CMPD : PPC::CMPW), CmpResult)
13723 MRI.createVirtualRegister(isPPC64 ? G8RC : GPRC);
13725 TII->get(isPPC64 ? PPC::DYNAREAOFFSET8 : PPC::DYNAREAOFFSET),
13726 MaxCallFrameSizeReg)
13727 .
add(
MI.getOperand(2))
13728 .
add(
MI.getOperand(3));
13729 BuildMI(TailMBB,
DL,
TII->get(isPPC64 ? PPC::ADD8 : PPC::ADD4), DstReg)
13731 .
addReg(MaxCallFrameSizeReg);
13737 MBB->addSuccessor(TestMBB);
13740 MI.eraseFromParent();
13742 ++NumDynamicAllocaProbed;
13747 switch (
MI.getOpcode()) {
13748 case PPC::SELECT_CC_I4:
13749 case PPC::SELECT_CC_I8:
13750 case PPC::SELECT_CC_F4:
13751 case PPC::SELECT_CC_F8:
13752 case PPC::SELECT_CC_F16:
13753 case PPC::SELECT_CC_VRRC:
13754 case PPC::SELECT_CC_VSFRC:
13755 case PPC::SELECT_CC_VSSRC:
13756 case PPC::SELECT_CC_VSRC:
13757 case PPC::SELECT_CC_SPE4:
13758 case PPC::SELECT_CC_SPE:
13766 switch (
MI.getOpcode()) {
13767 case PPC::SELECT_I4:
13768 case PPC::SELECT_I8:
13769 case PPC::SELECT_F4:
13770 case PPC::SELECT_F8:
13771 case PPC::SELECT_F16:
13772 case PPC::SELECT_SPE:
13773 case PPC::SELECT_SPE4:
13774 case PPC::SELECT_VRRC:
13775 case PPC::SELECT_VSFRC:
13776 case PPC::SELECT_VSSRC:
13777 case PPC::SELECT_VSRC:
13787 if (
MI.getOpcode() == TargetOpcode::STACKMAP ||
13788 MI.getOpcode() == TargetOpcode::PATCHPOINT) {
13789 if (Subtarget.is64BitELFABI() &&
13790 MI.getOpcode() == TargetOpcode::PATCHPOINT &&
13791 !Subtarget.isUsingPCRelativeCalls()) {
13803 if (
MI.getOpcode() == PPC::EH_SjLj_SetJmp32 ||
13804 MI.getOpcode() == PPC::EH_SjLj_SetJmp64) {
13806 }
else if (
MI.getOpcode() == PPC::EH_SjLj_LongJmp32 ||
13807 MI.getOpcode() == PPC::EH_SjLj_LongJmp64) {
13821 if (Subtarget.hasISEL() &&
13822 (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
13823 MI.getOpcode() == PPC::SELECT_CC_I8 ||
13824 MI.getOpcode() == PPC::SELECT_I4 ||
MI.getOpcode() == PPC::SELECT_I8)) {
13826 if (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
13827 MI.getOpcode() == PPC::SELECT_CC_I8)
13828 Cond.push_back(
MI.getOperand(4));
13831 Cond.push_back(
MI.getOperand(1));
13834 TII->insertSelect(*BB,
MI, dl,
MI.getOperand(0).getReg(),
Cond,
13835 MI.getOperand(2).getReg(),
MI.getOperand(3).getReg());
13851 F->insert(It, copy0MBB);
13852 F->insert(It, sinkMBB);
13861 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
13876 .
addReg(
MI.getOperand(1).getReg())
13879 unsigned SelectPred =
MI.getOperand(4).getImm();
13882 .
addReg(
MI.getOperand(1).getReg())
13899 .
addReg(
MI.getOperand(3).getReg())
13901 .
addReg(
MI.getOperand(2).getReg())
13903 }
else if (
MI.getOpcode() == PPC::ReadTB) {
13919 F->insert(It, readMBB);
13920 F->insert(It, sinkMBB);
13931 Register ReadAgainReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13939 Register CmpReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13941 BuildMI(BB, dl,
TII->get(PPC::CMPW), CmpReg)
13951 }
else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I8)
13953 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I16)
13955 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I32)
13957 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I64)
13960 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I8)
13962 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I16)
13964 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I32)
13966 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I64)
13969 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I8)
13971 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I16)
13973 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I32)
13975 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I64)
13978 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I8)
13980 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I16)
13982 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I32)
13984 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I64)
13987 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I8)
13989 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I16)
13991 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I32)
13993 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I64)
13996 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I8)
13998 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I16)
14000 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I32)
14002 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I64)
14005 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I8)
14007 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I16)
14009 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I32)
14011 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I64)
14014 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I8)
14016 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I16)
14018 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I32)
14020 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I64)
14023 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I8)
14025 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I16)
14027 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I32)
14029 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I64)
14032 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I8)
14034 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I16)
14036 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I32)
14038 else if (
MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I64)
14041 else if (
MI.getOpcode() == PPC::ATOMIC_SWAP_I8)
14043 else if (
MI.getOpcode() == PPC::ATOMIC_SWAP_I16)
14045 else if (
MI.getOpcode() == PPC::ATOMIC_SWAP_I32)
14047 else if (
MI.getOpcode() == PPC::ATOMIC_SWAP_I64)
14049 else if (
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
14050 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64 ||
14051 (Subtarget.hasPartwordAtomics() &&
14052 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8) ||
14053 (Subtarget.hasPartwordAtomics() &&
14054 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16)) {
14055 bool is64bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
14057 auto LoadMnemonic = PPC::LDARX;
14058 auto StoreMnemonic = PPC::STDCX;
14059 switch (
MI.getOpcode()) {
14062 case PPC::ATOMIC_CMP_SWAP_I8:
14063 LoadMnemonic = PPC::LBARX;
14064 StoreMnemonic = PPC::STBCX;
14065 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14067 case PPC::ATOMIC_CMP_SWAP_I16:
14068 LoadMnemonic = PPC::LHARX;
14069 StoreMnemonic = PPC::STHCX;
14070 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14072 case PPC::ATOMIC_CMP_SWAP_I32:
14073 LoadMnemonic = PPC::LWARX;
14074 StoreMnemonic = PPC::STWCX;
14076 case PPC::ATOMIC_CMP_SWAP_I64:
14077 LoadMnemonic = PPC::LDARX;
14078 StoreMnemonic = PPC::STDCX;
14085 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14086 Register oldval =
MI.getOperand(3).getReg();
14087 Register newval =
MI.getOperand(4).getReg();
14093 F->insert(It, loop1MBB);
14094 F->insert(It, loop2MBB);
14095 F->insert(It, exitMBB);
14116 BuildMI(BB, dl,
TII->get(is64bit ? PPC::CMPD : PPC::CMPW), CrReg)
14142 }
else if (
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 ||
14143 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16) {
14147 bool is64bit = Subtarget.isPPC64();
14148 bool isLittleEndian = Subtarget.isLittleEndian();
14149 bool is8bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8;
14154 Register oldval =
MI.getOperand(3).getReg();
14155 Register newval =
MI.getOperand(4).getReg();
14161 F->insert(It, loop1MBB);
14162 F->insert(It, loop2MBB);
14163 F->insert(It, exitMBB);
14170 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
14173 Register PtrReg = RegInfo.createVirtualRegister(RC);
14174 Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
14176 isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
14177 Register NewVal2Reg = RegInfo.createVirtualRegister(GPRC);
14178 Register NewVal3Reg = RegInfo.createVirtualRegister(GPRC);
14179 Register OldVal2Reg = RegInfo.createVirtualRegister(GPRC);
14180 Register OldVal3Reg = RegInfo.createVirtualRegister(GPRC);
14181 Register MaskReg = RegInfo.createVirtualRegister(GPRC);
14182 Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
14183 Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
14184 Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
14185 Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
14186 Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
14188 Register TmpReg = RegInfo.createVirtualRegister(GPRC);
14189 Register ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
14190 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14221 if (ptrA != ZeroReg) {
14222 Ptr1Reg = RegInfo.createVirtualRegister(RC);
14223 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
14232 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
14233 .
addReg(Ptr1Reg, 0, is64bit ? PPC::sub_32 : 0)
14236 .
addImm(is8bit ? 28 : 27);
14237 if (!isLittleEndian)
14238 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
14240 .
addImm(is8bit ? 24 : 16);
14242 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
14247 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
14252 BuildMI(BB, dl,
TII->get(PPC::SLW), NewVal2Reg)
14255 BuildMI(BB, dl,
TII->get(PPC::SLW), OldVal2Reg)
14262 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
14266 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
14269 BuildMI(BB, dl,
TII->get(PPC::AND), NewVal3Reg)
14272 BuildMI(BB, dl,
TII->get(PPC::AND), OldVal3Reg)
14277 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
14294 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
14318 }
else if (
MI.getOpcode() == PPC::FADDrtz) {
14328 Register MFFSReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14343 auto MIB =
BuildMI(*BB,
MI, dl,
TII->get(PPC::FADD), Dest)
14351 }
else if (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
14352 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT ||
14353 MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
14354 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8) {
14355 unsigned Opcode = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
14356 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8)
14359 bool IsEQ = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
14360 MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8);
14363 Register Dest = RegInfo.createVirtualRegister(
14364 Opcode == PPC::ANDI_rec ? &PPC::GPRCRegClass : &PPC::G8RCRegClass);
14368 .
addReg(
MI.getOperand(1).getReg())
14371 MI.getOperand(0).getReg())
14372 .
addReg(IsEQ ? PPC::CR0EQ : PPC::CR0GT);
14373 }
else if (
MI.getOpcode() == PPC::TCHECK_RET) {
14376 Register CRReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14379 MI.getOperand(0).getReg())
14381 }
else if (
MI.getOpcode() == PPC::TBEGIN_RET) {
14383 unsigned Imm =
MI.getOperand(1).getImm();
14386 MI.getOperand(0).getReg())
14388 }
else if (
MI.getOpcode() == PPC::SETRNDi) {
14390 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14393 if (
MRI.use_empty(OldFPSCRReg))
14394 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14396 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14407 unsigned Mode =
MI.getOperand(1).getImm();
14408 BuildMI(*BB,
MI, dl,
TII->get((Mode & 1) ? PPC::MTFSB1 : PPC::MTFSB0))
14412 BuildMI(*BB,
MI, dl,
TII->get((Mode & 2) ? PPC::MTFSB1 : PPC::MTFSB0))
14415 }
else if (
MI.getOpcode() == PPC::SETRND) {
14423 auto copyRegFromG8RCOrF8RC = [&] (
unsigned DestReg,
unsigned SrcReg) {
14424 if (Subtarget.hasDirectMove()) {
14425 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::COPY), DestReg)
14429 unsigned StoreOp = PPC::STD, LoadOp = PPC::LFD;
14432 if (RC == &PPC::F8RCRegClass) {
14434 assert((RegInfo.getRegClass(DestReg) == &PPC::G8RCRegClass) &&
14435 "Unsupported RegClass.");
14437 StoreOp = PPC::STFD;
14441 assert((RegInfo.getRegClass(SrcReg) == &PPC::G8RCRegClass) &&
14442 (RegInfo.getRegClass(DestReg) == &PPC::F8RCRegClass) &&
14443 "Unsupported RegClass.");
14476 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14479 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14491 Register OldFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14493 copyRegFromG8RCOrF8RC(OldFPSCRTmpReg, OldFPSCRReg);
14495 Register ImDefReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14496 Register ExtSrcReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14501 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), ImDefReg);
14502 BuildMI(*BB,
MI, dl,
TII->get(PPC::INSERT_SUBREG), ExtSrcReg)
14507 Register NewFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14508 BuildMI(*BB,
MI, dl,
TII->get(PPC::RLDIMI), NewFPSCRTmpReg)
14514 Register NewFPSCRReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14515 copyRegFromG8RCOrF8RC(NewFPSCRReg, NewFPSCRTmpReg);
14524 }
else if (
MI.getOpcode() == PPC::SETFLM) {
14528 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14529 if (
MRI.use_empty(OldFPSCRReg))
14530 BuildMI(*BB,
MI, Dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14532 BuildMI(*BB,
MI, Dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14535 Register NewFPSCRReg =
MI.getOperand(1).getReg();
14541 }
else if (
MI.getOpcode() == PPC::PROBED_ALLOCA_32 ||
14542 MI.getOpcode() == PPC::PROBED_ALLOCA_64) {
14544 }
else if (
MI.getOpcode() == PPC::SPLIT_QUADWORD) {
14551 .
addUse(Src, 0, PPC::sub_gp8_x1);
14554 .
addUse(Src, 0, PPC::sub_gp8_x0);
14555 }
else if (
MI.getOpcode() == PPC::LQX_PSEUDO ||
14556 MI.getOpcode() == PPC::STQX_PSEUDO) {
14562 F->getRegInfo().createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass);
14568 MI.getOpcode() == PPC::LQX_PSEUDO ?
TII->get(PPC::LQ)
14569 :
TII->get(PPC::STQ))
14573 }
else if (
MI.getOpcode() == PPC::LWAT_PSEUDO ||
14574 MI.getOpcode() == PPC::LDAT_PSEUDO) {
14576 Register DstReg =
MI.getOperand(0).getReg();
14577 Register PtrReg =
MI.getOperand(1).getReg();
14578 Register ValReg =
MI.getOperand(2).getReg();
14579 unsigned FC =
MI.getOperand(3).getImm();
14580 bool IsLwat =
MI.getOpcode() == PPC::LWAT_PSEUDO;
14581 Register Val64 =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
14583 BuildMI(*BB,
MI,
DL,
TII->get(TargetOpcode::SUBREG_TO_REG), Val64)
14590 Register G8rPair =
MRI.createVirtualRegister(&PPC::G8pRCRegClass);
14591 Register UndefG8r =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
14592 BuildMI(*BB,
MI,
DL,
TII->get(TargetOpcode::IMPLICIT_DEF), UndefG8r);
14595 .
addImm(PPC::sub_gp8_x0)
14597 .
addImm(PPC::sub_gp8_x1);
14599 Register PairResult =
MRI.createVirtualRegister(&PPC::G8pRCRegClass);
14600 BuildMI(*BB,
MI,
DL,
TII->get(IsLwat ? PPC::LWAT : PPC::LDAT), PairResult)
14604 Register Result64 =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
14606 .
addReg(PairResult, 0, PPC::sub_gp8_x0);
14609 .
addReg(Result64, 0, PPC::sub_32);
14617 MI.eraseFromParent();
14630 int RefinementSteps = Subtarget.hasRecipPrec() ? 1 : 3;
14633 return RefinementSteps;
14639 EVT VT =
Op.getValueType();
14642 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX())))
14666PPCTargetLowering::getSqrtResultForDenormInput(
SDValue Op,
14669 EVT VT =
Op.getValueType();
14670 if (VT != MVT::f64 &&
14671 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX()))
14674 return DAG.
getNode(PPCISD::FSQRT, SDLoc(
Op), VT,
Op);
14678 int Enabled,
int &RefinementSteps,
14679 bool &UseOneConstNR,
14680 bool Reciprocal)
const {
14682 if ((VT == MVT::f32 && Subtarget.hasFRSQRTES()) ||
14683 (VT == MVT::f64 && Subtarget.hasFRSQRTE()) ||
14684 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
14685 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
14691 UseOneConstNR = !Subtarget.needsTwoConstNR();
14692 return DAG.
getNode(PPCISD::FRSQRTE, SDLoc(Operand), VT, Operand);
14699 int &RefinementSteps)
const {
14701 if ((VT == MVT::f32 && Subtarget.hasFRES()) ||
14702 (VT == MVT::f64 && Subtarget.hasFRE()) ||
14703 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
14704 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
14707 return DAG.
getNode(PPCISD::FRE, SDLoc(Operand), VT, Operand);
14723 switch (Subtarget.getCPUDirective()) {
14750 unsigned Bytes,
int Dist,
14764 if (FS != BFS || FS != (
int)Bytes)
return false;
14769 int64_t Offset1 = 0, Offset2 = 0;
14772 if (Base1 == Base2 && Offset1 == (Offset2 + Dist * Bytes))
14782 if (isGA1 && isGA2 && GV1 == GV2)
14783 return Offset1 == (Offset2 + Dist*Bytes);
14790 unsigned Bytes,
int Dist,
14793 EVT VT = LS->getMemoryVT();
14800 switch (
N->getConstantOperandVal(1)) {
14801 default:
return false;
14802 case Intrinsic::ppc_altivec_lvx:
14803 case Intrinsic::ppc_altivec_lvxl:
14804 case Intrinsic::ppc_vsx_lxvw4x:
14805 case Intrinsic::ppc_vsx_lxvw4x_be:
14808 case Intrinsic::ppc_vsx_lxvd2x:
14809 case Intrinsic::ppc_vsx_lxvd2x_be:
14812 case Intrinsic::ppc_altivec_lvebx:
14815 case Intrinsic::ppc_altivec_lvehx:
14818 case Intrinsic::ppc_altivec_lvewx:
14828 switch (
N->getConstantOperandVal(1)) {
14829 default:
return false;
14830 case Intrinsic::ppc_altivec_stvx:
14831 case Intrinsic::ppc_altivec_stvxl:
14832 case Intrinsic::ppc_vsx_stxvw4x:
14835 case Intrinsic::ppc_vsx_stxvd2x:
14838 case Intrinsic::ppc_vsx_stxvw4x_be:
14841 case Intrinsic::ppc_vsx_stxvd2x_be:
14844 case Intrinsic::ppc_altivec_stvebx:
14847 case Intrinsic::ppc_altivec_stvehx:
14850 case Intrinsic::ppc_altivec_stvewx:
14867 SDValue Chain = LD->getChain();
14868 EVT VT = LD->getMemoryVT();
14877 while (!Queue.empty()) {
14878 SDNode *ChainNext = Queue.pop_back_val();
14879 if (!Visited.
insert(ChainNext).second)
14886 if (!Visited.
count(ChainLD->getChain().getNode()))
14887 Queue.push_back(ChainLD->getChain().getNode());
14889 for (
const SDUse &O : ChainNext->
ops())
14890 if (!Visited.
count(O.getNode()))
14891 Queue.push_back(O.getNode());
14893 LoadRoots.
insert(ChainNext);
14904 for (
SDNode *
I : LoadRoots) {
14905 Queue.push_back(
I);
14907 while (!Queue.empty()) {
14908 SDNode *LoadRoot = Queue.pop_back_val();
14909 if (!Visited.
insert(LoadRoot).second)
14921 Queue.push_back(U);
14954 auto Final = Shifted;
14965 DAGCombinerInfo &DCI)
const {
14968 SelectionDAG &DAG = DCI.DAG;
14973 if (!DCI.isAfterLegalizeDAG())
14978 for (
const SDNode *U :
N->users())
14983 auto OpSize =
N->getOperand(0).getValueSizeInBits();
14987 if (OpSize <
Size) {
15005 DAGCombinerInfo &DCI)
const {
15006 SelectionDAG &DAG = DCI.DAG;
15009 assert(Subtarget.useCRBits() &&
"Expecting to be tracking CR bits");
15020 N->getValueType(0) != MVT::i1)
15023 if (
N->getOperand(0).getValueType() != MVT::i32 &&
15024 N->getOperand(0).getValueType() != MVT::i64)
15034 unsigned OpBits =
N->getOperand(0).getValueSizeInBits();
15045 return (
N->getOpcode() ==
ISD::SETCC ? ConvertSETCCToSubtract(
N, DCI)
15068 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15069 N->getOperand(0).getOpcode() !=
ISD::OR &&
15070 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15080 N->getOperand(1).getOpcode() !=
ISD::AND &&
15081 N->getOperand(1).getOpcode() !=
ISD::OR &&
15082 N->getOperand(1).getOpcode() !=
ISD::XOR &&
15093 SmallPtrSet<SDNode *, 16> Visited;
15095 for (
unsigned i = 0; i < 2; ++i) {
15099 N->getOperand(i).getOperand(0).getValueType() == MVT::i1) ||
15111 while (!BinOps.
empty()) {
15119 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15153 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15157 for (
const SDNode *User : Inputs[i].
getNode()->
users()) {
15158 if (User !=
N && !Visited.
count(User))
15167 if (
User->getOperand(0) == Inputs[i])
15170 if (
User->getOperand(0) == Inputs[i] ||
15171 User->getOperand(1) == Inputs[i])
15177 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15178 for (
const SDNode *User : PromOps[i].
getNode()->
users()) {
15179 if (User !=
N && !Visited.
count(User))
15188 if (
User->getOperand(0) == PromOps[i])
15191 if (
User->getOperand(0) == PromOps[i] ||
15192 User->getOperand(1) == PromOps[i])
15199 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15208 std::list<HandleSDNode> PromOpHandles;
15209 for (
auto &PromOp : PromOps)
15210 PromOpHandles.emplace_back(PromOp);
15217 while (!PromOpHandles.empty()) {
15218 SDValue PromOp = PromOpHandles.back().getValue();
15219 PromOpHandles.pop_back();
15228 PromOpHandles.emplace_front(PromOp);
15242 default:
C = 0;
break;
15255 PromOpHandles.emplace_front(PromOp);
15262 for (
unsigned i = 0; i < 2; ++i)
15272 return N->getOperand(0);
15280 DAGCombinerInfo &DCI)
const {
15281 SelectionDAG &DAG = DCI.DAG;
15298 if (
N->getValueType(0) != MVT::i32 &&
15299 N->getValueType(0) != MVT::i64)
15302 if (!((
N->getOperand(0).getValueType() == MVT::i1 && Subtarget.useCRBits()) ||
15303 (
N->getOperand(0).getValueType() == MVT::i32 && Subtarget.isPPC64())))
15306 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15307 N->getOperand(0).getOpcode() !=
ISD::OR &&
15308 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15315 SmallPtrSet<SDNode *, 16> Visited;
15319 while (!BinOps.
empty()) {
15327 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15353 DenseMap<SDNode *, EVT> SelectTruncOp[2];
15358 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15363 if (User !=
N && !Visited.
count(User))
15369 if (
User->getOperand(0) == Inputs[i])
15370 SelectTruncOp[0].
insert(std::make_pair(User,
15371 User->getOperand(0).getValueType()));
15373 if (
User->getOperand(0) == Inputs[i])
15374 SelectTruncOp[0].
insert(std::make_pair(User,
15375 User->getOperand(0).getValueType()));
15376 if (
User->getOperand(1) == Inputs[i])
15377 SelectTruncOp[1].
insert(std::make_pair(User,
15378 User->getOperand(1).getValueType()));
15383 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15385 if (User !=
N && !Visited.
count(User))
15391 if (
User->getOperand(0) == PromOps[i])
15392 SelectTruncOp[0].
insert(std::make_pair(User,
15393 User->getOperand(0).getValueType()));
15395 if (
User->getOperand(0) == PromOps[i])
15396 SelectTruncOp[0].
insert(std::make_pair(User,
15397 User->getOperand(0).getValueType()));
15398 if (
User->getOperand(1) == PromOps[i])
15399 SelectTruncOp[1].
insert(std::make_pair(User,
15400 User->getOperand(1).getValueType()));
15405 unsigned PromBits =
N->getOperand(0).getValueSizeInBits();
15406 bool ReallyNeedsExt =
false;
15410 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15415 Inputs[i].getOperand(0).getValueSizeInBits();
15416 assert(PromBits < OpBits &&
"Truncation not to a smaller bit count?");
15421 OpBits-PromBits))) ||
15424 (OpBits-(PromBits-1)))) {
15425 ReallyNeedsExt =
true;
15433 std::list<HandleSDNode> PromOpHandles;
15434 for (
auto &PromOp : PromOps)
15435 PromOpHandles.emplace_back(PromOp);
15439 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15446 SDValue InSrc = Inputs[i].getOperand(0);
15464 while (!PromOpHandles.empty()) {
15466 PromOpHandles.pop_back();
15470 default:
C = 0;
break;
15483 PromOpHandles.emplace_front(PromOp);
15493 (SelectTruncOp[1].count(PromOp.
getNode()) &&
15495 PromOpHandles.emplace_front(PromOp);
15503 for (
unsigned i = 0; i < 2; ++i) {
15521 auto SI0 = SelectTruncOp[0].
find(PromOp.
getNode());
15522 if (SI0 != SelectTruncOp[0].
end())
15524 auto SI1 = SelectTruncOp[1].
find(PromOp.
getNode());
15525 if (SI1 != SelectTruncOp[1].
end())
15534 if (!ReallyNeedsExt)
15535 return N->getOperand(0);
15542 N->getValueSizeInBits(0), PromBits),
15543 dl,
N->getValueType(0)));
15546 "Invalid extension type");
15549 DAG.
getConstant(
N->getValueSizeInBits(0) - PromBits, dl, ShiftAmountTy);
15559 auto isValidForConvert = [](
SDValue &Operand) {
15578 if (LoadNode->isVolatile())
15599 return (isValidForConvert(
LHS) && isValidForConvert(
RHS));
15609 "CC mus be ISD::SETNE or ISD::SETEQ");
15611 auto getV16i8Load = [&](
const SDValue &Operand) {
15615 assert(Operand.
getOpcode() == ISD::LOAD &&
"Must be LoadSDNode here.");
15618 return DAG.
getLoad(MVT::v16i8,
DL, LoadNode->getChain(),
15619 LoadNode->getBasePtr(), LoadNode->getMemOperand());
15658 SDValue LHSVec = getV16i8Load(
N->getOperand(0));
15659 SDValue RHSVec = getV16i8Load(
N->getOperand(1));
15662 DAG.
getConstant(Intrinsic::ppc_altivec_vcmpequb_p,
DL, MVT::i32);
15665 IntrID, CRSel, LHSVec, RHSVec);
15668 return DAG.
getSetCC(
DL,
N->getValueType(0), PredResult,
15686 auto IsAndWithOne = [](
SDValue &V) {
15697 auto IsCompareWithZero = [](
SDValue &V) {
15704 return (IsAndWithOne(
LHS) && IsCompareWithZero(
RHS)) ||
15705 (IsAndWithOne(
RHS) && IsCompareWithZero(
LHS));
15722 auto MakeXor1 = [&](
SDValue V) {
15723 EVT VT = V.getValueType();
15730 return MakeXor1(
LHS);
15733 return MakeXor1(
RHS);
15739 DAGCombinerInfo &DCI)
const {
15741 "Should be called with a SETCC node");
15763 SelectionDAG &DAG = DCI.DAG;
15764 EVT VT =
N->getValueType(0);
15765 EVT OpVT =
LHS.getValueType();
15787 return DAGCombineTruncBoolExt(
N, DCI);
15794 Op.getValueType() == MVT::f64;
15806combineElementTruncationToVectorTruncation(
SDNode *
N,
15807 DAGCombinerInfo &DCI)
const {
15809 "Should be called with a BUILD_VECTOR node");
15811 SelectionDAG &DAG = DCI.DAG;
15814 SDValue FirstInput =
N->getOperand(0);
15816 "The input operand must be an fp-to-int conversion.");
15821 if (FirstConversion == PPCISD::FCTIDZ ||
15822 FirstConversion == PPCISD::FCTIDUZ ||
15823 FirstConversion == PPCISD::FCTIWZ ||
15824 FirstConversion == PPCISD::FCTIWUZ) {
15825 bool IsSplat =
true;
15826 bool Is32Bit = FirstConversion == PPCISD::FCTIWZ ||
15827 FirstConversion == PPCISD::FCTIWUZ;
15830 EVT TargetVT =
N->getValueType(0);
15831 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
15832 SDValue NextOp =
N->getOperand(i);
15833 if (NextOp.
getOpcode() != PPCISD::MFVSR)
15836 if (NextConversion != FirstConversion)
15844 if (
N->getOperand(i) != FirstInput)
15855 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
15856 SDValue In =
N->getOperand(i).getOperand(0);
15866 Ops.push_back(Trunc);
15869 Ops.push_back(
In.isUndef() ? DAG.
getUNDEF(SrcVT) :
In.getOperand(0));
15873 if (FirstConversion == PPCISD::FCTIDZ ||
15874 FirstConversion == PPCISD::FCTIWZ)
15879 EVT NewVT = TargetVT == MVT::v2i64 ? MVT::v2f64 : MVT::v4f32;
15881 return DAG.
getNode(Opcode, dl, TargetVT, BV);
15899 static const APInt BasePattern =
APInt(128, 0x8000000000000000ULL) << 64;
15903 if (FullVal == BasePattern)
15904 return std::make_tuple(Uim,
uint8_t{0});
15907 if (FullVal ==
APInt(128, 1))
15908 return std::make_tuple(Uim,
uint8_t{127});
15910 return std::nullopt;
15930 "Expected a BuildVectorSDNode in combineBVLoadsSpecialValue");
15934 EVT VT =
Op.getValueType();
15935 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
15949 for (
const SDValue &Operand :
Op.getNode()->op_values()) {
15959 for (
unsigned Index = 0;
Index < NumElems; ++
Index) {
15963 uint64_t ElemValue =
C->getZExtValue();
15967 ElemValue &= ((1ULL << ElemBits) - 1);
15971 (IsLittleEndian) ? (Index * ElemBits) : (128 - (
Index + 1) * ElemBits);
15974 APInt ElemAPInt(128, ElemValue);
15975 ElemAPInt <<= BitPos;
15978 FullVal |= ElemAPInt;
15985 const auto &[Uim, ShiftAmount] = *UIMOpt;
15989 if (ShiftAmount == 0) {
15994 <<
"combineBVLoadsSpecialValue: Instruction Emitted ";
15995 LxvkqInstr.
dump());
15999 assert(ShiftAmount == 127 &&
"Unexpected lxvkq shift amount value");
16011 DAG.
getMachineNode(PPC::VSRQ, Dl, VT, ShiftAmountVec, ShiftAmountVec),
16014 <<
"\n combineBVLoadsSpecialValue: Instruction Emitted ";
16030 "Should be called with a BUILD_VECTOR node");
16035 if (!
N->getValueType(0).getVectorElementType().isByteSized())
16038 bool InputsAreConsecutiveLoads =
true;
16039 bool InputsAreReverseConsecutive =
true;
16040 unsigned ElemSize =
N->getValueType(0).getScalarType().getStoreSize();
16041 SDValue FirstInput =
N->getOperand(0);
16042 bool IsRoundOfExtLoad =
false;
16051 if ((!IsRoundOfExtLoad && FirstInput.
getOpcode() != ISD::LOAD) ||
16052 N->getNumOperands() == 1)
16055 if (!IsRoundOfExtLoad)
16060 for (
int i = 1, e =
N->getNumOperands(); i < e; ++i) {
16062 if (IsRoundOfExtLoad &&
N->getOperand(i).getOpcode() !=
ISD::FP_ROUND)
16065 SDValue NextInput = IsRoundOfExtLoad ?
N->getOperand(i).getOperand(0) :
16067 if (NextInput.
getOpcode() != ISD::LOAD)
16071 IsRoundOfExtLoad ?
N->getOperand(i-1).getOperand(0) :
N->getOperand(i-1);
16082 InputsAreConsecutiveLoads =
false;
16084 InputsAreReverseConsecutive =
false;
16087 if (!InputsAreConsecutiveLoads && !InputsAreReverseConsecutive)
16092 assert(!(InputsAreConsecutiveLoads && InputsAreReverseConsecutive) &&
16093 "The loads cannot be both consecutive and reverse consecutive.");
16097 if (InputsAreConsecutiveLoads) {
16098 assert(FirstLoad &&
"Input needs to be a LoadSDNode.");
16102 ReturnSDVal = WideLoad;
16103 }
else if (InputsAreReverseConsecutive) {
16105 assert(LastLoad &&
"Input needs to be a LoadSDNode.");
16110 for (
int i =
N->getNumOperands() - 1; i >= 0; i--)
16118 for (
auto *LD : InputLoads)
16120 return ReturnSDVal;
16131 unsigned NumElems =
Input.getValueType().getVectorNumElements();
16137 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16139 ShuffleMask[CorrectElems & 0xF] = Elems & 0xF;
16141 ShuffleMask[(CorrectElems & 0xF0) >> 4] = (Elems & 0xF0) >> 4;
16142 CorrectElems = CorrectElems >> 8;
16143 Elems = Elems >> 8;
16150 EVT VT =
N->getValueType(0);
16154 Input.getValueType().getVectorElementType(),
16188 auto isSExtOfVecExtract = [&](
SDValue Op) ->
bool {
16214 Elems = Elems << 8;
16223 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16224 if (!isSExtOfVecExtract(
N->getOperand(i))) {
16231 int TgtElemArrayIdx;
16232 int InputSize =
Input.getValueType().getScalarSizeInBits();
16233 int OutputSize =
N->getValueType(0).getScalarSizeInBits();
16234 if (InputSize + OutputSize == 40)
16235 TgtElemArrayIdx = 0;
16236 else if (InputSize + OutputSize == 72)
16237 TgtElemArrayIdx = 1;
16238 else if (InputSize + OutputSize == 48)
16239 TgtElemArrayIdx = 2;
16240 else if (InputSize + OutputSize == 80)
16241 TgtElemArrayIdx = 3;
16242 else if (InputSize + OutputSize == 96)
16243 TgtElemArrayIdx = 4;
16247 uint64_t CorrectElems = TargetElems[TgtElemArrayIdx];
16249 ? CorrectElems & 0x0F0F0F0F0F0F0F0F
16250 : CorrectElems & 0xF0F0F0F0F0F0F0F0;
16251 if (Elems != CorrectElems) {
16267 if (
N->getValueType(0) != MVT::v1i128)
16270 SDValue Operand =
N->getOperand(0);
16277 EVT MemoryType = LD->getMemoryVT();
16281 bool ValidLDType = MemoryType == MVT::i8 || MemoryType == MVT::i16 ||
16282 MemoryType == MVT::i32 || MemoryType == MVT::i64;
16285 if (!ValidLDType ||
16291 LD->getChain(), LD->getBasePtr(),
16295 DAG.
getVTList(MVT::v1i128, MVT::Other),
16296 LoadOps, MemoryType, LD->getMemOperand());
16300 DAGCombinerInfo &DCI)
const {
16302 "Should be called with a BUILD_VECTOR node");
16304 SelectionDAG &DAG = DCI.DAG;
16307 if (!Subtarget.hasVSX())
16314 if (FirstInput.
getOpcode() == PPCISD::MFVSR) {
16315 SDValue Reduced = combineElementTruncationToVectorTruncation(
N, DCI);
16330 if (Subtarget.hasP9Altivec() && !DCI.isBeforeLegalize()) {
16339 if (Subtarget.isISA3_1()) {
16345 if (
N->getValueType(0) != MVT::v2f64)
16356 if (FirstInput.
getOpcode() !=
N->getOperand(1).getOpcode())
16367 if (!Ext1Op || !Ext2Op)
16376 if (FirstElem == 0 && SecondElem == 1)
16377 SubvecIdx = Subtarget.isLittleEndian() ? 1 : 0;
16378 else if (FirstElem == 2 && SecondElem == 3)
16379 SubvecIdx = Subtarget.isLittleEndian() ? 0 : 1;
16385 PPCISD::SINT_VEC_TO_FP : PPCISD::UINT_VEC_TO_FP;
16386 return DAG.
getNode(NodeType, dl, MVT::v2f64,
16391 DAGCombinerInfo &DCI)
const {
16394 "Need an int -> FP conversion node here");
16399 SelectionDAG &DAG = DCI.DAG;
16405 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
16407 if (!
Op.getOperand(0).getValueType().isSimple())
16409 if (
Op.getOperand(0).getValueType().getSimpleVT() <= MVT(MVT::i1) ||
16410 Op.getOperand(0).getValueType().getSimpleVT() > MVT(MVT::i64))
16413 SDValue FirstOperand(
Op.getOperand(0));
16414 bool SubWordLoad = FirstOperand.getOpcode() == ISD::LOAD &&
16415 (FirstOperand.getValueType() == MVT::i8 ||
16416 FirstOperand.getValueType() == MVT::i16);
16417 if (Subtarget.hasP9Vector() && Subtarget.hasP9Altivec() && SubWordLoad) {
16419 bool DstDouble =
Op.getValueType() == MVT::f64;
16420 unsigned ConvOp =
Signed ?
16421 (DstDouble ? PPCISD::FCFID : PPCISD::FCFIDS) :
16422 (DstDouble ? PPCISD::FCFIDU : PPCISD::FCFIDUS);
16427 SDValue Ops[] = { LDN->getChain(), LDN->getBasePtr(), WidthConst };
16430 Ops, MVT::i8, LDN->getMemOperand());
16435 SDValue ExtOps[] = { Ld, WidthConst };
16437 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ext);
16439 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ld);
16447 if (
Op.getOperand(0).getValueType() == MVT::i32)
16451 "UINT_TO_FP is supported only with FPCVT");
16455 unsigned FCFOp = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16460 MVT FCFTy = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16467 Subtarget.hasFPCVT()) ||
16469 SDValue Src =
Op.getOperand(0).getOperand(0);
16470 if (Src.getValueType() == MVT::f32) {
16471 Src = DAG.
getNode(ISD::FP_EXTEND, dl, MVT::f64, Src);
16472 DCI.AddToWorklist(Src.getNode());
16473 }
else if (Src.getValueType() != MVT::f64) {
16485 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
16488 DCI.AddToWorklist(
FP.getNode());
16512 switch (
N->getOpcode()) {
16517 Chain = LD->getChain();
16518 Base = LD->getBasePtr();
16519 MMO = LD->getMemOperand();
16538 MVT VecTy =
N->getValueType(0).getSimpleVT();
16546 Chain = Load.getValue(1);
16548 PPCISD::XXSWAPD, dl, DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Load);
16552 if (VecTy != MVT::v2f64) {
16579 switch (
N->getOpcode()) {
16584 Chain = ST->getChain();
16585 Base = ST->getBasePtr();
16586 MMO = ST->getMemOperand();
16606 SDValue Src =
N->getOperand(SrcOpnd);
16607 MVT VecTy = Src.getValueType().getSimpleVT();
16610 if (VecTy != MVT::v2f64) {
16611 Src = DAG.
getNode(ISD::BITCAST, dl, MVT::v2f64, Src);
16616 DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Src);
16622 StoreOps, VecTy, MMO);
16629 DAGCombinerInfo &DCI)
const {
16632 unsigned Opcode =
N->getOperand(1).getOpcode();
16634 bool Strict =
N->getOperand(1)->isStrictFPOpcode();
16638 &&
"Not a FP_TO_INT Instruction!");
16640 SDValue Val =
N->getOperand(1).getOperand(Strict ? 1 : 0);
16641 EVT Op1VT =
N->getOperand(1).getValueType();
16644 if (!Subtarget.hasVSX() || !Subtarget.hasFPCVT() || !
isTypeLegal(ResVT))
16648 bool ValidTypeForStoreFltAsInt =
16649 (Op1VT == MVT::i32 || (Op1VT == MVT::i64 && Subtarget.isPPC64()) ||
16650 (Subtarget.hasP9Vector() && (Op1VT == MVT::i16 || Op1VT == MVT::i8)));
16653 if (ResVT == MVT::ppcf128 || (ResVT == MVT::f128 && !Subtarget.hasP9Vector()))
16656 if ((Op1VT != MVT::i64 && !Subtarget.hasP8Vector()) ||
16664 SDValue Ops[] = {
N->getOperand(0), Val,
N->getOperand(2),
16679 bool PrevElemFromFirstVec = Mask[0] < NumElts;
16680 for (
int i = 1, e = Mask.size(); i < e; i++) {
16681 if (PrevElemFromFirstVec && Mask[i] < NumElts)
16683 if (!PrevElemFromFirstVec && Mask[i] >= NumElts)
16685 PrevElemFromFirstVec = !PrevElemFromFirstVec;
16696 for (
int i = 0, e =
Op.getNumOperands(); i < e; i++) {
16697 FirstOp =
Op.getOperand(i);
16703 for (
int i = 1, e =
Op.getNumOperands(); i < e; i++)
16704 if (
Op.getOperand(i) != FirstOp && !
Op.getOperand(i).isUndef())
16712 if (
Op.getOpcode() != ISD::BITCAST)
16714 Op =
Op.getOperand(0);
16730 int RHSFirstElt,
int RHSLastElt,
int HalfVec,
unsigned LHSNumValidElts,
16731 unsigned RHSNumValidElts,
const PPCSubtarget &Subtarget) {
16733 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - LHSNumValidElts;
16735 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - RHSNumValidElts;
16736 for (
int I = 0,
E = ShuffV.
size();
I <
E; ++
I) {
16737 int Idx = ShuffV[
I];
16738 if (Idx >= LHSFirstElt && Idx <= LHSLastElt)
16739 ShuffV[
I] += LHSEltFixup;
16740 else if (Idx >= RHSFirstElt && Idx <= RHSLastElt)
16741 ShuffV[
I] += RHSEltFixup;
16752 SDLoc dl(OrigSToV);
16755 "Expecting a SCALAR_TO_VECTOR here");
16768 "Cannot produce a permuted scalar_to_vector for one element vector");
16770 unsigned ResultInElt = NumElts / 2;
16776 return DAG.
getNode(PPCISD::SCALAR_TO_VECTOR_PERMUTED, dl, VT,
16781 int HalfVec,
int LHSLastElementDefined,
16782 int RHSLastElementDefined) {
16783 for (
int Index : ShuffV) {
16787 if ((LHSLastElementDefined >= 0) && (Index < HalfVec) &&
16788 (Index > LHSLastElementDefined))
16791 if ((RHSLastElementDefined >= 0) &&
16792 (Index > HalfVec + RHSLastElementDefined))
16799 int ScalarSize,
uint64_t ShuffleEltWidth,
unsigned &NumValidElts,
16800 int FirstElt,
int &LastElt,
SDValue VecShuffOperand,
SDValue SToVNode,
16816 LastElt = (
uint64_t)ScalarSize > ShuffleEltWidth
16817 ? ScalarSize / ShuffleEltWidth - 1 + FirstElt
16820 if (SToVPermuted.
getValueType() != VecShuffOperandType)
16821 SToVPermuted = DAG.
getBitcast(VecShuffOperandType, SToVPermuted);
16822 return SToVPermuted;
16842 int NumElts =
LHS.getValueType().getVectorNumElements();
16845 bool IsLittleEndian = Subtarget.isLittleEndian();
16852 if (!Subtarget.hasDirectMove())
16868 SmallVector<int, 16> ShuffV(Mask);
16871 if (SToVLHS || SToVRHS) {
16874 int ShuffleNumElts = ShuffV.
size();
16875 int HalfVec = ShuffleNumElts / 2;
16881 unsigned LHSNumValidElts = HalfVec;
16882 unsigned RHSNumValidElts = HalfVec;
16887 int LHSFirstElt = 0;
16888 int RHSFirstElt = ShuffleNumElts;
16889 int LHSLastElt = -1;
16890 int RHSLastElt = -1;
16898 int LHSScalarSize = 0;
16899 int RHSScalarSize = 0;
16902 if (!IsLittleEndian && LHSScalarSize >= 64)
16907 if (!IsLittleEndian && RHSScalarSize >= 64)
16910 if (LHSScalarSize != 0)
16912 LHSScalarSize, ShuffleEltWidth, LHSNumValidElts, LHSFirstElt,
16913 LHSLastElt,
LHS, SToVLHS, DAG, Subtarget);
16914 if (RHSScalarSize != 0)
16916 RHSScalarSize, ShuffleEltWidth, RHSNumValidElts, RHSFirstElt,
16917 RHSLastElt,
RHS, SToVRHS, DAG, Subtarget);
16928 ShuffV, LHSFirstElt, LHSLastElt, RHSFirstElt, RHSLastElt, HalfVec,
16929 LHSNumValidElts, RHSNumValidElts, Subtarget);
16955 if (IsLittleEndian) {
16958 if (Mask[0] < NumElts)
16959 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
16963 ShuffV[i] = (ShuffV[i - 1] >= 0 ? ShuffV[i - 1] : 0) + NumElts;
16968 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
16972 ShuffV[i] = (ShuffV[i + 1] >= 0 ? ShuffV[i + 1] : 0) + NumElts;
16977 if (Mask[0] < NumElts)
16978 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
16982 ShuffV[i] = ShuffV[i + 1] >= 0 ? ShuffV[i + 1] - NumElts : 0;
16987 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
16991 ShuffV[i] = ShuffV[i - 1] >= 0 ? ShuffV[i - 1] - NumElts : 0;
17001 if (IsLittleEndian)
17010 DAGCombinerInfo &DCI)
const {
17012 "Not a reverse memop pattern!");
17014 auto IsElementReverse = [](
const ShuffleVectorSDNode *SVN) ->
bool {
17017 auto I =
Mask.rbegin();
17018 auto E =
Mask.rend();
17020 for (;
I !=
E; ++
I) {
17028 SelectionDAG &DAG = DCI.DAG;
17031 if (!
isTypeLegal(VT) || !Subtarget.isLittleEndian() || !Subtarget.hasVSX())
17037 if (!Subtarget.hasP9Vector())
17040 if(!IsElementReverse(SVN))
17043 if (LSBase->
getOpcode() == ISD::LOAD) {
17047 for (SDUse &Use : LSBase->
uses())
17048 if (
Use.getResNo() == 0 &&
17055 PPCISD::LOAD_VEC_BE, dl, DAG.
getVTList(VT, MVT::Other), LoadOps,
17059 if (LSBase->
getOpcode() == ISD::STORE) {
17070 PPCISD::STORE_VEC_BE, dl, DAG.
getVTList(MVT::Other), StoreOps,
17079 if (IntrinsicID == Intrinsic::ppc_stdcx)
17081 else if (IntrinsicID == Intrinsic::ppc_stwcx)
17083 else if (IntrinsicID == Intrinsic::ppc_sthcx)
17085 else if (IntrinsicID == Intrinsic::ppc_stbcx)
17094 if (
N->getOpcode() == PPCISD::ADDC &&
N->hasAnyUseOfValue(1)) {
17098 if (
LHS->getOpcode() == PPCISD::ADDE &&
17111 switch (
N->getOpcode()) {
17114 return combineADD(
N, DCI);
17140 return combineSHL(
N, DCI);
17142 return combineSRA(
N, DCI);
17144 return combineSRL(
N, DCI);
17146 return combineMUL(
N, DCI);
17148 case PPCISD::FNMSUB:
17149 return combineFMALike(
N, DCI);
17152 return N->getOperand(0);
17156 return N->getOperand(0);
17162 return N->getOperand(0);
17168 return DAGCombineExtBoolTrunc(
N, DCI);
17170 return combineTRUNCATE(
N, DCI);
17172 if (
SDValue CSCC = combineSetCC(
N, DCI))
17176 return DAGCombineTruncBoolExt(
N, DCI);
17179 return combineFPToIntToFP(
N, DCI);
17188 EVT Op1VT =
N->getOperand(1).getValueType();
17189 unsigned Opcode =
N->getOperand(1).getOpcode();
17193 SDValue Val = combineStoreFPToInt(
N, DCI);
17207 N->getOperand(1).getNode()->hasOneUse() &&
17208 (Op1VT == MVT::i32 || Op1VT == MVT::i16 ||
17209 (Subtarget.hasLDBRX() && Subtarget.isPPC64() && Op1VT == MVT::i64))) {
17217 SDValue BSwapOp =
N->getOperand(1).getOperand(0);
17224 if (Op1VT.
bitsGT(mVT)) {
17229 if (Op1VT == MVT::i64)
17234 N->getOperand(0), BSwapOp,
N->getOperand(2), DAG.
getValueType(mVT)
17254 ST->getBasePtr(), ST->getOffset(), MemVT,
17255 ST->getMemOperand(), ST->getAddressingMode(),
17259 return ST->isUnindexed()
17268 if (Subtarget.needsSwapsForVSXMemOps() &&
17269 (StoreVT == MVT::v2f64 || StoreVT == MVT::v2i64 ||
17270 StoreVT == MVT::v4f32 || StoreVT == MVT::v4i32))
17277 EVT VT = LD->getValueType(0);
17283 if (Subtarget.needsSwapsForVSXMemOps() &&
17284 (LoadVT == MVT::v2f64 || LoadVT == MVT::v2i64 ||
17285 LoadVT == MVT::v4f32 || LoadVT == MVT::v4i32))
17296 auto ReplaceTwoFloatLoad = [&]() {
17297 if (VT != MVT::i64)
17312 if (!LD->hasNUsesOfValue(2, 0))
17315 auto UI = LD->user_begin();
17316 while (UI.getUse().getResNo() != 0) ++UI;
17318 while (UI.getUse().getResNo() != 0) ++UI;
17319 SDNode *RightShift = *UI;
17327 if (RightShift->getOpcode() !=
ISD::SRL ||
17329 RightShift->getConstantOperandVal(1) != 32 ||
17330 !RightShift->hasOneUse())
17333 SDNode *Trunc2 = *RightShift->user_begin();
17342 if (Bitcast->getOpcode() != ISD::BITCAST ||
17343 Bitcast->getValueType(0) != MVT::f32)
17345 if (Bitcast2->
getOpcode() != ISD::BITCAST ||
17349 if (Subtarget.isLittleEndian())
17355 SDValue BasePtr = LD->getBasePtr();
17356 if (LD->isIndexed()) {
17358 "Non-pre-inc AM on PPC?");
17366 SDValue FloatLoad = DAG.
getLoad(MVT::f32, dl, LD->getChain(), BasePtr,
17367 LD->getPointerInfo(), LD->getAlign(),
17368 MMOFlags, LD->getAAInfo());
17374 LD->getPointerInfo().getWithOffset(4),
17377 if (LD->isIndexed()) {
17391 if (ReplaceTwoFloatLoad())
17394 EVT MemVT = LD->getMemoryVT();
17397 if (LD->isUnindexed() && VT.
isVector() &&
17400 !Subtarget.hasP8Vector() &&
17401 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
17402 VT == MVT::v4f32))) &&
17403 LD->getAlign() < ABIAlignment) {
17405 SDValue Chain = LD->getChain();
17406 SDValue Ptr = LD->getBasePtr();
17407 bool isLittleEndian = Subtarget.isLittleEndian();
17434 MVT PermCntlTy, PermTy, LDTy;
17435 Intr = isLittleEndian ? Intrinsic::ppc_altivec_lvsr
17436 : Intrinsic::ppc_altivec_lvsl;
17437 IntrLD = Intrinsic::ppc_altivec_lvx;
17438 IntrPerm = Intrinsic::ppc_altivec_vperm;
17439 PermCntlTy = MVT::v16i8;
17440 PermTy = MVT::v4i32;
17459 SDValue BaseLoadOps[] = { Chain, LDXIntID, Ptr };
17463 BaseLoadOps, LDTy, BaseMMO);
17472 int IncValue = IncOffset;
17489 SDValue ExtraLoadOps[] = { Chain, LDXIntID, Ptr };
17493 ExtraLoadOps, LDTy, ExtraMMO);
17504 if (isLittleEndian)
17506 ExtraLoad, BaseLoad, PermCntl, DAG, dl);
17509 BaseLoad, ExtraLoad, PermCntl, DAG, dl);
17512 Perm = Subtarget.hasAltivec()
17513 ? DAG.
getNode(ISD::BITCAST, dl, VT, Perm)
17527 bool isLittleEndian = Subtarget.isLittleEndian();
17528 unsigned IID =
N->getConstantOperandVal(0);
17529 Intrinsic::ID Intr = (isLittleEndian ? Intrinsic::ppc_altivec_lvsr
17530 : Intrinsic::ppc_altivec_lvsl);
17531 if (IID == Intr &&
N->getOperand(1)->getOpcode() ==
ISD::ADD) {
17538 .zext(
Add.getScalarValueSizeInBits()))) {
17539 SDNode *BasePtr =
Add->getOperand(0).getNode();
17540 for (
SDNode *U : BasePtr->users()) {
17542 U->getConstantOperandVal(0) == IID) {
17553 SDNode *BasePtr =
Add->getOperand(0).getNode();
17554 for (
SDNode *U : BasePtr->users()) {
17557 (
Add->getConstantOperandVal(1) - U->getConstantOperandVal(1)) %
17563 V->getConstantOperandVal(0) == IID) {
17575 (IID == Intrinsic::ppc_altivec_vmaxsw ||
17576 IID == Intrinsic::ppc_altivec_vmaxsh ||
17577 IID == Intrinsic::ppc_altivec_vmaxsb)) {
17608 switch (
N->getConstantOperandVal(1)) {
17611 case Intrinsic::ppc_altivec_vsum4sbs:
17612 case Intrinsic::ppc_altivec_vsum4shs:
17613 case Intrinsic::ppc_altivec_vsum4ubs: {
17620 APInt APSplatBits, APSplatUndef;
17621 unsigned SplatBitSize;
17624 APSplatBits, APSplatUndef, SplatBitSize, HasAnyUndefs, 0,
17625 !Subtarget.isLittleEndian());
17627 if (BVNIsConstantSplat && APSplatBits == 0)
17632 case Intrinsic::ppc_vsx_lxvw4x:
17633 case Intrinsic::ppc_vsx_lxvd2x:
17636 if (Subtarget.needsSwapsForVSXMemOps())
17644 if (Subtarget.needsSwapsForVSXMemOps()) {
17645 switch (
N->getConstantOperandVal(1)) {
17648 case Intrinsic::ppc_vsx_stxvw4x:
17649 case Intrinsic::ppc_vsx_stxvd2x:
17658 bool Is64BitBswapOn64BitTgt =
17659 Subtarget.isPPC64() &&
N->getValueType(0) == MVT::i64;
17661 N->getOperand(0).hasOneUse();
17662 if (IsSingleUseNormalLd &&
17663 (
N->getValueType(0) == MVT::i32 ||
N->getValueType(0) == MVT::i16 ||
17664 (Subtarget.hasLDBRX() && Is64BitBswapOn64BitTgt))) {
17675 DAG.
getVTList(
N->getValueType(0) == MVT::i64 ?
17676 MVT::i64 : MVT::i32, MVT::Other),
17677 Ops, LD->getMemoryVT(), LD->getMemOperand());
17681 if (
N->getValueType(0) == MVT::i16)
17698 !IsSingleUseNormalLd)
17703 if (!LD->isSimple())
17705 SDValue BasePtr = LD->getBasePtr();
17707 LD->getPointerInfo(), LD->getAlign());
17712 LD->getMemOperand(), 4, 4);
17716 if (Subtarget.isLittleEndian())
17722 Hi.getOperand(0).getValue(1),
Lo.getOperand(0).getValue(1));
17731 if (!
N->getOperand(0).hasOneUse() &&
17732 !
N->getOperand(1).hasOneUse() &&
17733 !
N->getOperand(2).hasOneUse()) {
17736 SDNode *VCMPrecNode =
nullptr;
17738 SDNode *LHSN =
N->getOperand(0).getNode();
17740 if (
User->getOpcode() == PPCISD::VCMP_rec &&
17744 VCMPrecNode =
User;
17756 SDNode *FlagUser =
nullptr;
17758 FlagUser ==
nullptr; ++UI) {
17759 assert(UI != VCMPrecNode->
use_end() &&
"Didn't find user!");
17772 return SDValue(VCMPrecNode, 0);
17783 SDValue LHS =
N->getOperand(2), RHS =
N->getOperand(3);
17794 auto RHSAPInt = RHS->getAsAPIntVal();
17795 if (!RHSAPInt.isIntN(64))
17798 unsigned Val = RHSAPInt.getZExtValue();
17799 auto isImpossibleCompare = [&]() {
17802 if (Val != 0 && Val != 1) {
17804 return N->getOperand(0);
17806 return DAG.
getNode(ISD::BR, dl, MVT::Other,
17807 N->getOperand(0),
N->getOperand(4));
17812 unsigned StoreWidth = 0;
17815 if (
SDValue Impossible = isImpossibleCompare())
17827 SDValue Ops[] = {LHS.getOperand(0), LHS.getOperand(2), LHS.getOperand(3),
17831 PPCISD::STORE_COND, dl,
17833 MemNode->getMemoryVT(), MemNode->getMemOperand());
17837 if (
N->getOperand(0) == LHS.getValue(1))
17848 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other, InChain,
17850 DAG.
getRegister(PPC::CR0, MVT::i32),
N->getOperand(4),
17856 assert(isDot &&
"Can't compare against a vector result!");
17858 if (
SDValue Impossible = isImpossibleCompare())
17861 bool BranchOnWhenPredTrue = (CC ==
ISD::SETEQ) ^ (Val == 0);
17868 EVT VTs[] = { LHS.getOperand(2).getValueType(), MVT::Glue };
17873 switch (LHS.getConstantOperandVal(1)) {
17889 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other,
N->getOperand(0),
17892 N->getOperand(4), CompNode.
getValue(1));
17897 return DAGCombineBuildVector(
N, DCI);
17910 EVT VT =
N->getValueType(0);
17911 if (VT == MVT::i64 && !Subtarget.isPPC64())
17913 if ((VT != MVT::i32 && VT != MVT::i64) ||
17921 unsigned Lg2 = (IsNegPow2 ? -Divisor : Divisor).
countr_zero();
17941 const APInt &DemandedElts,
17943 unsigned Depth)
const {
17945 switch (
Op.getOpcode()) {
17947 case PPCISD::LBRX: {
17950 Known.
Zero = 0xFFFF0000;
17953 case PPCISD::ADDE: {
17954 if (
Op.getResNo() == 0) {
17959 Known.
Zero = ~1ULL;
17964 switch (
Op.getConstantOperandVal(0)) {
17966 case Intrinsic::ppc_altivec_vcmpbfp_p:
17967 case Intrinsic::ppc_altivec_vcmpeqfp_p:
17968 case Intrinsic::ppc_altivec_vcmpequb_p:
17969 case Intrinsic::ppc_altivec_vcmpequh_p:
17970 case Intrinsic::ppc_altivec_vcmpequw_p:
17971 case Intrinsic::ppc_altivec_vcmpequd_p:
17972 case Intrinsic::ppc_altivec_vcmpequq_p:
17973 case Intrinsic::ppc_altivec_vcmpgefp_p:
17974 case Intrinsic::ppc_altivec_vcmpgtfp_p:
17975 case Intrinsic::ppc_altivec_vcmpgtsb_p:
17976 case Intrinsic::ppc_altivec_vcmpgtsh_p:
17977 case Intrinsic::ppc_altivec_vcmpgtsw_p:
17978 case Intrinsic::ppc_altivec_vcmpgtsd_p:
17979 case Intrinsic::ppc_altivec_vcmpgtsq_p:
17980 case Intrinsic::ppc_altivec_vcmpgtub_p:
17981 case Intrinsic::ppc_altivec_vcmpgtuh_p:
17982 case Intrinsic::ppc_altivec_vcmpgtuw_p:
17983 case Intrinsic::ppc_altivec_vcmpgtud_p:
17984 case Intrinsic::ppc_altivec_vcmpgtuq_p:
17991 switch (
Op.getConstantOperandVal(1)) {
17994 case Intrinsic::ppc_load2r:
17996 Known.
Zero = 0xFFFF0000;
18005 switch (Subtarget.getCPUDirective()) {
18027 if (
ML->getLoopDepth() > 1 &&
ML->getSubLoops().empty())
18036 for (
auto I =
ML->block_begin(), IE =
ML->block_end();
I != IE; ++
I)
18038 LoopSize +=
TII->getInstSizeInBytes(J);
18043 if (LoopSize > 16 && LoopSize <= 32)
18057 if (Constraint.
size() == 1) {
18058 switch (Constraint[0]) {
18076 }
else if (Constraint ==
"wc") {
18078 }
else if (Constraint ==
"wa" || Constraint ==
"wd" ||
18079 Constraint ==
"wf" || Constraint ==
"ws" ||
18080 Constraint ==
"wi" || Constraint ==
"ww") {
18093 Value *CallOperandVal =
info.CallOperandVal;
18096 if (!CallOperandVal)
18103 else if ((
StringRef(constraint) ==
"wa" ||
18115 switch (*constraint) {
18145std::pair<unsigned, const TargetRegisterClass *>
18149 if (Constraint.
size() == 1) {
18151 switch (Constraint[0]) {
18153 if (VT == MVT::i64 && Subtarget.isPPC64())
18154 return std::make_pair(0U, &PPC::G8RC_NOX0RegClass);
18155 return std::make_pair(0U, &PPC::GPRC_NOR0RegClass);
18157 if (VT == MVT::i64 && Subtarget.isPPC64())
18158 return std::make_pair(0U, &PPC::G8RCRegClass);
18159 return std::make_pair(0U, &PPC::GPRCRegClass);
18165 if (Subtarget.hasSPE()) {
18166 if (VT == MVT::f32 || VT == MVT::i32)
18167 return std::make_pair(0U, &PPC::GPRCRegClass);
18168 if (VT == MVT::f64 || VT == MVT::i64)
18169 return std::make_pair(0U, &PPC::SPERCRegClass);
18171 if (VT == MVT::f32 || VT == MVT::i32)
18172 return std::make_pair(0U, &PPC::F4RCRegClass);
18173 if (VT == MVT::f64 || VT == MVT::i64)
18174 return std::make_pair(0U, &PPC::F8RCRegClass);
18178 if (Subtarget.hasAltivec() && VT.
isVector())
18179 return std::make_pair(0U, &PPC::VRRCRegClass);
18180 else if (Subtarget.hasVSX())
18182 return std::make_pair(0U, &PPC::VFRCRegClass);
18185 return std::make_pair(0U, &PPC::CRRCRegClass);
18187 }
else if (Constraint ==
"wc" && Subtarget.useCRBits()) {
18189 return std::make_pair(0U, &PPC::CRBITRCRegClass);
18190 }
else if ((Constraint ==
"wa" || Constraint ==
"wd" ||
18191 Constraint ==
"wf" || Constraint ==
"wi") &&
18192 Subtarget.hasVSX()) {
18196 return std::make_pair(0U, &PPC::VSRCRegClass);
18197 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18198 return std::make_pair(0U, &PPC::VSSRCRegClass);
18199 return std::make_pair(0U, &PPC::VSFRCRegClass);
18200 }
else if ((Constraint ==
"ws" || Constraint ==
"ww") && Subtarget.hasVSX()) {
18201 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18202 return std::make_pair(0U, &PPC::VSSRCRegClass);
18204 return std::make_pair(0U, &PPC::VSFRCRegClass);
18205 }
else if (Constraint ==
"lr") {
18206 if (VT == MVT::i64)
18207 return std::make_pair(0U, &PPC::LR8RCRegClass);
18209 return std::make_pair(0U, &PPC::LRRCRegClass);
18214 if (Constraint[0] ==
'{' && Constraint[Constraint.
size() - 1] ==
'}') {
18218 if (Constraint.
size() > 3 && Constraint[1] ==
'v' && Constraint[2] ==
's') {
18219 int VSNum = atoi(Constraint.
data() + 3);
18220 assert(VSNum >= 0 && VSNum <= 63 &&
18221 "Attempted to access a vsr out of range");
18223 return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass);
18224 return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass);
18229 if (Constraint.
size() > 3 && Constraint[1] ==
'f') {
18230 int RegNum = atoi(Constraint.
data() + 2);
18231 if (RegNum > 31 || RegNum < 0)
18233 if (VT == MVT::f32 || VT == MVT::i32)
18234 return Subtarget.hasSPE()
18235 ? std::make_pair(PPC::R0 + RegNum, &PPC::GPRCRegClass)
18236 : std::make_pair(PPC::F0 + RegNum, &PPC::F4RCRegClass);
18237 if (VT == MVT::f64 || VT == MVT::i64)
18238 return Subtarget.hasSPE()
18239 ? std::make_pair(PPC::S0 + RegNum, &PPC::SPERCRegClass)
18240 : std::make_pair(PPC::F0 + RegNum, &PPC::F8RCRegClass);
18244 std::pair<unsigned, const TargetRegisterClass *> R =
18253 if (R.first && VT == MVT::i64 && Subtarget.isPPC64() &&
18254 PPC::GPRCRegClass.contains(R.first))
18255 return std::make_pair(
TRI->getMatchingSuperReg(R.first,
18256 PPC::sub_32, &PPC::G8RCRegClass),
18257 &PPC::G8RCRegClass);
18260 if (!R.second &&
StringRef(
"{cc}").equals_insensitive(Constraint)) {
18261 R.first = PPC::CR0;
18262 R.second = &PPC::CRRCRegClass;
18266 if (Subtarget.isAIXABI() && !TM.getAIXExtendedAltivecABI()) {
18267 if (((R.first >= PPC::V20 && R.first <= PPC::V31) ||
18268 (R.first >= PPC::VF20 && R.first <= PPC::VF31)) &&
18269 (R.second == &PPC::VSRCRegClass || R.second == &PPC::VSFRCRegClass))
18270 errs() <<
"warning: vector registers 20 to 32 are reserved in the "
18271 "default AIX AltiVec ABI and cannot be used\n";
18281 std::vector<SDValue> &
Ops,
18286 if (Constraint.
size() > 1)
18289 char Letter = Constraint[0];
18304 EVT TCVT = MVT::i64;
18345 if (Result.getNode()) {
18346 Ops.push_back(Result);
18357 if (
I.getNumOperands() <= 1)
18361 auto IntrinsicID =
Ops[1].getNode()->getAsZExtVal();
18362 if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw &&
18363 IntrinsicID != Intrinsic::ppc_trapd && IntrinsicID != Intrinsic::ppc_trap)
18366 if (
MDNode *MDN =
I.getMetadata(LLVMContext::MD_annotation))
18382 if (Ty->isVectorTy() && AM.
BaseOffs != 0 && !Subtarget.hasP9Vector())
18394 switch (AM.
Scale) {
18422 unsigned Depth =
Op.getConstantOperandVal(0);
18446 SDValue RetAddrFI = getReturnAddrFrameIndex(DAG);
18454 unsigned Depth =
Op.getConstantOperandVal(0);
18461 bool isPPC64 = PtrVT == MVT::i64;
18467 FrameReg = isPPC64 ? PPC::X1 : PPC::R1;
18469 FrameReg = isPPC64 ? PPC::FP8 : PPC::FP;
18475 FrameAddr, MachinePointerInfo());
18479#define GET_REGISTER_MATCHER
18480#include "PPCGenAsmMatcher.inc"
18484 bool IsPPC64 = Subtarget.isPPC64();
18496 if ((IsPPC64 && Reg == PPC::R2) || Reg == PPC::R0)
18502 Reg = Reg.id() - PPC::R0 + PPC::X0;
18509 if (Subtarget.is32BitELFABI())
18514 if (Subtarget.isAIXABI())
18528 return Subtarget.isGVIndirectSymbol(
G->getGlobal());
18544 case Intrinsic::ppc_atomicrmw_xchg_i128:
18545 case Intrinsic::ppc_atomicrmw_add_i128:
18546 case Intrinsic::ppc_atomicrmw_sub_i128:
18547 case Intrinsic::ppc_atomicrmw_nand_i128:
18548 case Intrinsic::ppc_atomicrmw_and_i128:
18549 case Intrinsic::ppc_atomicrmw_or_i128:
18550 case Intrinsic::ppc_atomicrmw_xor_i128:
18551 case Intrinsic::ppc_cmpxchg_i128:
18553 Info.memVT = MVT::i128;
18554 Info.ptrVal =
I.getArgOperand(0);
18556 Info.align =
Align(16);
18560 case Intrinsic::ppc_atomic_load_i128:
18562 Info.memVT = MVT::i128;
18563 Info.ptrVal =
I.getArgOperand(0);
18565 Info.align =
Align(16);
18568 case Intrinsic::ppc_atomic_store_i128:
18570 Info.memVT = MVT::i128;
18571 Info.ptrVal =
I.getArgOperand(2);
18573 Info.align =
Align(16);
18576 case Intrinsic::ppc_altivec_lvx:
18577 case Intrinsic::ppc_altivec_lvxl:
18578 case Intrinsic::ppc_altivec_lvebx:
18579 case Intrinsic::ppc_altivec_lvehx:
18580 case Intrinsic::ppc_altivec_lvewx:
18581 case Intrinsic::ppc_vsx_lxvd2x:
18582 case Intrinsic::ppc_vsx_lxvw4x:
18583 case Intrinsic::ppc_vsx_lxvd2x_be:
18584 case Intrinsic::ppc_vsx_lxvw4x_be:
18585 case Intrinsic::ppc_vsx_lxvl:
18586 case Intrinsic::ppc_vsx_lxvll: {
18589 case Intrinsic::ppc_altivec_lvebx:
18592 case Intrinsic::ppc_altivec_lvehx:
18595 case Intrinsic::ppc_altivec_lvewx:
18598 case Intrinsic::ppc_vsx_lxvd2x:
18599 case Intrinsic::ppc_vsx_lxvd2x_be:
18609 Info.ptrVal =
I.getArgOperand(0);
18612 Info.align =
Align(1);
18616 case Intrinsic::ppc_altivec_stvx:
18617 case Intrinsic::ppc_altivec_stvxl:
18618 case Intrinsic::ppc_altivec_stvebx:
18619 case Intrinsic::ppc_altivec_stvehx:
18620 case Intrinsic::ppc_altivec_stvewx:
18621 case Intrinsic::ppc_vsx_stxvd2x:
18622 case Intrinsic::ppc_vsx_stxvw4x:
18623 case Intrinsic::ppc_vsx_stxvd2x_be:
18624 case Intrinsic::ppc_vsx_stxvw4x_be:
18625 case Intrinsic::ppc_vsx_stxvl:
18626 case Intrinsic::ppc_vsx_stxvll: {
18629 case Intrinsic::ppc_altivec_stvebx:
18632 case Intrinsic::ppc_altivec_stvehx:
18635 case Intrinsic::ppc_altivec_stvewx:
18638 case Intrinsic::ppc_vsx_stxvd2x:
18639 case Intrinsic::ppc_vsx_stxvd2x_be:
18649 Info.ptrVal =
I.getArgOperand(1);
18652 Info.align =
Align(1);
18656 case Intrinsic::ppc_stdcx:
18657 case Intrinsic::ppc_stwcx:
18658 case Intrinsic::ppc_sthcx:
18659 case Intrinsic::ppc_stbcx: {
18661 auto Alignment =
Align(8);
18663 case Intrinsic::ppc_stdcx:
18666 case Intrinsic::ppc_stwcx:
18668 Alignment =
Align(4);
18670 case Intrinsic::ppc_sthcx:
18672 Alignment =
Align(2);
18674 case Intrinsic::ppc_stbcx:
18676 Alignment =
Align(1);
18681 Info.ptrVal =
I.getArgOperand(0);
18683 Info.align = Alignment;
18698 const AttributeList &FuncAttributes)
const {
18702 if (Subtarget.hasAltivec() &&
Op.size() >= 16) {
18703 if (
Op.isMemset() && Subtarget.hasVSX()) {
18708 if (TailSize > 2 && TailSize <= 4) {
18713 if (
Op.isAligned(
Align(16)) || Subtarget.hasP8Vector())
18718 if (Subtarget.isPPC64()) {
18729 assert(Ty->isIntegerTy());
18731 unsigned BitSize = Ty->getPrimitiveSizeInBits();
18732 return !(BitSize == 0 || BitSize > 64);
18740 return NumBits1 == 64 && NumBits2 == 32;
18748 return NumBits1 == 64 && NumBits2 == 32;
18755 EVT MemVT = LD->getMemoryVT();
18756 if ((MemVT == MVT::i1 || MemVT == MVT::i8 || MemVT == MVT::i16 ||
18757 (Subtarget.isPPC64() && MemVT == MVT::i32)) &&
18773 "invalid fpext types");
18775 if (DestVT == MVT::f128)
18790 unsigned *
Fast)
const {
18804 !Subtarget.allowsUnalignedFPAccess())
18808 if (Subtarget.hasVSX()) {
18809 if (VT != MVT::v2f64 && VT != MVT::v2i64 &&
18810 VT != MVT::v4f32 && VT != MVT::v4i32)
18817 if (VT == MVT::ppcf128)
18832 if (!ConstNode->getAPIntValue().isSignedIntN(64))
18840 int64_t Imm = ConstNode->getSExtValue();
18861 if (Subtarget.hasSPE() || Subtarget.useSoftFloat())
18863 switch (Ty->getScalarType()->getTypeID()) {
18868 return Subtarget.hasP9Vector();
18876 if (!
I->hasOneUse())
18880 assert(
User &&
"A single use instruction with no uses.");
18882 switch (
I->getOpcode()) {
18883 case Instruction::FMul: {
18885 if (
User->getOpcode() != Instruction::FSub &&
18886 User->getOpcode() != Instruction::FAdd)
18893 bool AllowContract =
I->getFastMathFlags().allowContract() &&
18894 User->getFastMathFlags().allowContract();
18900 case Instruction::Load: {
18913 if (
User->getOpcode() != Instruction::Store)
18933 static const MCPhysReg ScratchRegs[] = {
18934 PPC::X12, PPC::LR8, PPC::CTR8, 0
18937 return ScratchRegs;
18941 const Constant *PersonalityFn)
const {
18942 return Subtarget.isPPC64() ? PPC::X3 : PPC::R3;
18946 const Constant *PersonalityFn)
const {
18947 return Subtarget.isPPC64() ? PPC::X4 : PPC::R4;
18952 EVT VT ,
unsigned DefinedValues)
const {
18953 if (VT == MVT::v2i64)
18954 return Subtarget.hasDirectMove();
18956 if (Subtarget.hasVSX())
18983 return PPCISD::FNMSUB;
18984 case PPCISD::FNMSUB:
18990 bool LegalOps,
bool OptForSize,
18992 unsigned Depth)
const {
18996 unsigned Opc =
Op.getOpcode();
18997 EVT VT =
Op.getValueType();
19001 case PPCISD::FNMSUB:
19022 if (Flags.hasNoSignedZeros() ||
Options.NoSignedZerosFPMath) {
19026 N0Cost,
Depth + 1);
19030 N1Cost,
Depth + 1);
19032 if (NegN0 && N0Cost <= N1Cost) {
19033 Cost = std::min(N0Cost, N2Cost);
19035 }
else if (NegN1) {
19036 Cost = std::min(N1Cost, N2Cost);
19056 if (M.getStackProtectorGuard() ==
"tls" || Subtarget.isTargetLinux())
19062 bool ForCodeSize)
const {
19063 if (!VT.
isSimple() || !Subtarget.hasVSX())
19073 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
19078 APSInt IntResult(16,
false);
19083 if (IsExact && IntResult <= 15 && IntResult >= -16)
19085 return Imm.isZero();
19088 return Imm.isPosZero();
19100 unsigned Opcode =
N->getOpcode();
19120 if (Mask->getZExtValue() == OpSizeInBits - 1)
19127 DAGCombinerInfo &DCI)
const {
19128 EVT VT =
N->getValueType(0);
19131 unsigned Opc =
N->getOpcode();
19133 "Unexpected opcode.");
19140 if (EltTy != MVT::i64 && EltTy != MVT::i32)
19144 uint64_t SplatBits = 0;
19145 bool AddSplatCase =
false;
19149 AddSplatCase =
true;
19153 if (!AddSplatCase) {
19157 unsigned SplatBitSize;
19159 APInt APSplatBits, APSplatUndef;
19161 bool BVNIsConstantSplat =
19163 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
19164 if (!BVNIsConstantSplat || SplatBitSize != EltBits)
19175 if (SplatBits == (EltBits - 1)) {
19179 NewOpc = PPCISD::SHL;
19182 NewOpc = PPCISD::SRL;
19185 NewOpc = PPCISD::SRA;
19189 return DCI.DAG.getNode(NewOpc,
DL, VT, N0, SplatOnes);
19197 if (EltTy != MVT::i64 || SplatBits != 1)
19200 return DCI.DAG.getNode(
ISD::ADD, SDLoc(
N), VT, N0, N0);
19203SDValue PPCTargetLowering::combineSHL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19207 if (
N->getValueType(0).isVector())
19208 return combineVectorShift(
N, DCI);
19212 if (!Subtarget.isISA3_0() || !Subtarget.isPPC64() ||
19215 N->getValueType(0) != MVT::i64)
19230 ShiftBy = DCI.DAG.getConstant(CN1->
getZExtValue(),
DL, MVT::i32);
19236SDValue PPCTargetLowering::combineSRA(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19240 if (
N->getValueType(0).isVector())
19241 return combineVectorShift(
N, DCI);
19246SDValue PPCTargetLowering::combineSRL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19250 if (
N->getValueType(0).isVector())
19251 return combineVectorShift(
N, DCI);
19262 if (!Subtarget.isPPC64())
19268 auto isZextOfCompareWithConstant = [](
SDValue Op) {
19270 Op.getValueType() != MVT::i64)
19274 if (Cmp.getOpcode() !=
ISD::SETCC || !Cmp.hasOneUse() ||
19275 Cmp.getOperand(0).getValueType() != MVT::i64)
19279 int64_t NegConstant = 0 -
Constant->getSExtValue();
19288 bool LHSHasPattern = isZextOfCompareWithConstant(
LHS);
19289 bool RHSHasPattern = isZextOfCompareWithConstant(
RHS);
19292 if (LHSHasPattern && !RHSHasPattern)
19294 else if (!LHSHasPattern && !RHSHasPattern)
19298 EVT CarryType = Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
19301 SDValue Z = Cmp.getOperand(0);
19303 int64_t NegConstant = 0 -
Constant->getSExtValue();
19316 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
19334 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
19364 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
19367 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
19375 if (!GSDN || !ConstNode)
19403 EVT VT =
N->getValueType(0);
19404 if (!Subtarget.hasVSX())
19408 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
19420 unsigned NumOfEles =
RHS.getNumOperands();
19421 for (
unsigned i = 0; i < NumOfEles; ++i) {
19423 if (!CN || CN->getSExtValue() != 1)
19438SDValue PPCTargetLowering::combineADD(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19460 DAGCombinerInfo &DCI)
const {
19462 if (Subtarget.useCRBits()) {
19464 if (
SDValue CRTruncValue = DAGCombineTruncBoolExt(
N, DCI))
19465 return CRTruncValue;
19472 if (Op0.
getValueType() != MVT::i128 ||
N->getValueType(0) != MVT::i64)
19475 int EltToExtract = DCI.DAG.getDataLayout().isBigEndian() ? 1 : 0;
19485 EltToExtract = EltToExtract ? 0 : 1;
19495 return DCI.DAG.getNode(
19497 DCI.DAG.getTargetConstant(EltToExtract, dl, MVT::i32));
19502SDValue PPCTargetLowering::combineMUL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19503 SelectionDAG &DAG = DCI.DAG;
19506 if (!ConstOpOrElement)
19514 auto IsProfitable = [
this](
bool IsNeg,
bool IsAddOne, EVT VT) ->
bool {
19515 switch (this->Subtarget.getCPUDirective()) {
19538 return IsAddOne && IsNeg ? VT.
isVector() :
true;
19542 EVT VT =
N->getValueType(0);
19547 APInt MulAmtAbs = MulAmt.
abs();
19549 if ((MulAmtAbs - 1).isPowerOf2()) {
19553 if (!IsProfitable(IsNeg,
true, VT))
19566 }
else if ((MulAmtAbs + 1).isPowerOf2()) {
19570 if (!IsProfitable(IsNeg,
false, VT))
19591 DAGCombinerInfo &DCI)
const {
19595 SDNodeFlags
Flags =
N->getFlags();
19596 EVT VT =
N->getValueType(0);
19597 SelectionDAG &DAG = DCI.DAG;
19599 unsigned Opc =
N->getOpcode();
19601 bool LegalOps = !DCI.isBeforeLegalizeOps();
19609 if (!
Flags.hasNoSignedZeros() && !
Options.NoSignedZerosFPMath)
19625bool PPCTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
19627 if (!Subtarget.is64BitELFABI())
19637 if (!TM.Options.GuaranteedTailCallOpt &&
DisableSCO)
19642 if (!Callee ||
Callee->isVarArg())
19655bool PPCTargetLowering::
19656isMaskAndCmp0FoldingBeneficial(
const Instruction &AndI)
const {
19661 if (CI->getBitWidth() > 64)
19663 int64_t ConstVal = CI->getZExtValue();
19665 (
isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF));
19674PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(
unsigned Flags)
const {
19680 if ((Flags & FlagSet) == FlagSet)
19683 if ((Flags & FlagSet) == FlagSet)
19686 if ((Flags & FlagSet) == FlagSet)
19689 if ((Flags & FlagSet) == FlagSet)
19710 if ((FrameIndexAlign % 4) != 0)
19711 FlagSet &=
~PPC::MOF_RPlusSImm16Mult4;
19712 if ((FrameIndexAlign % 16) != 0)
19713 FlagSet &=
~PPC::MOF_RPlusSImm16Mult16;
19717 if ((FrameIndexAlign % 4) == 0)
19719 if ((FrameIndexAlign % 16) == 0)
19732 auto SetAlignFlagsForImm = [&](
uint64_t Imm) {
19733 if ((Imm & 0x3) == 0)
19735 if ((Imm & 0xf) == 0)
19741 const APInt &ConstImm = CN->getAPIntValue();
19760 const APInt &ConstImm = CN->getAPIntValue();
19770 }
else if (
RHS.getOpcode() == PPCISD::Lo && !
RHS.getConstantOperandVal(1))
19781 return (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR ||
19790unsigned PPCTargetLowering::computeMOFlags(
const SDNode *Parent,
SDValue N,
19795 if (!Subtarget.hasP9Vector())
19800 if (Subtarget.hasPrefixInstrs())
19803 if (Subtarget.hasSPE())
19812 unsigned ParentOp = Parent->
getOpcode();
19816 if ((
ID == Intrinsic::ppc_vsx_lxvp) || (
ID == Intrinsic::ppc_vsx_stxvp)) {
19817 SDValue IntrinOp = (
ID == Intrinsic::ppc_vsx_lxvp)
19829 if (LSB->isIndexed())
19835 assert(MN &&
"Parent should be a MemSDNode!");
19840 "Not expecting scalar integers larger than 16 bytes!");
19843 else if (
Size == 32)
19850 else if (
Size == 256) {
19851 assert(Subtarget.pairedVectorMemops() &&
19852 "256-bit vectors are only available when paired vector memops is "
19860 else if (MemVT == MVT::f128 || MemVT.
isVector())
19891 FlagSet &= ~PPC::MOF_NoExt;
19896 bool IsNonP1034BitConst =
19900 IsNonP1034BitConst)
19913 int16_t ForceXFormImm = 0;
19916 Disp =
N.getOperand(0);
19917 Base =
N.getOperand(1);
19928 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
19929 Disp =
N.getOperand(0);
19930 Base =
N.getOperand(1);
19935 Disp = DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
19944 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
19950 if (PartVT == MVT::f64 &&
19951 (ValVT == MVT::i32 || ValVT == MVT::i16 || ValVT == MVT::i8)) {
19953 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::f64, Val);
19960SDValue PPCTargetLowering::lowerToLibCall(
const char *LibCallName,
SDValue Op,
19964 EVT RetVT =
Op.getValueType();
19971 EVT ArgVT =
N.getValueType();
19975 Entry.IsZExt = !Entry.IsSExt;
19976 Args.push_back(Entry);
19984 (RetTy ==
F.getReturnType() ||
F.getReturnType()->isVoidTy());
19997SDValue PPCTargetLowering::lowerLibCallBasedOnType(
19998 const char *LibCallFloatName,
const char *LibCallDoubleName,
SDValue Op,
20000 if (
Op.getValueType() == MVT::f32)
20001 return lowerToLibCall(LibCallFloatName,
Op, DAG);
20003 if (
Op.getValueType() == MVT::f64)
20004 return lowerToLibCall(LibCallDoubleName,
Op, DAG);
20009bool PPCTargetLowering::isLowringToMASSFiniteSafe(
SDValue Op)
const {
20010 SDNodeFlags
Flags =
Op.getNode()->getFlags();
20011 return isLowringToMASSSafe(
Op) &&
Flags.hasNoSignedZeros() &&
20015bool PPCTargetLowering::isLowringToMASSSafe(
SDValue Op)
const {
20016 return Op.getNode()->getFlags().hasApproximateFuncs();
20019bool PPCTargetLowering::isScalarMASSConversionEnabled()
const {
20023SDValue PPCTargetLowering::lowerLibCallBase(
const char *LibCallDoubleName,
20024 const char *LibCallFloatName,
20025 const char *LibCallDoubleNameFinite,
20026 const char *LibCallFloatNameFinite,
20029 if (!isScalarMASSConversionEnabled() || !isLowringToMASSSafe(
Op))
20032 if (!isLowringToMASSFiniteSafe(
Op))
20033 return lowerLibCallBasedOnType(LibCallFloatName, LibCallDoubleName,
Op,
20036 return lowerLibCallBasedOnType(LibCallFloatNameFinite,
20037 LibCallDoubleNameFinite,
Op, DAG);
20041 return lowerLibCallBase(
"__xl_pow",
"__xl_powf",
"__xl_pow_finite",
20042 "__xl_powf_finite",
Op, DAG);
20046 return lowerLibCallBase(
"__xl_sin",
"__xl_sinf",
"__xl_sin_finite",
20047 "__xl_sinf_finite",
Op, DAG);
20051 return lowerLibCallBase(
"__xl_cos",
"__xl_cosf",
"__xl_cos_finite",
20052 "__xl_cosf_finite",
Op, DAG);
20056 return lowerLibCallBase(
"__xl_log",
"__xl_logf",
"__xl_log_finite",
20057 "__xl_logf_finite",
Op, DAG);
20061 return lowerLibCallBase(
"__xl_log10",
"__xl_log10f",
"__xl_log10_finite",
20062 "__xl_log10f_finite",
Op, DAG);
20066 return lowerLibCallBase(
"__xl_exp",
"__xl_expf",
"__xl_exp_finite",
20067 "__xl_expf_finite",
Op, DAG);
20092 unsigned Flags = computeMOFlags(Parent,
N, DAG);
20103 assert(Subtarget.isUsingPCRelativeCalls() &&
20104 "Must be using PC-Relative calls when a valid PC-Relative node is "
20134 Disp =
N.getOperand(1).getOperand(0);
20139 Base =
N.getOperand(0);
20147 EVT CNType = CN->getValueType(0);
20148 uint64_t CNImm = CN->getZExtValue();
20159 if ((CNType == MVT::i32 ||
isInt<32>(CNImm)) &&
20161 int32_t Addr = (int32_t)CNImm;
20166 uint32_t LIS = CNType == MVT::i32 ? PPC::LIS : PPC::LIS8;
20182 unsigned Opcode =
N.getOpcode();
20190 Base =
N.getOperand(0);
20209 Base = FI ?
N :
N.getOperand(1);
20210 Disp = FI ? DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20221 bool IsVarArg)
const {
20231 return Subtarget.isPPC64() && Subtarget.hasQuadwordAtomics();
20267 return Intrinsic::ppc_atomicrmw_xchg_i128;
20269 return Intrinsic::ppc_atomicrmw_add_i128;
20271 return Intrinsic::ppc_atomicrmw_sub_i128;
20273 return Intrinsic::ppc_atomicrmw_and_i128;
20275 return Intrinsic::ppc_atomicrmw_or_i128;
20277 return Intrinsic::ppc_atomicrmw_xor_i128;
20279 return Intrinsic::ppc_atomicrmw_nand_i128;
20287 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
20289 assert(ValTy->getPrimitiveSizeInBits() == 128);
20291 Value *IncrLo = Builder.CreateTrunc(Incr, Int64Ty,
"incr_lo");
20293 Builder.CreateTrunc(Builder.CreateLShr(Incr, 64), Int64Ty,
"incr_hi");
20294 Value *LoHi = Builder.CreateIntrinsic(
20296 {AlignedAddr, IncrLo, IncrHi});
20297 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
20298 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
20299 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
20300 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
20301 return Builder.CreateOr(
20302 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
20309 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
20311 assert(ValTy->getPrimitiveSizeInBits() == 128);
20315 Value *CmpLo = Builder.CreateTrunc(CmpVal, Int64Ty,
"cmp_lo");
20317 Builder.CreateTrunc(Builder.CreateLShr(CmpVal, 64), Int64Ty,
"cmp_hi");
20318 Value *NewLo = Builder.CreateTrunc(NewVal, Int64Ty,
"new_lo");
20320 Builder.CreateTrunc(Builder.CreateLShr(NewVal, 64), Int64Ty,
"new_hi");
20323 Builder.CreateCall(IntCmpXchg, {AlignedAddr, CmpLo, CmpHi, NewLo, NewHi});
20325 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
20326 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
20327 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
20328 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
20329 return Builder.CreateOr(
20330 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
20334 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!")
const TargetInstrInfo & TII
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")
Analysis containing CSE Info
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.
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].
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.
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 & 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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
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
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...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
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.
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...
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)
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
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.
FastISel * createFastISel(FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const override
createFastISel - This method returns a target-specific FastISel object, or null if the target does no...
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.
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...
virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
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...
@ 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.
@ ADD
Simple integer binary arithmetic operators.
@ 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.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ SSUBO
Same for subtraction.
@ 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).
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ 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.
@ 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) ...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ 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.
@ 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.
@ 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.
@ 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 ...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ 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)...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ 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