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");
167 unsigned OpIdx,
bool IsByte,
185 initializeAddrModeMap();
188 bool isPPC64 = Subtarget.isPPC64();
190 const MVT RegVT = Subtarget.getScalarIntVT();
198 if (!Subtarget.hasEFPU2())
215 if (!Subtarget.hasP10Vector()) {
244 if (Subtarget.isISA3_0()) {
277 if (!Subtarget.hasSPE()) {
284 if (Subtarget.useCRBits()) {
287 if (isPPC64 || Subtarget.hasFPCVT()) {
353 if (Subtarget.isISA3_0()) {
388 if (!Subtarget.hasSPE()) {
393 if (Subtarget.hasVSX()) {
398 if (Subtarget.hasFSQRT()) {
403 if (Subtarget.hasFPRND()) {
444 if (Subtarget.hasSPE()) {
454 if (Subtarget.hasSPE())
458 if (!Subtarget.hasFSQRT() && !(Subtarget.hasFRSQRTE() && Subtarget.hasFRE()))
461 if (!Subtarget.hasFSQRT() &&
462 !(Subtarget.hasFRSQRTES() && Subtarget.hasFRES()))
465 if (Subtarget.hasFCPSGN()) {
473 if (Subtarget.hasFPRND()) {
487 if (Subtarget.isISA3_1()) {
493 ((Subtarget.hasP8Vector()) && isPPC64) ?
Custom
498 if (Subtarget.isISA3_0()) {
518 if (!Subtarget.useCRBits()) {
531 if (!Subtarget.useCRBits())
534 if (Subtarget.hasFPU()) {
545 if (!Subtarget.useCRBits())
550 if (Subtarget.hasSPE()) {
582 if (Subtarget.hasDirectMove() && isPPC64) {
644 if (Subtarget.is64BitELFABI()) {
655 }
else if (Subtarget.is32BitELFABI()) {
663 if (Subtarget.is32BitELFABI())
679 if (Subtarget.isISA3_0() && isPPC64) {
707 if (Subtarget.hasSPE()) {
729 if (Subtarget.has64BitSupport()) {
744 if (Subtarget.hasLFIWAX() || isPPC64) {
750 if (Subtarget.hasSPE()) {
760 if (Subtarget.hasFPCVT()) {
761 if (Subtarget.has64BitSupport()) {
782 if (Subtarget.use64BitRegs()) {
800 if (Subtarget.has64BitSupport()) {
807 if (Subtarget.hasVSX()) {
820 if (Subtarget.hasAltivec()) {
821 for (
MVT VT : { MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
838 if (VT.getSizeInBits() <= 128 && VT.getScalarSizeInBits() <= 64) {
851 if (Subtarget.hasVSX()) {
860 if (Subtarget.hasP8Altivec() && (VT.SimpleTy != MVT::v1i128)) {
870 if (Subtarget.hasP9Altivec() && (VT.SimpleTy != MVT::v1i128))
944 if (!Subtarget.hasP8Vector()) {
986 if (Subtarget.hasAltivec())
987 for (
auto VT : {MVT::v4i32, MVT::v8i16, MVT::v16i8})
990 if (Subtarget.hasP8Altivec())
1001 if (Subtarget.hasVSX()) {
1007 if (Subtarget.hasP8Altivec())
1012 if (Subtarget.isISA3_1()) {
1058 if (Subtarget.hasVSX()) {
1061 if (Subtarget.hasP8Vector()) {
1065 if (Subtarget.hasDirectMove() && isPPC64) {
1114 if (Subtarget.hasP8Vector())
1123 if (Subtarget.hasP8Altivec()) {
1150 if (Subtarget.isISA3_1())
1253 if (Subtarget.hasP8Altivec()) {
1258 if (Subtarget.hasP9Vector()) {
1263 if (Subtarget.useCRBits()) {
1323 }
else if (Subtarget.hasVSX()) {
1348 for (
MVT VT : {MVT::f32, MVT::f64}) {
1367 if (Subtarget.hasP9Altivec()) {
1368 if (Subtarget.isISA3_1()) {
1391 if (Subtarget.hasP10Vector()) {
1406 if (Subtarget.pairedVectorMemops()) {
1411 if (Subtarget.hasMMA()) {
1412 if (Subtarget.isISAFuture()) {
1428 if (Subtarget.has64BitSupport())
1431 if (Subtarget.isISA3_1())
1449 if (Subtarget.hasAltivec()) {
1467 if (Subtarget.hasFPCVT())
1470 if (Subtarget.useCRBits())
1479 if (Subtarget.useCRBits()) {
1483 if (Subtarget.hasP8Vector())
1488 if (Subtarget.useCRBits()) {
1504 auto CPUDirective = Subtarget.getCPUDirective();
1505 switch (CPUDirective) {
1528 if (Subtarget.enableMachineScheduler())
1602void PPCTargetLowering::initializeAddrModeMap() {
1653 if (MaxAlign == MaxMaxAlign)
1656 if (MaxMaxAlign >= 32 &&
1657 VTy->getPrimitiveSizeInBits().getFixedValue() >= 256)
1658 MaxAlign =
Align(32);
1659 else if (VTy->getPrimitiveSizeInBits().getFixedValue() >= 128 &&
1661 MaxAlign =
Align(16);
1665 if (EltAlign > MaxAlign)
1666 MaxAlign = EltAlign;
1668 for (
auto *EltTy : STy->elements()) {
1671 if (EltAlign > MaxAlign)
1672 MaxAlign = EltAlign;
1673 if (MaxAlign == MaxMaxAlign)
1686 if (Subtarget.hasAltivec())
1692 return Subtarget.useSoftFloat();
1696 return Subtarget.hasSPE();
1704 Type *VectorTy,
unsigned ElemSizeInBits,
unsigned &Index)
const {
1705 if (!Subtarget.isPPC64() || !Subtarget.hasVSX())
1709 if (VTy->getScalarType()->isIntegerTy()) {
1711 if (ElemSizeInBits == 32) {
1712 Index = Subtarget.isLittleEndian() ? 2 : 1;
1715 if (ElemSizeInBits == 64) {
1716 Index = Subtarget.isLittleEndian() ? 1 : 0;
1727 return Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
1744 return CFP->getValueAPF().isZero();
1749 return CFP->getValueAPF().isZero();
1757 return Op < 0 ||
Op == Val;
1769 if (ShuffleKind == 0) {
1772 for (
unsigned i = 0; i != 16; ++i)
1775 }
else if (ShuffleKind == 2) {
1778 for (
unsigned i = 0; i != 16; ++i)
1781 }
else if (ShuffleKind == 1) {
1782 unsigned j = IsLE ? 0 : 1;
1783 for (
unsigned i = 0; i != 8; ++i)
1800 if (ShuffleKind == 0) {
1803 for (
unsigned i = 0; i != 16; i += 2)
1807 }
else if (ShuffleKind == 2) {
1810 for (
unsigned i = 0; i != 16; i += 2)
1814 }
else if (ShuffleKind == 1) {
1815 unsigned j = IsLE ? 0 : 2;
1816 for (
unsigned i = 0; i != 8; i += 2)
1837 if (!Subtarget.hasP8Vector())
1841 if (ShuffleKind == 0) {
1844 for (
unsigned i = 0; i != 16; i += 4)
1850 }
else if (ShuffleKind == 2) {
1853 for (
unsigned i = 0; i != 16; i += 4)
1859 }
else if (ShuffleKind == 1) {
1860 unsigned j = IsLE ? 0 : 4;
1861 for (
unsigned i = 0; i != 8; i += 4)
1878 unsigned LHSStart,
unsigned RHSStart) {
1879 if (
N->getValueType(0) != MVT::v16i8)
1881 assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) &&
1882 "Unsupported merge size!");
1884 for (
unsigned i = 0; i != 8/UnitSize; ++i)
1885 for (
unsigned j = 0; j != UnitSize; ++j) {
1887 LHSStart+j+i*UnitSize) ||
1889 RHSStart+j+i*UnitSize))
1904 if (ShuffleKind == 1)
1906 else if (ShuffleKind == 2)
1911 if (ShuffleKind == 1)
1913 else if (ShuffleKind == 0)
1929 if (ShuffleKind == 1)
1931 else if (ShuffleKind == 2)
1936 if (ShuffleKind == 1)
1938 else if (ShuffleKind == 0)
1988 unsigned RHSStartValue) {
1989 if (
N->getValueType(0) != MVT::v16i8)
1992 for (
unsigned i = 0; i < 2; ++i)
1993 for (
unsigned j = 0; j < 4; ++j)
1995 i*RHSStartValue+j+IndexOffset) ||
1997 i*RHSStartValue+j+IndexOffset+8))
2019 unsigned indexOffset = CheckEven ? 4 : 0;
2020 if (ShuffleKind == 1)
2022 else if (ShuffleKind == 2)
2028 unsigned indexOffset = CheckEven ? 0 : 4;
2029 if (ShuffleKind == 1)
2031 else if (ShuffleKind == 0)
2047 if (
N->getValueType(0) != MVT::v16i8)
2054 for (i = 0; i != 16 && SVOp->
getMaskElt(i) < 0; ++i)
2057 if (i == 16)
return -1;
2062 if (ShiftAmt < i)
return -1;
2067 if ((ShuffleKind == 0 && !isLE) || (ShuffleKind == 2 && isLE)) {
2069 for (++i; i != 16; ++i)
2072 }
else if (ShuffleKind == 1) {
2074 for (++i; i != 16; ++i)
2081 ShiftAmt = 16 - ShiftAmt;
2090 EVT VT =
N->getValueType(0);
2091 if (VT == MVT::v2i64 || VT == MVT::v2f64)
2092 return EltSize == 8 &&
N->getMaskElt(0) ==
N->getMaskElt(1);
2095 EltSize <= 8 &&
"Can only handle 1,2,4,8 byte element sizes");
2099 if (
N->getMaskElt(0) % EltSize != 0)
2104 unsigned ElementBase =
N->getMaskElt(0);
2107 if (ElementBase >= 16)
2112 for (
unsigned i = 1; i != EltSize; ++i)
2113 if (
N->getMaskElt(i) < 0 ||
N->getMaskElt(i) != (
int)(i+ElementBase))
2116 for (
unsigned i = EltSize, e = 16; i != e; i += EltSize) {
2118 if (
N->getMaskElt(i) < 0) {
2119 for (
unsigned j = 1; j != EltSize; ++j)
2120 if (
N->getMaskElt(i + j) >= 0)
2123 for (
unsigned j = 0; j != EltSize; ++j)
2124 if (
N->getMaskElt(i + j) !=
N->getMaskElt(j))
2141 assert((Width == 2 || Width == 4 || Width == 8 || Width == 16) &&
2142 "Unexpected element width.");
2143 assert((StepLen == 1 || StepLen == -1) &&
"Unexpected element width.");
2145 unsigned NumOfElem = 16 / Width;
2146 unsigned MaskVal[16];
2147 for (
unsigned i = 0; i < NumOfElem; ++i) {
2148 MaskVal[0] =
N->getMaskElt(i * Width);
2149 if ((StepLen == 1) && (MaskVal[0] % Width)) {
2151 }
else if ((StepLen == -1) && ((MaskVal[0] + 1) % Width)) {
2155 for (
unsigned int j = 1; j < Width; ++j) {
2156 MaskVal[j] =
N->getMaskElt(i * Width + j);
2157 if (MaskVal[j] != MaskVal[j-1] + StepLen) {
2167 unsigned &InsertAtByte,
bool &Swap,
bool IsLE) {
2172 unsigned M0 =
N->getMaskElt(0) / 4;
2173 unsigned M1 =
N->getMaskElt(4) / 4;
2174 unsigned M2 =
N->getMaskElt(8) / 4;
2175 unsigned M3 =
N->getMaskElt(12) / 4;
2176 unsigned LittleEndianShifts[] = { 2, 1, 0, 3 };
2177 unsigned BigEndianShifts[] = { 3, 0, 1, 2 };
2182 if ((
M0 > 3 &&
M1 == 1 && M2 == 2 && M3 == 3) ||
2183 (
M0 < 4 &&
M1 == 5 && M2 == 6 && M3 == 7)) {
2184 ShiftElts = IsLE ? LittleEndianShifts[
M0 & 0x3] : BigEndianShifts[
M0 & 0x3];
2185 InsertAtByte = IsLE ? 12 : 0;
2190 if ((
M1 > 3 &&
M0 == 0 && M2 == 2 && M3 == 3) ||
2191 (
M1 < 4 &&
M0 == 4 && M2 == 6 && M3 == 7)) {
2192 ShiftElts = IsLE ? LittleEndianShifts[
M1 & 0x3] : BigEndianShifts[
M1 & 0x3];
2193 InsertAtByte = IsLE ? 8 : 4;
2198 if ((M2 > 3 &&
M0 == 0 &&
M1 == 1 && M3 == 3) ||
2199 (M2 < 4 &&
M0 == 4 &&
M1 == 5 && M3 == 7)) {
2200 ShiftElts = IsLE ? LittleEndianShifts[M2 & 0x3] : BigEndianShifts[M2 & 0x3];
2201 InsertAtByte = IsLE ? 4 : 8;
2206 if ((M3 > 3 &&
M0 == 0 &&
M1 == 1 && M2 == 2) ||
2207 (M3 < 4 &&
M0 == 4 &&
M1 == 5 && M2 == 6)) {
2208 ShiftElts = IsLE ? LittleEndianShifts[M3 & 0x3] : BigEndianShifts[M3 & 0x3];
2209 InsertAtByte = IsLE ? 0 : 12;
2216 if (
N->getOperand(1).isUndef()) {
2219 unsigned XXINSERTWSrcElem = IsLE ? 2 : 1;
2220 if (
M0 == XXINSERTWSrcElem &&
M1 == 1 && M2 == 2 && M3 == 3) {
2221 InsertAtByte = IsLE ? 12 : 0;
2224 if (
M0 == 0 &&
M1 == XXINSERTWSrcElem && M2 == 2 && M3 == 3) {
2225 InsertAtByte = IsLE ? 8 : 4;
2228 if (
M0 == 0 &&
M1 == 1 && M2 == XXINSERTWSrcElem && M3 == 3) {
2229 InsertAtByte = IsLE ? 4 : 8;
2232 if (
M0 == 0 &&
M1 == 1 && M2 == 2 && M3 == XXINSERTWSrcElem) {
2233 InsertAtByte = IsLE ? 0 : 12;
2242 bool &Swap,
bool IsLE) {
2243 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2249 unsigned M0 =
N->getMaskElt(0) / 4;
2250 unsigned M1 =
N->getMaskElt(4) / 4;
2251 unsigned M2 =
N->getMaskElt(8) / 4;
2252 unsigned M3 =
N->getMaskElt(12) / 4;
2256 if (
N->getOperand(1).isUndef()) {
2257 assert(
M0 < 4 &&
"Indexing into an undef vector?");
2258 if (
M1 != (
M0 + 1) % 4 || M2 != (
M1 + 1) % 4 || M3 != (M2 + 1) % 4)
2261 ShiftElts = IsLE ? (4 -
M0) % 4 :
M0;
2267 if (
M1 != (
M0 + 1) % 8 || M2 != (
M1 + 1) % 8 || M3 != (M2 + 1) % 8)
2271 if (
M0 == 0 ||
M0 == 7 ||
M0 == 6 ||
M0 == 5) {
2276 ShiftElts = (8 -
M0) % 8;
2277 }
else if (
M0 == 4 ||
M0 == 3 ||
M0 == 2 ||
M0 == 1) {
2282 ShiftElts = (4 -
M0) % 4;
2287 if (
M0 == 0 ||
M0 == 1 ||
M0 == 2 ||
M0 == 3) {
2292 }
else if (
M0 == 4 ||
M0 == 5 ||
M0 == 6 ||
M0 == 7) {
2304 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2309 for (
int i = 0; i < 16; i += Width)
2310 if (
N->getMaskElt(i) != i + Width - 1)
2341 bool &Swap,
bool IsLE) {
2342 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2348 unsigned M0 =
N->getMaskElt(0) / 8;
2349 unsigned M1 =
N->getMaskElt(8) / 8;
2350 assert(((
M0 |
M1) < 4) &&
"A mask element out of bounds?");
2354 if (
N->getOperand(1).isUndef()) {
2355 if ((
M0 |
M1) < 2) {
2356 DM = IsLE ? (((
~M1) & 1) << 1) + ((~
M0) & 1) : (
M0 << 1) + (
M1 & 1);
2364 if (
M0 > 1 &&
M1 < 2) {
2374 DM = (((
~M1) & 1) << 1) + ((~
M0) & 1);
2379 }
else if (
M0 > 1 &&
M1 < 2) {
2387 DM = (
M0 << 1) + (
M1 & 1);
2402 if (VT == MVT::v2i64 || VT == MVT::v2f64)
2407 return (16 / EltSize) - 1 - (SVOp->
getMaskElt(0) / EltSize);
2423 unsigned EltSize = 16/
N->getNumOperands();
2424 if (EltSize < ByteSize) {
2425 unsigned Multiple = ByteSize/EltSize;
2427 assert(Multiple > 1 && Multiple <= 4 &&
"How can this happen?");
2430 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
2431 if (
N->getOperand(i).isUndef())
continue;
2435 if (!UniquedVals[i&(Multiple-1)].
getNode())
2436 UniquedVals[i&(Multiple-1)] =
N->getOperand(i);
2437 else if (UniquedVals[i&(Multiple-1)] !=
N->getOperand(i))
2447 bool LeadingZero =
true;
2448 bool LeadingOnes =
true;
2449 for (
unsigned i = 0; i != Multiple-1; ++i) {
2450 if (!UniquedVals[i].
getNode())
continue;
2457 if (!UniquedVals[Multiple-1].
getNode())
2464 if (!UniquedVals[Multiple-1].
getNode())
2475 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
2476 if (
N->getOperand(i).isUndef())
continue;
2478 OpVal =
N->getOperand(i);
2479 else if (OpVal !=
N->getOperand(i))
2485 unsigned ValSizeInBytes = EltSize;
2488 Value = CN->getZExtValue();
2490 assert(CN->getValueType(0) == MVT::f32 &&
"Only one legal FP vector type!");
2497 if (ValSizeInBytes < ByteSize)
return SDValue();
2508 if (MaskVal == 0)
return SDValue();
2528 Imm = (int16_t)
N->getAsZExtVal();
2529 if (
N->getValueType(0) == MVT::i32)
2530 return Imm == (int32_t)
N->getAsZExtVal();
2532 return Imm == (int64_t)
N->getAsZExtVal();
2550 return (~(LHSKnown.
Zero | RHSKnown.
Zero) == 0);
2558 for (
SDNode *U :
N->users()) {
2560 if (Memop->getMemoryVT() == MVT::f64) {
2561 Base =
N.getOperand(0);
2562 Index =
N.getOperand(1);
2605 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm)))
2607 if (
N.getOperand(1).getOpcode() == PPCISD::Lo)
2610 Base =
N.getOperand(0);
2611 Index =
N.getOperand(1);
2613 }
else if (
N.getOpcode() ==
ISD::OR) {
2615 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm)))
2627 if (~(LHSKnown.
Zero | RHSKnown.
Zero) == 0) {
2628 Base =
N.getOperand(0);
2629 Index =
N.getOperand(1);
2699 (!EncodingAlignment ||
isAligned(*EncodingAlignment, imm))) {
2705 Base =
N.getOperand(0);
2708 }
else if (
N.getOperand(1).getOpcode() == PPCISD::Lo) {
2710 assert(!
N.getOperand(1).getConstantOperandVal(1) &&
2711 "Cannot handle constant offsets yet!");
2712 Disp =
N.getOperand(1).getOperand(0);
2717 Base =
N.getOperand(0);
2720 }
else if (
N.getOpcode() ==
ISD::OR) {
2723 (!EncodingAlignment ||
isAligned(*EncodingAlignment, imm))) {
2737 Base =
N.getOperand(0);
2750 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm))) {
2753 CN->getValueType(0));
2758 if ((CN->getValueType(0) == MVT::i32 ||
2759 (int64_t)CN->getZExtValue() == (
int)CN->getZExtValue()) &&
2760 (!EncodingAlignment ||
2761 isAligned(*EncodingAlignment, CN->getZExtValue()))) {
2762 int Addr = (int)CN->getZExtValue();
2769 unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8;
2790 if (
N.getValueType() != MVT::i64)
2803 Base =
N.getOperand(0);
2819 Base =
N.getOperand(0);
2852 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
2853 Base =
N.getOperand(0);
2854 Index =
N.getOperand(1);
2876 if (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR)
2897 EVT MemVT = LD->getMemoryVT();
2904 if (!ST.hasP8Vector())
2909 if (!ST.hasP9Vector())
2921 if (
Use.getResNo() == 0 &&
2923 Use.
getUser()->getOpcode() != PPCISD::SCALAR_TO_VECTOR_PERMUTED)
2943 Ptr = LD->getBasePtr();
2944 VT = LD->getMemoryVT();
2945 Alignment = LD->getAlign();
2947 Ptr = ST->getBasePtr();
2948 VT = ST->getMemoryVT();
2949 Alignment = ST->getAlign();
2988 if (VT != MVT::i64) {
2993 if (Alignment <
Align(4))
3003 if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 &&
3020 unsigned &HiOpFlags,
unsigned &LoOpFlags,
3062 EVT VT = Subtarget.getScalarIntVT();
3064 : Subtarget.isAIXABI()
3069 PPCISD::TOC_ENTRY, dl, DAG.
getVTList(VT, MVT::Other),
Ops, VT,
3076 EVT PtrVT =
Op.getValueType();
3082 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3083 if (Subtarget.isUsingPCRelativeCalls()) {
3088 return DAG.
getNode(PPCISD::MAT_PCREL_ADDR,
DL, Ty, ConstPool);
3092 return getTOCEntry(DAG, SDLoc(CP), GA);
3095 unsigned MOHiFlag, MOLoFlag;
3099 if (IsPIC && Subtarget.isSVR4ABI()) {
3102 return getTOCEntry(DAG, SDLoc(CP), GA);
3125 if (Subtarget.isPPC64() || Subtarget.isAIXABI())
3132 if (!Subtarget.isPPC64() || Subtarget.isAIXABI())
3149 if (!Subtarget.isPPC64() || Subtarget.isAIXABI())
3162 EVT PtrVT =
Op.getValueType();
3180 return getTOCEntry(DAG,
SDLoc(JT), GA);
3183 unsigned MOHiFlag, MOLoFlag;
3187 if (IsPIC && Subtarget.isSVR4ABI()) {
3190 return getTOCEntry(DAG, SDLoc(GA), GA);
3200 EVT PtrVT =
Op.getValueType();
3205 if (Subtarget.isUsingPCRelativeCalls()) {
3216 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3219 return getTOCEntry(DAG, SDLoc(BASDN), GA);
3228 unsigned MOHiFlag, MOLoFlag;
3238 if (Subtarget.isAIXABI())
3239 return LowerGlobalTLSAddressAIX(
Op, DAG);
3241 return LowerGlobalTLSAddressLinux(
Op, DAG);
3263 if (
I.getOpcode() == Instruction::Call)
3265 if (
Function *CF = CI->getCalledFunction())
3266 if (CF->isDeclaration() &&
3267 CF->getIntrinsicID() == Intrinsic::threadlocal_address)
3275 unsigned TLSGVCnt = TLSGV.
size();
3285 <<
" function is using the TLS-IE model for TLS-LD access.\n");
3298 const GlobalValue *GV = GA->
getGlobal();
3300 bool Is64Bit = Subtarget.isPPC64();
3304 if (Subtarget.hasAIXShLibTLSModelOpt())
3314 bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS();
3315 bool HasAIXSmallTLSGlobalAttr =
false;
3318 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3322 if (GVar->hasAttribute(
"aix-small-tls"))
3323 HasAIXSmallTLSGlobalAttr =
true;
3342 if ((HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr) &&
3343 IsTLSLocalExecModel) {
3348 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA, TLSReg);
3358 TLSReg = DAG.
getNode(PPCISD::GET_TPOINTER, dl, PtrVT);
3363 if (HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr)
3365 "currently only supported on AIX (64-bit mode).");
3367 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
3371 bool HasAIXSmallLocalDynamicTLS = Subtarget.hasAIXSmallLocalDynamicTLS();
3375 if (!Is64Bit && HasAIXSmallLocalDynamicTLS)
3377 "currently only supported on AIX (64-bit mode).");
3385 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3388 GlobalVariable *TLSGV =
3392 assert(TLSGV &&
"Not able to create GV for _$TLSML.");
3395 SDValue ModuleHandleTOC = getTOCEntry(DAG, dl, ModuleHandleTGA);
3397 DAG.
getNode(PPCISD::TLSLD_AIX, dl, PtrVT, ModuleHandleTOC);
3406 if (HasAIXSmallLocalDynamicTLS) {
3411 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA,
3415 return DAG.
getNode(
ISD::ADD, dl, PtrVT, ModuleHandle, VariableOffset);
3428 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3429 SDValue RegionHandle = getTOCEntry(DAG, dl, RegionHandleTGA);
3430 return DAG.
getNode(PPCISD::TLSGD_AIX, dl, PtrVT, VariableOffset,
3445 const GlobalValue *GV = GA->
getGlobal();
3447 bool is64bit = Subtarget.isPPC64();
3455 if (Subtarget.isUsingPCRelativeCalls()) {
3460 DAG.
getNode(PPCISD::TLS_LOCAL_EXEC_MAT_ADDR, dl, PtrVT, TGA);
3461 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, MatAddr);
3472 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, TGALo,
Hi);
3476 bool IsPCRel = Subtarget.isUsingPCRelativeCalls();
3483 SDValue MatPCRel = DAG.
getNode(PPCISD::MAT_PCREL_ADDR, dl, PtrVT, TGA);
3485 MachinePointerInfo());
3492 DAG.
getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl, PtrVT, GOTReg, TGA);
3494 if (!TM.isPositionIndependent())
3495 GOTPtr = DAG.
getNode(PPCISD::PPC32_GOT, dl, PtrVT);
3501 TPOffset = DAG.
getNode(PPCISD::LD_GOT_TPREL_L, dl, PtrVT, TGA, GOTPtr);
3507 if (Subtarget.isUsingPCRelativeCalls()) {
3510 return DAG.
getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3518 GOTPtr = DAG.
getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT,
3526 return DAG.
getNode(PPCISD::ADDI_TLSGD_L_ADDR, dl, PtrVT,
3531 if (Subtarget.isUsingPCRelativeCalls()) {
3535 DAG.
getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3536 return DAG.
getNode(PPCISD::PADDI_DTPREL, dl, PtrVT, MatPCRel, TGA);
3544 GOTPtr = DAG.
getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT,
3553 PtrVT, GOTPtr, TGA, TGA);
3555 PtrVT, TLSAddr, TGA);
3556 return DAG.
getNode(PPCISD::ADDI_DTPREL_L, dl, PtrVT, DtvOffsetHi, TGA);
3564 EVT PtrVT =
Op.getValueType();
3567 const GlobalValue *GV = GSDN->
getGlobal();
3571 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3572 if (Subtarget.isUsingPCRelativeCalls()) {
3579 MachinePointerInfo());
3584 return DAG.
getNode(PPCISD::MAT_PCREL_ADDR,
DL, Ty, GA);
3589 return getTOCEntry(DAG,
DL, GA);
3592 unsigned MOHiFlag, MOLoFlag;
3596 if (IsPIC && Subtarget.isSVR4ABI()) {
3600 return getTOCEntry(DAG,
DL, GA);
3612 bool IsStrict =
Op->isStrictFPOpcode();
3613 const SDNodeFlags
Flags =
Op.getNode()->getFlags();
3619 EVT LHSVT =
LHS.getValueType();
3623 if (LHSVT == MVT::f128 ||
3624 (Subtarget.hasSPE() && (LHSVT == MVT::f32 || LHSVT == MVT::f64) &&
3625 (!
Flags.hasNoNaNs() || !
Flags.hasNoInfs()))) {
3626 assert(!Subtarget.hasP9Vector() &&
3627 "SETCC for f128 is already legal under Power9!");
3636 }
else if (LHSVT == MVT::f32 || LHSVT == MVT::f64) {
3640 assert(!IsStrict &&
"Don't know how to handle STRICT_FSETCC!");
3642 if (
Op.getValueType() == MVT::v2i64) {
3645 if (
LHS.getValueType() == MVT::v2i64) {
3653 int ShuffV[] = {1, 0, 3, 2};
3658 dl, MVT::v4i32, Shuff, SetCC32));
3675 if (
C->isAllOnes() ||
C->isZero())
3685 EVT VT =
Op.getValueType();
3693 const SDNodeFlags
Flags =
Op->getFlags();
3699 EVT LHSVT =
LHS.getValueType();
3702 assert(Subtarget.hasSPE() &&
"LowerBR_CC used only for targets with SPE");
3704 if ((LHSVT == MVT::f32 || LHSVT == MVT::f64) &&
Flags.hasNoNaNs() &&
3722 SDNode *
Node =
Op.getNode();
3723 EVT VT =
Node->getValueType(0);
3730 assert(!Subtarget.isPPC64() &&
"LowerVAARG is PPC32 only");
3734 VAListPtr, MachinePointerInfo(SV), MVT::i8);
3737 if (VT == MVT::i64) {
3756 FprPtr, MachinePointerInfo(SV), MVT::i8);
3767 DAG.
getLoad(MVT::i32, dl, InChain, OverflowAreaPtr, MachinePointerInfo());
3768 InChain = OverflowArea.
getValue(1);
3771 DAG.
getLoad(MVT::i32, dl, InChain, RegSaveAreaPtr, MachinePointerInfo());
3801 MachinePointerInfo(SV), MVT::i8);
3814 InChain = DAG.
getTruncStore(InChain, dl, OverflowArea, OverflowAreaPtr,
3815 MachinePointerInfo(), MVT::i32);
3817 return DAG.
getLoad(VT, dl, InChain, Result, MachinePointerInfo());
3821 assert(!Subtarget.isPPC64() &&
"LowerVACOPY is PPC32 only");
3827 Align(8),
false,
true,
nullptr, std::nullopt,
3828 MachinePointerInfo(), MachinePointerInfo());
3833 return Op.getOperand(0);
3838 PPCFunctionInfo &MFI = *MF.
getInfo<PPCFunctionInfo>();
3842 "Expecting Inline ASM node.");
3852 if (
Op.getOperand(
NumOps - 1).getValueType() == MVT::Glue)
3857 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(i));
3858 unsigned NumVals =
Flags.getNumOperandRegisters();
3861 switch (
Flags.getKind()) {
3872 for (; NumVals; --NumVals, ++i) {
3874 if (
Reg != PPC::LR &&
Reg != PPC::LR8)
3897 if (Subtarget.isAIXABI()) {
3901 uint64_t
PointerSize = Subtarget.isPPC64() ? 8 : 4;
3902 MaybeAlign PointerAlign(PointerSize);
3903 auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
3906 : MachineMemOperand::MONone;
3913 const Value *TrampolineAddr =
3923 DAG.
getLoad(PtrVT, dl, Chain, FPtr, MachinePointerInfo(Func, 0),
3924 PointerAlign, MMOFlags);
3926 OutChains[0] = DAG.
getStore(EPLoadChain, dl, LoadEntryPoint, Trmp,
3927 MachinePointerInfo(TrampolineAddr, 0));
3931 SDValue TOCFromDescriptorPtr =
3933 SDValue TOCReg = DAG.
getLoad(PtrVT, dl, Chain, TOCFromDescriptorPtr,
3934 MachinePointerInfo(Func, TOCPointerOffset),
3935 PointerAlign, MMOFlags);
3936 SDValue TrampolineTOCPointer =
3940 DAG.
getStore(TOCLoadChain, dl, TOCReg, TrampolineTOCPointer,
3941 MachinePointerInfo(TrampolineAddr, TOCPointerOffset));
3947 DAG.
getStore(Chain, dl, Nest, EnvPointer,
3948 MachinePointerInfo(TrampolineAddr, EnvPointerOffset));
3955 bool isPPC64 = (PtrVT == MVT::i64);
3962 DAG.
getConstant(isPPC64 ? 48 : 40, dl, Subtarget.getScalarIntVT()),
3968 TargetLowering::CallLoweringInfo CLI(DAG);
3969 CLI.setDebugLoc(dl).setChain(Chain).setLibCallee(
3973 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3974 return CallResult.second;
3979 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
3984 if (Subtarget.isPPC64() || Subtarget.isAIXABI()) {
3989 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
3990 MachinePointerInfo(SV));
4024 uint64_t FrameOffset = PtrVT.getSizeInBits()/8;
4027 uint64_t StackOffset = PtrVT.getSizeInBits()/8 - 1;
4030 uint64_t FPROffset = 1;
4038 MachinePointerInfo(SV), MVT::i8);
4039 uint64_t nextOffset = FPROffset;
4046 MachinePointerInfo(SV, nextOffset), MVT::i8);
4047 nextOffset += StackOffset;
4048 nextPtr = DAG.
getNode(
ISD::ADD, dl, PtrVT, nextPtr, ConstStackOffset);
4051 SDValue thirdStore = DAG.
getStore(secondStore, dl, StackOffsetFI, nextPtr,
4052 MachinePointerInfo(SV, nextOffset));
4053 nextOffset += FrameOffset;
4054 nextPtr = DAG.
getNode(
ISD::ADD, dl, PtrVT, nextPtr, ConstFrameOffset);
4057 return DAG.
getStore(thirdStore, dl, FR, nextPtr,
4058 MachinePointerInfo(SV, nextOffset));
4063static const MCPhysReg FPR[] = {PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5,
4064 PPC::F6, PPC::F7, PPC::F8, PPC::F9, PPC::F10,
4065 PPC::F11, PPC::F12, PPC::F13};
4070 unsigned PtrByteSize) {
4072 if (Flags.isByVal())
4073 ArgSize = Flags.getByValSize();
4077 if (!Flags.isInConsecutiveRegs())
4078 ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4087 unsigned PtrByteSize) {
4088 Align Alignment(PtrByteSize);
4091 if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 ||
4092 ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 ||
4093 ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 ||
4094 ArgVT == MVT::v1i128 || ArgVT == MVT::f128)
4095 Alignment =
Align(16);
4098 if (Flags.isByVal()) {
4099 auto BVAlign = Flags.getNonZeroByValAlign();
4100 if (BVAlign > PtrByteSize) {
4101 if (BVAlign.value() % PtrByteSize != 0)
4103 "ByVal alignment is not a multiple of the pointer size");
4105 Alignment = BVAlign;
4110 if (Flags.isInConsecutiveRegs()) {
4114 if (Flags.isSplit() && OrigVT != MVT::ppcf128)
4128 unsigned PtrByteSize,
unsigned LinkageSize,
4129 unsigned ParamAreaSize,
unsigned &ArgOffset,
4130 unsigned &AvailableFPRs,
4131 unsigned &AvailableVRs) {
4132 bool UseMemory =
false;
4137 ArgOffset =
alignTo(ArgOffset, Alignment);
4140 if (ArgOffset >= LinkageSize + ParamAreaSize)
4145 if (Flags.isInConsecutiveRegsLast())
4146 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4149 if (ArgOffset > LinkageSize + ParamAreaSize)
4154 if (!Flags.isByVal()) {
4155 if (ArgVT == MVT::f32 || ArgVT == MVT::f64)
4156 if (AvailableFPRs > 0) {
4160 if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 ||
4161 ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 ||
4162 ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 ||
4163 ArgVT == MVT::v1i128 || ArgVT == MVT::f128)
4164 if (AvailableVRs > 0) {
4176 unsigned NumBytes) {
4180SDValue PPCTargetLowering::LowerFormalArguments(
4184 if (Subtarget.isAIXABI())
4185 return LowerFormalArguments_AIX(Chain, CallConv, isVarArg, Ins, dl, DAG,
4187 if (Subtarget.is64BitELFABI())
4188 return LowerFormalArguments_64SVR4(Chain, CallConv, isVarArg, Ins, dl, DAG,
4190 assert(Subtarget.is32BitELFABI());
4191 return LowerFormalArguments_32SVR4(Chain, CallConv, isVarArg, Ins, dl, DAG,
4195SDValue PPCTargetLowering::LowerFormalArguments_32SVR4(
4231 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
4237 const Align PtrAlign(4);
4245 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
4246 CCInfo.AllocateStack(LinkageSize, PtrAlign);
4249 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4250 CCValAssign &VA = ArgLocs[i];
4262 RC = &PPC::GPRCRegClass;
4265 if (Subtarget.hasP8Vector())
4266 RC = &PPC::VSSRCRegClass;
4267 else if (Subtarget.hasSPE())
4268 RC = &PPC::GPRCRegClass;
4270 RC = &PPC::F4RCRegClass;
4273 if (Subtarget.hasVSX())
4274 RC = &PPC::VSFRCRegClass;
4275 else if (Subtarget.hasSPE())
4277 RC = &PPC::GPRCRegClass;
4279 RC = &PPC::F8RCRegClass;
4284 RC = &PPC::VRRCRegClass;
4287 RC = &PPC::VRRCRegClass;
4291 RC = &PPC::VRRCRegClass;
4298 if (VA.
getLocVT() == MVT::f64 && Subtarget.hasSPE()) {
4299 assert(i + 1 < e &&
"No second half of double precision argument");
4304 if (!Subtarget.isLittleEndian())
4306 ArgValue = DAG.
getNode(PPCISD::BUILD_SPE64, dl, MVT::f64, ArgValueLo,
4311 ValVT == MVT::i1 ? MVT::i32 : ValVT);
4312 if (ValVT == MVT::i1)
4327 ArgOffset += ArgSize - ObjSize;
4345 CCByValInfo.AllocateStack(CCInfo.getStackSize(), PtrAlign);
4350 unsigned MinReservedArea = CCByValInfo.getStackSize();
4351 MinReservedArea = std::max(MinReservedArea, LinkageSize);
4367 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
4368 PPC::R7, PPC::R8, PPC::R9, PPC::R10,
4370 const unsigned NumGPArgRegs = std::size(GPArgRegs);
4373 PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
4376 unsigned NumFPArgRegs = std::size(FPArgRegs);
4385 int Depth = NumGPArgRegs * PtrVT.getSizeInBits()/8 +
4386 NumFPArgRegs * MVT(MVT::f64).getSizeInBits()/8;
4389 PtrVT.getSizeInBits() / 8, CCInfo.getStackSize(),
true));
4402 VReg = MF.
addLiveIn(GPArgReg, &PPC::GPRCRegClass);
4417 for (
unsigned FPRIndex = 0; FPRIndex != NumFPArgRegs; ++FPRIndex) {
4421 VReg = MF.
addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass);
4434 if (!MemOps.
empty())
4445 const SDLoc &dl)
const {
4449 else if (
Flags.isZExt())
4456SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
4462 bool isELFv2ABI = Subtarget.isELFv2ABI();
4463 bool isLittleEndian = Subtarget.isLittleEndian();
4466 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
4469 "fastcc not supported on varargs functions");
4475 unsigned PtrByteSize = 8;
4476 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
4479 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
4480 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
4483 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
4484 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
4487 const unsigned Num_GPR_Regs = std::size(GPR);
4489 const unsigned Num_VR_Regs = std::size(VR);
4497 bool HasParameterArea = !isELFv2ABI || isVarArg;
4498 unsigned ParamAreaSize = Num_GPR_Regs * PtrByteSize;
4499 unsigned NumBytes = LinkageSize;
4500 unsigned AvailableFPRs = Num_FPR_Regs;
4501 unsigned AvailableVRs = Num_VR_Regs;
4502 for (
const ISD::InputArg &In : Ins) {
4503 if (
In.Flags.isNest())
4507 LinkageSize, ParamAreaSize, NumBytes,
4508 AvailableFPRs, AvailableVRs))
4509 HasParameterArea =
true;
4516 unsigned ArgOffset = LinkageSize;
4517 unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
4520 unsigned CurArgIdx = 0;
4521 for (
unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
4523 bool needsLoad =
false;
4524 EVT ObjectVT = Ins[ArgNo].VT;
4525 EVT OrigVT = Ins[ArgNo].ArgVT;
4527 unsigned ArgSize = ObjSize;
4528 ISD::ArgFlagsTy
Flags = Ins[ArgNo].Flags;
4529 if (Ins[ArgNo].isOrigArg()) {
4530 std::advance(FuncArg, Ins[ArgNo].getOrigArgIndex() - CurArgIdx);
4531 CurArgIdx = Ins[ArgNo].getOrigArgIndex();
4536 unsigned CurArgOffset;
4538 auto ComputeArgOffset = [&]() {
4542 ArgOffset =
alignTo(ArgOffset, Alignment);
4543 CurArgOffset = ArgOffset;
4550 GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
4551 GPR_idx = std::min(GPR_idx, Num_GPR_Regs);
4556 if (
Flags.isByVal()) {
4557 assert(Ins[ArgNo].isOrigArg() &&
"Byval arguments cannot be implicit");
4563 ObjSize =
Flags.getByValSize();
4564 ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4586 if (HasParameterArea ||
4587 ArgSize + ArgOffset > LinkageSize + Num_GPR_Regs * PtrByteSize)
4594 if (ObjSize < PtrByteSize) {
4598 if (!isLittleEndian) {
4604 if (GPR_idx != Num_GPR_Regs) {
4611 MachinePointerInfo(&*FuncArg), ObjType);
4616 ArgOffset += PtrByteSize;
4625 for (
unsigned j = 0;
j < ArgSize;
j += PtrByteSize) {
4626 if (GPR_idx == Num_GPR_Regs)
4637 unsigned StoreSizeInBits = std::min(PtrByteSize, (ObjSize - j)) * 8;
4641 MachinePointerInfo(&*FuncArg, j), ObjType);
4645 ArgOffset += ArgSize;
4654 if (
Flags.isNest()) {
4659 if (ObjectVT == MVT::i32 || ObjectVT == MVT::i1)
4660 ArgVal = extendArgForPPC64(Flags, ObjectVT, DAG, ArgVal, dl);
4668 if (GPR_idx != Num_GPR_Regs) {
4673 if (ObjectVT == MVT::i32 || ObjectVT == MVT::i1)
4676 ArgVal = extendArgForPPC64(Flags, ObjectVT, DAG, ArgVal, dl);
4682 ArgSize = PtrByteSize;
4693 if (FPR_idx != Num_FPR_Regs) {
4696 if (ObjectVT == MVT::f32)
4698 Subtarget.hasP8Vector()
4699 ? &PPC::VSSRCRegClass
4700 : &PPC::F4RCRegClass);
4703 ? &PPC::VSFRCRegClass
4704 : &PPC::F8RCRegClass);
4719 if (ObjectVT == MVT::f32) {
4720 if ((ArgOffset % PtrByteSize) == (isLittleEndian ? 4 : 0))
4738 ArgSize =
Flags.isInConsecutiveRegs() ? ObjSize : PtrByteSize;
4739 ArgOffset += ArgSize;
4740 if (
Flags.isInConsecutiveRegsLast())
4741 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4755 if (VR_idx != Num_VR_Regs) {
4772 if (ObjSize < ArgSize && !isLittleEndian)
4773 CurArgOffset += ArgSize - ObjSize;
4776 ArgVal = DAG.
getLoad(ObjectVT, dl, Chain, FIN, MachinePointerInfo());
4783 unsigned MinReservedArea;
4784 if (HasParameterArea)
4785 MinReservedArea = std::max(ArgOffset, LinkageSize + 8 * PtrByteSize);
4787 MinReservedArea = LinkageSize;
4804 int Depth = ArgOffset;
4813 for (GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
4814 GPR_idx < Num_GPR_Regs; ++GPR_idx) {
4826 if (!MemOps.
empty())
4835 unsigned ParamSize) {
4837 if (!isTailCall)
return 0;
4841 int SPDiff = (int)CallerMinReservedArea - (
int)ParamSize;
4843 if (SPDiff < FI->getTailCallSPDelta())
4859 "PC Relative callers do not have a TOC and cannot share a TOC Base");
4918 Caller->hasComdat() || CalleeGV->
getSection() != Caller->getSection())
4921 if (
F->getSectionPrefix() != Caller->getSectionPrefix())
4933 const unsigned PtrByteSize = 8;
4937 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
4938 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
4941 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
4942 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
4945 const unsigned NumGPRs = std::size(GPR);
4946 const unsigned NumFPRs = 13;
4947 const unsigned NumVRs = std::size(VR);
4948 const unsigned ParamAreaSize = NumGPRs * PtrByteSize;
4950 unsigned NumBytes = LinkageSize;
4951 unsigned AvailableFPRs = NumFPRs;
4952 unsigned AvailableVRs = NumVRs;
4955 if (Param.Flags.isNest())
continue;
4958 LinkageSize, ParamAreaSize, NumBytes,
4959 AvailableFPRs, AvailableVRs))
4970 auto CalleeArgEnd = CB.
arg_end();
4973 for (; CalleeArgIter != CalleeArgEnd; ++CalleeArgIter, ++CallerArgIter) {
4974 const Value* CalleeArg = *CalleeArgIter;
4975 const Value* CallerArg = &(*CallerArgIter);
4976 if (CalleeArg == CallerArg)
5002 if (!isTailCallableCC(CallerCC) || !isTailCallableCC(CalleeCC))
5012bool PPCTargetLowering::IsEligibleForTailCallOptimization_64SVR4(
5017 bool isCalleeExternalSymbol)
const {
5020 if (
DisableSCO && !TailCallOpt)
return false;
5023 if (isVarArg)
return false;
5030 if (
any_of(Ins, [](
const ISD::InputArg &IA) {
return IA.Flags.isByVal(); }))
5066 if (!Subtarget.isUsingPCRelativeCalls() &&
5071 if (!Subtarget.isUsingPCRelativeCalls() &&
5099bool PPCTargetLowering::IsEligibleForTailCallOptimization(
5112 if (
any_of(Ins, [](
const ISD::InputArg &IA) {
return IA.Flags.isByVal(); }))
5133 if (!
C)
return nullptr;
5135 int Addr =
C->getZExtValue();
5136 if ((Addr & 3) != 0 ||
5142 (
int)
C->getZExtValue() >> 2,
SDLoc(
Op),
5149struct TailCallArgumentInfo {
5154 TailCallArgumentInfo() =
default;
5164 for (
unsigned i = 0, e = TailCallArgs.
size(); i != e; ++i) {
5165 SDValue Arg = TailCallArgs[i].Arg;
5166 SDValue FIN = TailCallArgs[i].FrameIdxOp;
5167 int FI = TailCallArgs[i].FrameIdx;
5170 Chain, dl, Arg, FIN,
5179 int SPDiff,
const SDLoc &dl) {
5185 int SlotSize = Subtarget.isPPC64() ? 8 : 4;
5186 int NewRetAddrLoc = SPDiff + FL->getReturnSaveOffset();
5188 NewRetAddrLoc,
true);
5191 Chain = DAG.
getStore(Chain, dl, OldRetAddr, NewRetAddrFrIdx,
5201 int SPDiff,
unsigned ArgOffset,
5203 int Offset = ArgOffset + SPDiff;
5206 EVT VT = IsPPC64 ? MVT::i64 : MVT::i32;
5208 TailCallArgumentInfo Info;
5210 Info.FrameIdxOp = FIN;
5218SDValue PPCTargetLowering::EmitTailCallLoadFPAndRetAddr(
5223 LROpOut = getReturnAddrFrameIndex(DAG);
5224 LROpOut = DAG.
getLoad(Subtarget.getScalarIntVT(), dl, Chain, LROpOut,
5225 MachinePointerInfo());
5241 Align Alignment = Flags.getNonZeroByValAlign();
5243 Chain, dl, Dst, Src, SizeNode, Alignment, Alignment,
false,
false,
5251 SDValue PtrOff,
int SPDiff,
unsigned ArgOffset,
bool isPPC64,
5275 const SDLoc &dl,
int SPDiff,
unsigned NumBytes,
SDValue LROp,
5285 if (!MemOpChains2.
empty())
5309SDValue PPCTargetLowering::LowerCallResult(
5317 CCRetInfo.AnalyzeCallResult(
5323 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
5324 CCValAssign &VA = RVLocs[i];
5329 if (Subtarget.hasSPE() && VA.
getLocVT() == MVT::f64) {
5339 if (!Subtarget.isLittleEndian())
5341 Val = DAG.
getNode(PPCISD::BUILD_SPE64, dl, MVT::f64,
Lo,
Hi);
5407 bool IsStrictFPCall =
false) {
5409 return PPCISD::TC_RETURN;
5411 unsigned RetOpc = 0;
5422 if (Subtarget.usePointerGlueHelper())
5423 RetOpc = PPCISD::BL_LOAD_TOC;
5429 RetOpc = PPCISD::CALL_NOTOC;
5444 RetOpc = PPCISD::CALL;
5445 if (IsStrictFPCall) {
5449 case PPCISD::BCTRL_LOAD_TOC:
5450 RetOpc = PPCISD::BCTRL_LOAD_TOC_RM;
5453 RetOpc = PPCISD::BCTRL_RM;
5455 case PPCISD::BL_LOAD_TOC:
5456 RetOpc = PPCISD::BL_LOAD_TOC_RM;
5458 case PPCISD::CALL_NOTOC:
5459 RetOpc = PPCISD::CALL_NOTOC_RM;
5462 RetOpc = PPCISD::CALL_RM;
5464 case PPCISD::CALL_NOP:
5465 RetOpc = PPCISD::CALL_NOP_RM;
5479 auto isLocalCallee = [&]() {
5495 const auto getAIXFuncEntryPointSymbolSDNode = [&](
const GlobalValue *GV) {
5511 return getAIXFuncEntryPointSymbolSDNode(GV);
5518 const char *SymName = S->getSymbol();
5525 return getAIXFuncEntryPointSymbolSDNode(
F);
5531 const auto getExternalFunctionEntryPointSymbol = [&](
StringRef SymName) {
5539 SymName = getExternalFunctionEntryPointSymbol(SymName)->getName().data();
5546 assert(Callee.getNode() &&
"What no callee?");
5552 "Expected a CALLSEQ_STARTSDNode.");
5569 SDValue MTCTROps[] = {Chain, Callee, Glue};
5570 EVT ReturnTypes[] = {MVT::Other, MVT::Glue};
5571 Chain = DAG.
getNode(PPCISD::MTCTR, dl, ReturnTypes,
5611 auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
5630 SDValue LoadFuncPtr = DAG.
getLoad(RegVT, dl, LDChain, Callee, MPI,
5631 Alignment, MMOFlags);
5638 DAG.
getLoad(RegVT, dl, LDChain, AddTOC,
5645 DAG.
getLoad(RegVT, dl, LDChain, AddPtr,
5657 "Nest parameter is not supported on AIX.");
5672 const SDLoc &dl,
bool hasNest,
5682 Chain = MoveToPhysicalReg.
getValue(0);
5683 Glue = MoveToPhysicalReg.
getValue(1);
5690 SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass,
5693 const bool IsPPC64 = Subtarget.isPPC64();
5698 Ops.push_back(Chain);
5702 Ops.push_back(Callee);
5703 else if (Subtarget.usePointerGlueHelper()) {
5704 Ops.push_back(Callee);
5727 Ops.push_back(AddTOC);
5738 Ops.push_back(DAG.
getRegister(IsPPC64 ? PPC::CTR8 : PPC::CTR, RegVT));
5747 for (
const auto &[
Reg,
N] : RegsToPass)
5765 assert(Mask &&
"Missing call preserved mask for calling convention");
5770 Ops.push_back(Glue);
5773SDValue PPCTargetLowering::FinishCall(
5780 if ((Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls()) ||
5781 Subtarget.isAIXABI())
5788 if (!CFlags.IsIndirect)
5790 else if (Subtarget.usesFunctionDescriptors()) {
5791 if (Subtarget.usePointerGlueHelper()) {
5793 CFlags.HasNest, Subtarget);
5799 dl, CFlags.HasNest, Subtarget);
5811 if (CFlags.IsTailCall) {
5819 (CFlags.IsIndirect && Subtarget.isUsingPCRelativeCalls())) &&
5820 "Expecting a global address, external symbol, absolute value, "
5821 "register or an indirect tail call when PC Relative calls are "
5824 assert(CallOpc == PPCISD::TC_RETURN &&
5825 "Unexpected call opcode for a tail call.");
5832 std::array<EVT, 2> ReturnTypes = {{MVT::Other, MVT::Glue}};
5833 Chain = DAG.
getNode(CallOpc, dl, ReturnTypes,
Ops);
5845 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, BytesCalleePops, Glue, dl);
5848 return LowerCallResult(Chain, Glue, CFlags.CallConv, CFlags.IsVarArg, Ins, dl,
5868 return isEligibleForTCO(CalleeGV, CalleeCC, CallerCC, CB,
5869 CalleeFunc->
isVarArg(), Outs, Ins, CallerFunc,
5873bool PPCTargetLowering::isEligibleForTCO(
5878 bool isCalleeExternalSymbol)
const {
5882 if (Subtarget.
isSVR4ABI() && Subtarget.isPPC64())
5883 return IsEligibleForTailCallOptimization_64SVR4(
5884 CalleeGV, CalleeCC, CallerCC, CB, isVarArg, Outs, Ins, CallerFunc,
5885 isCalleeExternalSymbol);
5887 return IsEligibleForTailCallOptimization(CalleeGV, CalleeCC, CallerCC,
5915 isEligibleForTCO(GV, CallConv, CallerCC, CB, isVarArg, Outs, Ins,
5930 "Callee should be an llvm::Function object.");
5933 <<
"\nTCO callee: ");
5940 "site marked musttail");
5947 Callee = LowerGlobalAddress(Callee, DAG);
5950 CallConv, isTailCall, isVarArg, isPatchPoint,
5953 Subtarget.is64BitELFABI() &&
5957 if (Subtarget.isAIXABI())
5958 return LowerCall_AIX(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5961 assert(Subtarget.isSVR4ABI());
5962 if (Subtarget.isPPC64())
5963 return LowerCall_64SVR4(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5965 return LowerCall_32SVR4(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5969SDValue PPCTargetLowering::LowerCall_32SVR4(
5980 const bool IsVarArg = CFlags.IsVarArg;
5981 const bool IsTailCall = CFlags.IsTailCall;
5987 const Align PtrAlign(4);
5998 MF.
getInfo<PPCFunctionInfo>()->setHasFastCall();
6006 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.
getContext());
6009 CCInfo.AllocateStack(Subtarget.getFrameLowering()->getLinkageSize(),
6016 unsigned NumArgs = Outs.
size();
6018 for (
unsigned i = 0; i != NumArgs; ++i) {
6019 MVT ArgVT = Outs[i].VT;
6020 ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
6025 Outs[i].OrigTy, CCInfo);
6028 ArgFlags, Outs[i].OrigTy, CCInfo);
6033 errs() <<
"Call operand #" << i <<
" has unhandled type "
6046 CCState CCByValInfo(CallConv, IsVarArg, MF, ByValArgLocs, *DAG.
getContext());
6049 CCByValInfo.AllocateStack(CCInfo.getStackSize(), PtrAlign);
6056 unsigned NumBytes = CCByValInfo.getStackSize();
6070 Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, dl);
6081 bool seenFloatArg =
false;
6086 for (
unsigned i = 0, RealArgIdx = 0, j = 0, e = ArgLocs.
size();
6088 ++i, ++RealArgIdx) {
6089 CCValAssign &VA = ArgLocs[i];
6090 SDValue Arg = OutVals[RealArgIdx];
6091 ISD::ArgFlagsTy
Flags = Outs[RealArgIdx].Flags;
6093 if (
Flags.isByVal()) {
6098 assert((j < ByValArgLocs.
size()) &&
"Index out of bounds!");
6099 CCValAssign &ByValVA = ByValArgLocs[
j++];
6121 Chain = CallSeqStart = NewCallSeqStart;
6140 if (Subtarget.hasSPE() && Arg.
getValueType() == MVT::f64) {
6141 bool IsLE = Subtarget.isLittleEndian();
6142 SDValue SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
6145 SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
6147 RegsToPass.
push_back(std::make_pair(ArgLocs[++i].getLocReg(),
6162 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
6171 if (!MemOpChains.
empty())
6177 for (
const auto &[
Reg,
N] : RegsToPass) {
6185 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
6188 Chain = DAG.
getNode(seenFloatArg ? PPCISD::CR6SET : PPCISD::CR6UNSET, dl,
6198 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
6199 Callee, SPDiff, NumBytes, Ins, InVals, CB);
6204SDValue PPCTargetLowering::createMemcpyOutsideCallSeq(
6216 return NewCallSeqStart;
6219SDValue PPCTargetLowering::LowerCall_64SVR4(
6226 bool isELFv2ABI = Subtarget.isELFv2ABI();
6227 bool isLittleEndian = Subtarget.isLittleEndian();
6229 bool IsSibCall =
false;
6233 unsigned PtrByteSize = 8;
6246 MF.
getInfo<PPCFunctionInfo>()->setHasFastCall();
6248 assert(!(IsFastCall && CFlags.IsVarArg) &&
6249 "fastcc not supported on varargs functions");
6255 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
6256 unsigned NumBytes = LinkageSize;
6257 unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
6260 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6261 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
6264 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
6265 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
6268 const unsigned NumGPRs = std::size(GPR);
6270 const unsigned NumVRs = std::size(VR);
6276 bool HasParameterArea = !isELFv2ABI || CFlags.IsVarArg || IsFastCall;
6277 if (!HasParameterArea) {
6278 unsigned ParamAreaSize = NumGPRs * PtrByteSize;
6279 unsigned AvailableFPRs = NumFPRs;
6280 unsigned AvailableVRs = NumVRs;
6281 unsigned NumBytesTmp = NumBytes;
6282 for (
unsigned i = 0; i !=
NumOps; ++i) {
6283 if (Outs[i].
Flags.isNest())
continue;
6285 PtrByteSize, LinkageSize, ParamAreaSize,
6286 NumBytesTmp, AvailableFPRs, AvailableVRs))
6287 HasParameterArea =
true;
6293 unsigned NumGPRsUsed = 0, NumFPRsUsed = 0, NumVRsUsed = 0;
6298 HasParameterArea =
false;
6301 for (
unsigned i = 0; i !=
NumOps; ++i) {
6302 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
6303 EVT ArgVT = Outs[i].VT;
6304 EVT OrigVT = Outs[i].ArgVT;
6310 if (
Flags.isByVal()) {
6311 NumGPRsUsed += (
Flags.getByValSize()+7)/8;
6312 if (NumGPRsUsed > NumGPRs)
6313 HasParameterArea =
true;
6320 if (++NumGPRsUsed <= NumGPRs)
6330 if (++NumVRsUsed <= NumVRs)
6334 if (++NumVRsUsed <= NumVRs)
6339 if (++NumFPRsUsed <= NumFPRs)
6343 HasParameterArea =
true;
6350 NumBytes =
alignTo(NumBytes, Alignement);
6353 if (
Flags.isInConsecutiveRegsLast())
6354 NumBytes = ((NumBytes + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
6357 unsigned NumBytesActuallyUsed = NumBytes;
6367 if (HasParameterArea)
6368 NumBytes = std::max(NumBytes, LinkageSize + 8 * PtrByteSize);
6370 NumBytes = LinkageSize;
6385 if (CFlags.IsTailCall)
6397 Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, dl);
6408 unsigned ArgOffset = LinkageSize;
6414 for (
unsigned i = 0; i !=
NumOps; ++i) {
6416 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
6417 EVT ArgVT = Outs[i].VT;
6418 EVT OrigVT = Outs[i].ArgVT;
6427 auto ComputePtrOff = [&]() {
6431 ArgOffset =
alignTo(ArgOffset, Alignment);
6442 GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
6443 GPR_idx = std::min(GPR_idx, NumGPRs);
6450 Arg = DAG.
getNode(ExtOp, dl, MVT::i64, Arg);
6456 if (
Flags.isByVal()) {
6474 EVT VT = (
Size==1) ? MVT::i8 : ((
Size==2) ? MVT::i16 : MVT::i32);
6475 if (GPR_idx != NumGPRs) {
6477 MachinePointerInfo(), VT);
6481 ArgOffset += PtrByteSize;
6486 if (GPR_idx == NumGPRs &&
Size < 8) {
6488 if (!isLittleEndian) {
6493 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, AddPtr,
6496 ArgOffset += PtrByteSize;
6505 if ((NumGPRs - GPR_idx) * PtrByteSize <
Size)
6506 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, PtrOff,
6511 if (
Size < 8 && GPR_idx != NumGPRs) {
6521 if (!isLittleEndian) {
6525 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, AddPtr,
6531 DAG.
getLoad(PtrVT, dl, Chain, PtrOff, MachinePointerInfo());
6536 ArgOffset += PtrByteSize;
6542 for (
unsigned j=0;
j<
Size;
j+=PtrByteSize) {
6545 if (GPR_idx != NumGPRs) {
6546 unsigned LoadSizeInBits = std::min(PtrByteSize, (
Size - j)) * 8;
6549 MachinePointerInfo(), ObjType);
6553 ArgOffset += PtrByteSize;
6555 ArgOffset += ((
Size -
j + PtrByteSize-1)/PtrByteSize)*PtrByteSize;
6567 if (
Flags.isNest()) {
6569 RegsToPass.
push_back(std::make_pair(PPC::X11, Arg));
6576 if (GPR_idx != NumGPRs) {
6577 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Arg));
6582 assert(HasParameterArea &&
6583 "Parameter area must exist to pass an argument in memory.");
6585 true, CFlags.IsTailCall,
false, MemOpChains,
6586 TailCallArguments, dl);
6588 ArgOffset += PtrByteSize;
6591 ArgOffset += PtrByteSize;
6604 bool NeedGPROrStack = CFlags.IsVarArg || FPR_idx == NumFPRs;
6605 bool NeededLoad =
false;
6608 if (FPR_idx != NumFPRs)
6609 RegsToPass.
push_back(std::make_pair(
FPR[FPR_idx++], Arg));
6612 if (!NeedGPROrStack)
6614 else if (GPR_idx != NumGPRs && !IsFastCall) {
6628 }
else if (!
Flags.isInConsecutiveRegs()) {
6634 }
else if (ArgOffset % PtrByteSize != 0) {
6638 if (!isLittleEndian)
6643 }
else if (
Flags.isInConsecutiveRegsLast()) {
6646 if (!isLittleEndian)
6656 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], ArgVal));
6664 !isLittleEndian && !
Flags.isInConsecutiveRegs()) {
6669 assert(HasParameterArea &&
6670 "Parameter area must exist to pass an argument in memory.");
6672 true, CFlags.IsTailCall,
false, MemOpChains,
6673 TailCallArguments, dl);
6680 if (!IsFastCall || NeededLoad) {
6682 Flags.isInConsecutiveRegs()) ? 4 : 8;
6683 if (
Flags.isInConsecutiveRegsLast())
6684 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
6704 if (CFlags.IsVarArg) {
6705 assert(HasParameterArea &&
6706 "Parameter area must exist if we have a varargs call.");
6710 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
6712 if (VR_idx != NumVRs) {
6714 DAG.
getLoad(MVT::v4f32, dl,
Store, PtrOff, MachinePointerInfo());
6719 for (
unsigned i=0; i<16; i+=PtrByteSize) {
6720 if (GPR_idx == NumGPRs)
6725 DAG.
getLoad(PtrVT, dl,
Store, Ix, MachinePointerInfo());
6733 if (VR_idx != NumVRs) {
6734 RegsToPass.
push_back(std::make_pair(VR[VR_idx++], Arg));
6739 assert(HasParameterArea &&
6740 "Parameter area must exist to pass an argument in memory.");
6742 true, CFlags.IsTailCall,
true, MemOpChains,
6743 TailCallArguments, dl);
6754 assert((!HasParameterArea || NumBytesActuallyUsed == ArgOffset) &&
6755 "mismatch in size of parameter area");
6756 (void)NumBytesActuallyUsed;
6758 if (!MemOpChains.
empty())
6764 if (CFlags.IsIndirect) {
6768 assert(!CFlags.IsTailCall &&
"Indirect tails calls not supported");
6773 unsigned TOCSaveOffset = Subtarget.getFrameLowering()->getTOCSaveOffset();
6783 if (isELFv2ABI && !CFlags.IsPatchPoint)
6784 RegsToPass.
push_back(std::make_pair((
unsigned)PPC::X12, Callee));
6790 for (
const auto &[
Reg,
N] : RegsToPass) {
6795 if (CFlags.IsTailCall && !IsSibCall)
6799 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
6800 Callee, SPDiff, NumBytes, Ins, InVals, CB);
6807 "Required alignment greater than stack alignment.");
6827 return RequiredAlign <= 8;
6832 return RequiredAlign <= 4;
6840 State.getMachineFunction().getSubtarget());
6841 const bool IsPPC64 = Subtarget.isPPC64();
6842 const unsigned PtrSize = IsPPC64 ? 8 : 4;
6843 const Align PtrAlign(PtrSize);
6844 const Align StackAlign(16);
6847 if (ValVT == MVT::f128)
6851 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
6852 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
6854 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6855 PPC::X7, PPC::X8, PPC::X9, PPC::X10};
6858 PPC::V2, PPC::V3, PPC::V4, PPC::V5,
6859 PPC::V6, PPC::V7, PPC::V8, PPC::V9,
6860 PPC::V10, PPC::V11, PPC::V12, PPC::V13};
6865 MCRegister EnvReg = State.AllocateReg(IsPPC64 ? PPC::X11 : PPC::R11);
6874 if (ByValAlign > StackAlign)
6876 "16 are not supported.");
6879 const Align ObjAlign = ByValAlign > PtrAlign ? ByValAlign : PtrAlign;
6883 if (ByValSize == 0) {
6885 State.getStackSize(), RegVT, LocInfo));
6890 unsigned NextReg = State.getFirstUnallocated(GPRs);
6891 while (NextReg != GPRs.
size() &&
6896 State.AllocateStack(PtrSize, PtrAlign);
6897 assert(
Reg &&
"Alocating register unexpectedly failed.");
6899 NextReg = State.getFirstUnallocated(GPRs);
6902 const unsigned StackSize =
alignTo(ByValSize, ObjAlign);
6903 unsigned Offset = State.AllocateStack(StackSize, ObjAlign);
6923 assert(IsPPC64 &&
"PPC32 should have split i64 values.");
6927 const unsigned Offset = State.AllocateStack(PtrSize, PtrAlign);
6946 State.AllocateStack(IsPPC64 ? 8 : StoreSize,
Align(4));
6952 for (
unsigned I = 0;
I < StoreSize;
I += PtrSize) {
6954 assert(FReg &&
"An FPR should be available when a GPR is reserved.");
6955 if (State.isVarArg()) {
6987 const unsigned VecSize = 16;
6988 const Align VecAlign(VecSize);
6990 if (!State.isVarArg()) {
6993 if (
MCRegister VReg = State.AllocateReg(VR)) {
7000 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7005 unsigned NextRegIndex = State.getFirstUnallocated(GPRs);
7008 while (NextRegIndex != GPRs.
size() &&
7012 State.AllocateStack(PtrSize, PtrAlign);
7013 assert(
Reg &&
"Allocating register unexpectedly failed.");
7015 NextRegIndex = State.getFirstUnallocated(GPRs);
7023 if (
MCRegister VReg = State.AllocateReg(VR)) {
7026 for (
unsigned I = 0;
I != VecSize;
I += PtrSize)
7027 State.AllocateReg(GPRs);
7028 State.AllocateStack(VecSize, VecAlign);
7032 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7038 if (NextRegIndex == GPRs.
size()) {
7039 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7047 if (GPRs[NextRegIndex] == PPC::R9) {
7048 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7052 const MCRegister FirstReg = State.AllocateReg(PPC::R9);
7053 const MCRegister SecondReg = State.AllocateReg(PPC::R10);
7054 assert(FirstReg && SecondReg &&
7055 "Allocating R9 or R10 unexpectedly failed.");
7066 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7069 for (
unsigned I = 0;
I != VecSize;
I += PtrSize) {
7071 assert(
Reg &&
"Failed to allocated register for vararg vector argument");
7086 assert((IsPPC64 || SVT != MVT::i64) &&
7087 "i64 should have been split for 32-bit codegen.");
7095 return IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
7097 return HasP8Vector ? &PPC::VSSRCRegClass : &PPC::F4RCRegClass;
7099 return HasVSX ? &PPC::VSFRCRegClass : &PPC::F8RCRegClass;
7107 return &PPC::VRRCRegClass;
7120 else if (Flags.isZExt())
7132 "Reg must be a valid argument register!");
7133 return LASize + 4 * (
Reg - PPC::R3);
7138 "Reg must be a valid argument register!");
7139 return LASize + 8 * (
Reg - PPC::X3);
7185SDValue PPCTargetLowering::LowerFormalArguments_AIX(
7192 "Unexpected calling convention!");
7200 const PPCSubtarget &Subtarget = DAG.
getSubtarget<PPCSubtarget>();
7202 const bool IsPPC64 = Subtarget.isPPC64();
7203 const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
7209 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
7210 CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.
getContext());
7214 const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
7215 CCInfo.AllocateStack(LinkageSize,
Align(PtrByteSize));
7216 uint64_t SaveStackPos = CCInfo.getStackSize();
7218 CCInfo.AnalyzeFormalArguments(Ins,
CC_AIX);
7222 for (
size_t I = 0, End = ArgLocs.
size();
I != End; ) {
7223 CCValAssign &VA = ArgLocs[
I++];
7228 EVT ArgVT = Ins[VA.
getValNo()].ArgVT;
7229 bool ArgSignExt = Ins[VA.
getValNo()].Flags.isSExt();
7241 LocVT.
SimpleTy, IsPPC64, Subtarget.hasP8Vector(), Subtarget.hasVSX());
7243 MVT SaveVT = RegClass == &PPC::G8RCRegClass ? MVT::i64 : LocVT;
7249 MachinePointerInfo(),
Align(PtrByteSize));
7255 unsigned StoreSize =
7257 SaveStackPos =
alignTo(SaveStackPos + StoreSize, PtrByteSize);
7260 auto HandleMemLoc = [&]() {
7263 assert((ValSize <= LocSize) &&
7264 "Object size is larger than size of MemLoc");
7267 if (LocSize > ValSize)
7268 CurArgOffset += LocSize - ValSize;
7270 const bool IsImmutable =
7276 DAG.
getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo());
7310 assert(isVarArg &&
"Only use custom memloc for vararg.");
7313 const unsigned OriginalValNo = VA.
getValNo();
7314 (void)OriginalValNo;
7316 auto HandleCustomVecRegLoc = [&]() {
7317 assert(
I != End && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7318 "Missing custom RegLoc.");
7321 "Unexpected Val type for custom RegLoc.");
7323 "ValNo mismatch between custom MemLoc and RegLoc.");
7327 Subtarget.hasVSX()));
7334 HandleCustomVecRegLoc();
7335 HandleCustomVecRegLoc();
7339 if (
I != End && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom()) {
7341 "Only 2 custom RegLocs expected for 64-bit codegen.");
7342 HandleCustomVecRegLoc();
7343 HandleCustomVecRegLoc();
7387 const unsigned Size =
7399 if (
Flags.isByVal()) {
7403 const PPCFrameLowering *FL = Subtarget.getFrameLowering();
7405 const unsigned StackSize =
alignTo(
Flags.getByValSize(), PtrByteSize);
7414 IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
7416 auto HandleRegLoc = [&, RegClass, LocVT](
const MCPhysReg PhysReg,
7429 CopyFrom.
getValue(1), dl, CopyFrom,
7439 for (;
Offset != StackSize && ArgLocs[
I].isRegLoc();
7442 "RegLocs should be for ByVal argument.");
7444 const CCValAssign RL = ArgLocs[
I++];
7449 if (
Offset != StackSize) {
7451 "Expected MemLoc for remaining bytes.");
7452 assert(ArgLocs[
I].isMemLoc() &&
"Expected MemLoc for remaining bytes.");
7466 Subtarget.hasVSX()));
7483 const unsigned MinParameterSaveArea = 8 * PtrByteSize;
7485 unsigned CallerReservedArea = std::max<unsigned>(
7486 CCInfo.getStackSize(), LinkageSize + MinParameterSaveArea);
7492 CallerReservedArea =
7497 int VAListIndex = 0;
7501 if (CCInfo.getStackSize() < (LinkageSize + MinParameterSaveArea)) {
7502 unsigned FixedStackSize =
7503 LinkageSize + MinParameterSaveArea - CCInfo.getStackSize();
7519 static const MCPhysReg GPR_32[] = {PPC::R3, PPC::R4, PPC::R5, PPC::R6,
7520 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
7522 static const MCPhysReg GPR_64[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6,
7523 PPC::X7, PPC::X8, PPC::X9, PPC::X10};
7524 const unsigned NumGPArgRegs = std::size(IsPPC64 ? GPR_64 : GPR_32);
7530 GPRIndex = (CCInfo.getStackSize() - LinkageSize) / PtrByteSize,
7532 GPRIndex < NumGPArgRegs; ++GPRIndex,
Offset += PtrByteSize) {
7535 IsPPC64 ? MF.
addLiveIn(GPR_64[GPRIndex], &PPC::G8RCRegClass)
7536 : MF.
addLiveIn(GPR_32[GPRIndex], &PPC::GPRCRegClass);
7539 MachinePointerInfo MPI =
7549 if (!MemOps.
empty())
7555SDValue PPCTargetLowering::LowerCall_AIX(
7568 "Unexpected calling convention!");
7570 if (CFlags.IsPatchPoint)
7573 const PPCSubtarget &Subtarget = DAG.
getSubtarget<PPCSubtarget>();
7577 CCState CCInfo(CFlags.CallConv, CFlags.IsVarArg, MF, ArgLocs,
7584 const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
7585 const bool IsPPC64 = Subtarget.isPPC64();
7587 const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
7588 CCInfo.AllocateStack(LinkageSize,
Align(PtrByteSize));
7589 CCInfo.AnalyzeCallOperands(Outs,
CC_AIX);
7597 const unsigned MinParameterSaveAreaSize = 8 * PtrByteSize;
7598 const unsigned NumBytes = std::max<unsigned>(
7599 LinkageSize + MinParameterSaveAreaSize, CCInfo.getStackSize());
7615 for (
unsigned I = 0,
E = ArgLocs.
size();
I !=
E;) {
7616 const unsigned ValNo = ArgLocs[
I].getValNo();
7618 ISD::ArgFlagsTy
Flags = Outs[ValNo].Flags;
7620 if (
Flags.isByVal()) {
7621 const unsigned ByValSize =
Flags.getByValSize();
7629 auto GetLoad = [&](EVT VT,
unsigned LoadOffset) {
7635 MachinePointerInfo(), VT);
7638 unsigned LoadOffset = 0;
7641 while (LoadOffset + PtrByteSize <= ByValSize && ArgLocs[
I].isRegLoc()) {
7644 LoadOffset += PtrByteSize;
7645 const CCValAssign &ByValVA = ArgLocs[
I++];
7647 "Unexpected location for pass-by-value argument.");
7651 if (LoadOffset == ByValSize)
7655 assert(ArgLocs[
I].getValNo() == ValNo &&
7656 "Expected additional location for by-value argument.");
7658 if (ArgLocs[
I].isMemLoc()) {
7659 assert(LoadOffset < ByValSize &&
"Unexpected memloc for by-val arg.");
7660 const CCValAssign &ByValVA = ArgLocs[
I++];
7661 ISD::ArgFlagsTy MemcpyFlags =
Flags;
7664 Chain = CallSeqStart = createMemcpyOutsideCallSeq(
7670 CallSeqStart, MemcpyFlags, DAG, dl);
7679 const unsigned ResidueBytes = ByValSize % PtrByteSize;
7680 assert(ResidueBytes != 0 && LoadOffset + PtrByteSize > ByValSize &&
7681 "Unexpected register residue for by-value argument.");
7683 for (
unsigned Bytes = 0; Bytes != ResidueBytes;) {
7687 : ((
N == 2) ? MVT::i16 : (
N == 4 ? MVT::i32 : MVT::i64));
7697 "Unexpected load emitted during handling of pass-by-value "
7705 ResidueVal = ResidueVal ? DAG.
getNode(
ISD::OR, dl, PtrVT, ResidueVal,
7710 const CCValAssign &ByValVA = ArgLocs[
I++];
7715 CCValAssign &VA = ArgLocs[
I++];
7740 assert(CFlags.IsVarArg &&
"Custom MemLocs only used for Vector args.");
7746 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
7748 const unsigned OriginalValNo = VA.
getValNo();
7750 unsigned LoadOffset = 0;
7751 auto HandleCustomVecRegLoc = [&]() {
7752 assert(
I !=
E &&
"Unexpected end of CCvalAssigns.");
7753 assert(ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7754 "Expected custom RegLoc.");
7755 CCValAssign RegVA = ArgLocs[
I++];
7757 "Custom MemLoc ValNo and custom RegLoc ValNo must match.");
7763 LoadOffset += PtrByteSize;
7769 HandleCustomVecRegLoc();
7770 HandleCustomVecRegLoc();
7772 if (
I !=
E && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7773 ArgLocs[
I].getValNo() == OriginalValNo) {
7775 "Only 2 custom RegLocs expected for 64-bit codegen.");
7776 HandleCustomVecRegLoc();
7777 HandleCustomVecRegLoc();
7788 DAG.
getStore(Chain, dl, Arg, PtrOff,
7790 Subtarget.getFrameLowering()->getStackAlign()));
7797 "Unexpected register handling for calling convention.");
7803 "Custom register handling only expected for VarArg.");
7808 if (Arg.getValueType().getStoreSize() == LocVT.
getStoreSize())
7812 else if (Arg.getValueType().getFixedSizeInBits() <
7820 assert(Arg.getValueType() == MVT::f64 && CFlags.IsVarArg && !IsPPC64 &&
7821 "Unexpected custom register for argument!");
7822 CCValAssign &GPR1 = VA;
7831 CCValAssign &PeekArg = ArgLocs[
I];
7834 CCValAssign &GPR2 = ArgLocs[
I++];
7842 if (!MemOpChains.
empty())
7847 if (CFlags.IsIndirect && !Subtarget.usePointerGlueHelper()) {
7848 assert(!CFlags.IsTailCall &&
"Indirect tail-calls not supported.");
7849 const MCRegister TOCBaseReg = Subtarget.getTOCPointerRegister();
7850 const MCRegister StackPtrReg = Subtarget.getStackPointerRegister();
7851 const MVT PtrVT = Subtarget.getScalarIntVT();
7852 const unsigned TOCSaveOffset =
7853 Subtarget.getFrameLowering()->getTOCSaveOffset();
7868 for (
auto Reg : RegsToPass) {
7873 const int SPDiff = 0;
7874 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
7875 Callee, SPDiff, NumBytes, Ins, InVals, CB);
7883 const Type *RetTy)
const {
7885 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
7886 return CCInfo.CheckReturn(
7901 CCInfo.AnalyzeReturn(Outs,
7910 for (
unsigned i = 0, RealResIdx = 0; i != RVLocs.
size(); ++i, ++RealResIdx) {
7911 CCValAssign &VA = RVLocs[i];
7914 SDValue Arg = OutVals[RealResIdx];
7929 if (Subtarget.hasSPE() && VA.
getLocVT() == MVT::f64) {
7930 bool isLittleEndian = Subtarget.isLittleEndian();
7933 DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
7937 SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
7952 RetOps.push_back(Glue);
7954 return DAG.
getNode(PPCISD::RET_GLUE, dl, MVT::Other, RetOps);
7958PPCTargetLowering::LowerGET_DYNAMIC_AREA_OFFSET(
SDValue Op,
7963 EVT IntVT =
Op.getValueType();
7967 SDValue FPSIdx = getFramePointerFrameIndex(DAG);
7971 return DAG.
getNode(PPCISD::DYNAREAOFFSET, dl, VTs,
Ops);
7983 bool isPPC64 = Subtarget.isPPC64();
7984 unsigned SP = isPPC64 ? PPC::X1 : PPC::R1;
7993 DAG.
getLoad(PtrVT, dl, Chain, StackPtr, MachinePointerInfo());
7999 return DAG.
getStore(Chain, dl, LoadLinkSP, StackPtr, MachinePointerInfo());
8004 bool isPPC64 = Subtarget.isPPC64();
8009 PPCFunctionInfo *FI = MF.
getInfo<PPCFunctionInfo>();
8015 int LROffset = Subtarget.getFrameLowering()->getReturnSaveOffset();
8025PPCTargetLowering::getFramePointerFrameIndex(
SelectionDAG & DAG)
const {
8027 bool isPPC64 = Subtarget.isPPC64();
8032 PPCFunctionInfo *FI = MF.
getInfo<PPCFunctionInfo>();
8038 int FPOffset = Subtarget.getFrameLowering()->getFramePointerSaveOffset();
8061 SDValue FPSIdx = getFramePointerFrameIndex(DAG);
8063 SDVTList VTs = DAG.
getVTList(PtrVT, MVT::Other);
8065 return DAG.
getNode(PPCISD::PROBED_ALLOCA, dl, VTs,
Ops);
8066 return DAG.
getNode(PPCISD::DYNALLOC, dl, VTs,
Ops);
8073 bool isPPC64 = Subtarget.isPPC64();
8083 return DAG.
getNode(PPCISD::EH_SJLJ_SETJMP,
DL,
8085 Op.getOperand(0),
Op.getOperand(1));
8091 return DAG.
getNode(PPCISD::EH_SJLJ_LONGJMP,
DL, MVT::Other,
8092 Op.getOperand(0),
Op.getOperand(1));
8096 if (
Op.getValueType().isVector())
8097 return LowerVectorLoad(
Op, DAG);
8099 assert(
Op.getValueType() == MVT::i1 &&
8100 "Custom lowering only for i1 loads");
8109 MachineMemOperand *MMO =
LD->getMemOperand();
8113 BasePtr, MVT::i8, MMO);
8121 if (
Op.getOperand(1).getValueType().isVector())
8122 return LowerVectorStore(
Op, DAG);
8124 assert(
Op.getOperand(1).getValueType() == MVT::i1 &&
8125 "Custom lowering only for i1 stores");
8135 MachineMemOperand *MMO =
ST->getMemOperand();
8144 assert(
Op.getValueType() == MVT::i1 &&
8145 "Custom lowering only for i1 results");
8173 EVT TrgVT =
Op.getValueType();
8197 if (SrcSize == 256) {
8208 Op1 = SrcSize == 128 ? N1 :
widenVec(DAG, N1,
DL);
8214 SmallVector<int, 16> ShuffV;
8215 if (Subtarget.isLittleEndian())
8216 for (
unsigned i = 0; i < TrgNumElts; ++i)
8219 for (
unsigned i = 1; i <= TrgNumElts; ++i)
8223 for (
unsigned i = TrgNumElts; i < WideNumElts; ++i)
8236 EVT ResVT =
Op.getValueType();
8237 EVT CmpVT =
Op.getOperand(0).getValueType();
8239 SDValue TV =
Op.getOperand(2), FV =
Op.getOperand(3);
8245 if (!Subtarget.hasP9Vector() && CmpVT == MVT::f128) {
8258 SDNodeFlags
Flags =
Op.getNode()->getFlags();
8262 if (Subtarget.hasP9Vector() &&
LHS == TV &&
RHS == FV) {
8279 if (!
Flags.hasNoInfs() || !
Flags.hasNoNaNs() || ResVT == MVT::f128)
8292 if (
LHS.getValueType() == MVT::f32)
8294 Sel1 = DAG.
getNode(PPCISD::FSEL, dl, ResVT,
LHS, TV, FV);
8297 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8305 if (
LHS.getValueType() == MVT::f32)
8307 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
LHS, TV, FV);
8314 if (
LHS.getValueType() == MVT::f32)
8316 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8328 if (
Cmp.getValueType() == MVT::f32)
8330 Sel1 = DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8333 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8338 if (
Cmp.getValueType() == MVT::f32)
8340 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV);
8344 if (
Cmp.getValueType() == MVT::f32)
8346 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8350 if (
Cmp.getValueType() == MVT::f32)
8352 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV);
8356 if (
Cmp.getValueType() == MVT::f32)
8358 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8367 case PPCISD::FCTIDZ:
8368 return PPCISD::STRICT_FCTIDZ;
8369 case PPCISD::FCTIWZ:
8370 return PPCISD::STRICT_FCTIWZ;
8371 case PPCISD::FCTIDUZ:
8372 return PPCISD::STRICT_FCTIDUZ;
8373 case PPCISD::FCTIWUZ:
8374 return PPCISD::STRICT_FCTIWUZ;
8376 return PPCISD::STRICT_FCFID;
8377 case PPCISD::FCFIDU:
8378 return PPCISD::STRICT_FCFIDU;
8379 case PPCISD::FCFIDS:
8380 return PPCISD::STRICT_FCFIDS;
8381 case PPCISD::FCFIDUS:
8382 return PPCISD::STRICT_FCFIDUS;
8389 bool IsStrict =
Op->isStrictFPOpcode();
8398 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8400 MVT DestTy =
Op.getSimpleValueType();
8401 assert(Src.getValueType().isFloatingPoint() &&
8402 (DestTy == MVT::i8 || DestTy == MVT::i16 || DestTy == MVT::i32 ||
8403 DestTy == MVT::i64) &&
8404 "Invalid FP_TO_INT types");
8405 if (Src.getValueType() == MVT::f32) {
8409 DAG.
getVTList(MVT::f64, MVT::Other), {Chain, Src}, Flags);
8414 if ((DestTy == MVT::i8 || DestTy == MVT::i16) && Subtarget.hasP9Vector())
8420 Opc = IsSigned ? PPCISD::FCTIWZ
8421 : (Subtarget.hasFPCVT() ? PPCISD::FCTIWUZ : PPCISD::FCTIDZ);
8424 assert((IsSigned || Subtarget.hasFPCVT()) &&
8425 "i64 FP_TO_UINT is supported only with FPCVT");
8426 Opc = IsSigned ? PPCISD::FCTIDZ : PPCISD::FCTIDUZ;
8428 EVT ConvTy = Src.getValueType() == MVT::f128 ? MVT::f128 : MVT::f64;
8440void PPCTargetLowering::LowerFP_TO_INTForReuse(
SDValue Op, ReuseLoadInfo &RLI,
8442 const SDLoc &dl)
const {
8446 bool IsStrict =
Op->isStrictFPOpcode();
8449 bool i32Stack =
Op.getValueType() == MVT::i32 && Subtarget.hasSTFIWX() &&
8450 (IsSigned || Subtarget.hasFPCVT());
8453 MachinePointerInfo MPI =
8461 Alignment =
Align(4);
8462 MachineMemOperand *MMO =
8468 Chain = DAG.
getStore(Chain, dl, Tmp, FIPtr, MPI, Alignment);
8472 if (
Op.getValueType() == MVT::i32 && !i32Stack &&
8473 !Subtarget.isLittleEndian()) {
8482 RLI.Alignment = Alignment;
8490 const SDLoc &dl)
const {
8493 if (
Op->isStrictFPOpcode())
8500 const SDLoc &dl)
const {
8501 bool IsStrict =
Op->isStrictFPOpcode();
8504 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8505 EVT SrcVT = Src.getValueType();
8506 EVT DstVT =
Op.getValueType();
8509 if (SrcVT == MVT::f128)
8510 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8514 if (SrcVT == MVT::ppcf128) {
8515 if (DstVT == MVT::i32) {
8520 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8531 {Op.getOperand(0), Lo, Hi}, Flags);
8534 {Res.getValue(1), Res}, Flags);
8540 const uint64_t TwoE31[] = {0x41e0000000000000LL, 0};
8564 {Chain, Src, FltOfs}, Flags);
8568 {Chain, Val}, Flags);
8571 dl, DstVT, Sel, DAG.
getConstant(0, dl, DstVT), SignMask);
8589 if (Subtarget.hasDirectMove() && Subtarget.isPPC64())
8590 return LowerFP_TO_INTDirectMove(
Op, DAG, dl);
8593 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8595 return DAG.
getLoad(
Op.getValueType(), dl, RLI.Chain, RLI.Ptr, RLI.MPI,
8596 RLI.Alignment, RLI.MMOFlags(),
8597 MMOMetadata(RLI.AAInfo, RLI.Ranges));
8608bool PPCTargetLowering::canReuseLoadAddress(
SDValue Op,
EVT MemVT,
8613 if (
Op->isStrictFPOpcode())
8618 (Subtarget.hasFPCVT() ||
Op.getValueType() == MVT::i32);
8622 Op.getOperand(0).getValueType())) {
8624 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8629 if (!LD ||
LD->getExtensionType() != ET ||
LD->isVolatile() ||
8630 LD->isNonTemporal())
8632 if (
LD->getMemoryVT() != MemVT)
8642 RLI.Ptr =
LD->getBasePtr();
8643 if (
LD->isIndexed() && !
LD->getOffset().isUndef()) {
8645 "Non-pre-inc AM on PPC?");
8650 RLI.Chain =
LD->getChain();
8651 RLI.MPI =
LD->getPointerInfo();
8652 RLI.IsDereferenceable =
LD->isDereferenceable();
8653 RLI.IsInvariant =
LD->isInvariant();
8654 RLI.Alignment =
LD->getAlign();
8655 RLI.AAInfo =
LD->getAAInfo();
8656 RLI.Ranges =
LD->getRanges();
8658 RLI.ResChain =
SDValue(LD,
LD->isIndexed() ? 2 : 1);
8665bool PPCTargetLowering::directMoveIsProfitable(
const SDValue &
Op)
const {
8666 SDNode *Origin =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0).getNode();
8673 if (!Subtarget.hasP9Vector() &&
8677 for (SDUse &Use : Origin->
uses()) {
8680 if (
Use.getResNo() != 0)
8707 bool IsSingle =
Op.getValueType() == MVT::f32 && Subtarget.hasFPCVT();
8708 unsigned ConvOpc = IsSingle ? (IsSigned ? PPCISD::FCFIDS : PPCISD::FCFIDUS)
8709 : (IsSigned ? PPCISD::FCFID : PPCISD::FCFIDU);
8710 EVT ConvTy = IsSingle ? MVT::f32 : MVT::f64;
8711 if (
Op->isStrictFPOpcode()) {
8713 Chain =
Op.getOperand(0);
8715 DAG.
getVTList(ConvTy, MVT::Other), {Chain, Src}, Flags);
8717 return DAG.
getNode(ConvOpc, dl, ConvTy, Src);
8725 const SDLoc &dl)
const {
8726 assert((
Op.getValueType() == MVT::f32 ||
8727 Op.getValueType() == MVT::f64) &&
8728 "Invalid floating point type as target of conversion");
8729 assert(Subtarget.hasFPCVT() &&
8730 "Int to FP conversions with direct moves require FPCVT");
8731 SDValue Src =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0);
8732 bool WordInt = Src.getSimpleValueType().SimpleTy == MVT::i32;
8735 unsigned MovOpc = (WordInt && !
Signed) ? PPCISD::MTVSRZ : PPCISD::MTVSRA;
8754 for (
unsigned i = 1; i < NumConcat; ++i)
8761 const SDLoc &dl)
const {
8762 bool IsStrict =
Op->isStrictFPOpcode();
8763 unsigned Opc =
Op.getOpcode();
8764 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8767 "Unexpected conversion type");
8768 assert((
Op.getValueType() == MVT::v2f64 ||
Op.getValueType() == MVT::v4f32) &&
8769 "Supports conversions to v2f64/v4f32 only.");
8773 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8776 bool FourEltRes =
Op.getValueType() == MVT::v4f32;
8781 MVT IntermediateVT = FourEltRes ? MVT::v4i32 : MVT::v2i64;
8783 SmallVector<int, 16> ShuffV;
8784 for (
unsigned i = 0; i < WideNumElts; ++i)
8787 int Stride = FourEltRes ? WideNumElts / 4 : WideNumElts / 2;
8788 int SaveElts = FourEltRes ? 4 : 2;
8789 if (Subtarget.isLittleEndian())
8790 for (
int i = 0; i < SaveElts; i++)
8791 ShuffV[i * Stride] = i;
8793 for (
int i = 1; i <= SaveElts; i++)
8794 ShuffV[i * Stride - 1] = i - 1;
8802 Arrange = DAG.
getBitcast(IntermediateVT, Arrange);
8803 EVT ExtVT = Src.getValueType();
8804 if (Subtarget.hasP9Altivec())
8815 {Op.getOperand(0), Extend}, Flags);
8817 return DAG.
getNode(
Opc, dl,
Op.getValueType(), Extend);
8825 bool IsStrict =
Op->isStrictFPOpcode();
8826 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8831 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8833 EVT InVT = Src.getValueType();
8834 EVT OutVT =
Op.getValueType();
8837 return LowerINT_TO_FPVector(
Op, DAG, dl);
8840 if (
Op.getValueType() == MVT::f128)
8841 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8844 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
8847 if (Src.getValueType() == MVT::i1) {
8859 if (Subtarget.hasDirectMove() && directMoveIsProfitable(
Op) &&
8860 Subtarget.isPPC64() && Subtarget.hasFPCVT())
8861 return LowerINT_TO_FPDirectMove(
Op, DAG, dl);
8863 assert((IsSigned || Subtarget.hasFPCVT()) &&
8864 "UINT_TO_FP is supported only with FPCVT");
8866 if (Src.getValueType() == MVT::i64) {
8881 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT() &&
8882 !
Op->getFlags().hasApproximateFuncs()) {
8922 if (canReuseLoadAddress(SINT, MVT::i64, RLI, DAG)) {
8926 DAG.
getLoad(MVT::f64, dl, RLI.Chain, RLI.Ptr, RLI.MPI, RLI.Alignment,
8927 RLI.MMOFlags(), MMOMetadata(RLI.AAInfo));
8930 }
else if (Subtarget.hasLFIWAX() &&
8931 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::SEXTLOAD)) {
8934 MMOMetadata(RLI.AAInfo, RLI.Ranges));
8938 Ops, MVT::i32, MMO);
8941 }
else if (Subtarget.hasFPCVT() &&
8942 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::ZEXTLOAD)) {
8945 MMOMetadata(RLI.AAInfo, RLI.Ranges));
8949 Ops, MVT::i32, MMO);
8952 }
else if (((Subtarget.hasLFIWAX() &&
8954 (Subtarget.hasFPCVT() &&
8969 "Expected an i32 store");
8975 RLI.Alignment =
Align(4);
8979 MMOMetadata(RLI.AAInfo, RLI.Ranges));
8982 PPCISD::LFIWZX : PPCISD::LFIWAX,
8983 dl, DAG.
getVTList(MVT::f64, MVT::Other),
8984 Ops, MVT::i32, MMO);
8985 Chain =
Bits.getValue(1);
8993 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
8997 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)},
9006 assert(Src.getValueType() == MVT::i32 &&
9007 "Unhandled INT_TO_FP type in custom expander!");
9017 if (Subtarget.hasLFIWAX() || Subtarget.hasFPCVT()) {
9020 if (!(ReusingLoad = canReuseLoadAddress(Src, MVT::i32, RLI, DAG))) {
9030 "Expected an i32 store");
9036 RLI.Alignment =
Align(4);
9041 MMOMetadata(RLI.AAInfo, RLI.Ranges));
9047 if (ReusingLoad && RLI.ResChain) {
9051 assert(Subtarget.isPPC64() &&
9052 "i32->FP without LFIWAX supported only on PPC64");
9061 Chain, dl, Ext64, FIdx,
9067 MVT::f64, dl, Chain, FIdx,
9076 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
9080 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)}, Flags);
9097 uint64_t
Mode = CVal->getZExtValue();
9098 assert(
Mode < 4 &&
"Unsupported rounding mode!");
9099 unsigned InternalRnd =
Mode ^ (~(
Mode >> 1) & 1);
9100 if (Subtarget.isISA3_0())
9103 PPC::MFFSCRNI, Dl, {MVT::f64, MVT::Other},
9104 {DAG.getConstant(InternalRnd, Dl, MVT::i32, true), Chain}),
9107 (InternalRnd & 2) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
9108 {DAG.
getConstant(30, Dl, MVT::i32,
true), Chain});
9110 (InternalRnd & 1) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
9128 if (!Subtarget.isISA3_0()) {
9129 MFFS = DAG.
getNode(PPCISD::MFFS, Dl, {MVT::f64, MVT::Other}, Chain);
9133 if (Subtarget.isPPC64()) {
9134 if (Subtarget.isISA3_0()) {
9139 PPC::RLDIMI, Dl, MVT::i64,
9144 NewFPSCR =
SDValue(InsertRN, 0);
9151 SDValue Addr = Subtarget.isLittleEndian()
9155 if (Subtarget.isISA3_0()) {
9156 Chain = DAG.
getStore(Chain, Dl, DstFlag, Addr, MachinePointerInfo());
9158 Chain = DAG.
getStore(Chain, Dl, MFFS, StackSlot, MachinePointerInfo());
9160 DAG.
getLoad(MVT::i32, Dl, Chain, Addr, MachinePointerInfo());
9163 PPC::RLWIMI, Dl, MVT::i32,
9164 {Tmp, DstFlag, DAG.getTargetConstant(0, Dl, MVT::i32),
9165 DAG.getTargetConstant(30, Dl, MVT::i32),
9166 DAG.getTargetConstant(31, Dl, MVT::i32)}),
9168 Chain = DAG.
getStore(Chain, Dl, Tmp, Addr, MachinePointerInfo());
9171 DAG.
getLoad(MVT::f64, Dl, Chain, StackSlot, MachinePointerInfo());
9174 if (Subtarget.isISA3_0())
9180 PPC::MTFSF, Dl, MVT::Other,
9208 EVT VT =
Op.getValueType();
9213 SDValue MFFS = DAG.
getNode(PPCISD::MFFS, dl, {MVT::f64, MVT::Other}, Chain);
9224 Chain = DAG.
getStore(Chain, dl, MFFS, StackSlot, MachinePointerInfo());
9228 "Stack slot adjustment is valid only on big endian subtargets!");
9231 CWD = DAG.
getLoad(MVT::i32, dl, Chain, Addr, MachinePointerInfo());
9258 EVT VT =
Op.getValueType();
9262 VT ==
Op.getOperand(1).getValueType() &&
9282 SDValue OutOps[] = { OutLo, OutHi };
9287 EVT VT =
Op.getValueType();
9291 VT ==
Op.getOperand(1).getValueType() &&
9311 SDValue OutOps[] = { OutLo, OutHi };
9317 EVT VT =
Op.getValueType();
9320 VT ==
Op.getOperand(1).getValueType() &&
9340 SDValue OutOps[] = { OutLo, OutHi };
9347 EVT VT =
Op.getValueType();
9354 EVT AmtVT =
Z.getValueType();
9364 X = DAG.
getNode(PPCISD::SHL, dl, VT,
X, IsFSHL ? Z : SubZ);
9365 Y = DAG.
getNode(PPCISD::SRL, dl, VT,
Y, IsFSHL ? SubZ : Z);
9377 static const MVT VTys[] = {
9378 MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
9381 EVT ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1];
9384 if (Val == ((1LLU << (SplatSize * 8)) - 1)) {
9389 EVT CanonicalVT = VTys[SplatSize-1];
9402 const SDLoc &dl,
EVT DestVT = MVT::Other) {
9403 if (DestVT == MVT::Other) DestVT =
Op.getValueType();
9412 EVT DestVT = MVT::Other) {
9413 if (DestVT == MVT::Other) DestVT =
LHS.getValueType();
9422 EVT DestVT = MVT::Other) {
9425 DAG.
getConstant(IID, dl, MVT::i32), Op0, Op1, Op2);
9437 for (
unsigned i = 0; i != 16; ++i)
9458 EVT VecVT = V->getValueType(0);
9459 bool RightType = VecVT == MVT::v2f64 ||
9460 (HasP8Vector && VecVT == MVT::v4f32) ||
9461 (HasDirectMove && (VecVT == MVT::v2i64 || VecVT == MVT::v4i32));
9465 bool IsSplat =
true;
9466 bool IsLoad =
false;
9472 if (V->isConstant())
9474 for (
int i = 0, e = V->getNumOperands(); i < e; ++i) {
9475 if (V->getOperand(i).isUndef())
9479 if (V->getOperand(i).getOpcode() ==
ISD::LOAD ||
9481 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD) ||
9483 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD) ||
9485 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD))
9489 if (V->getOperand(i) != Op0 ||
9490 (!IsLoad && !V->isOnlyUserOf(V->getOperand(i).getNode())))
9493 return !(IsSplat && IsLoad);
9503 (
Op.getValueType() != MVT::f128))
9508 if ((
Lo.getValueType() != MVT::i64) || (
Hi.getValueType() != MVT::i64))
9511 if (!Subtarget.isLittleEndian())
9514 return DAG.
getNode(PPCISD::BUILD_FP128, dl, MVT::f128,
Lo,
Hi);
9522 InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED) {
9523 IsPermuted = InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED;
9536 APFloat APFloatToConvert = ArgAPFloat;
9537 bool LosesInfo =
true;
9542 ArgAPFloat = APFloatToConvert;
9564 APFloat APFloatToConvert = ArgAPFloat;
9565 bool LosesInfo =
true;
9569 return (!LosesInfo && !APFloatToConvert.
isDenormal());
9578 EVT Ty =
Op->getValueType(0);
9581 if ((Ty == MVT::v2f64 || Ty == MVT::v4f32 || Ty == MVT::v4i32) &&
9590 if ((Ty == MVT::v8i16 || Ty == MVT::v16i8) &&
ISD::isEXTLoad(InputNode) &&
9594 if (Ty == MVT::v2i64) {
9597 if (MemVT == MVT::i32) {
9599 Opcode = PPCISD::ZEXT_LD_SPLAT;
9601 Opcode = PPCISD::SEXT_LD_SPLAT;
9609 bool IsLittleEndian) {
9615 APInt ConstValue(VTSize, 0);
9619 unsigned BitPos = 0;
9627 ConstValue.
insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth),
9628 IsLittleEndian ? BitPos : VTSize - EltWidth - BitPos);
9632 for (
unsigned J = 0; J < 16; ++J) {
9634 if (ExtractValue != 0x00 && ExtractValue != 0xFF)
9636 if (ExtractValue == 0xFF)
9651 assert(BVN &&
"Expected a BuildVectorSDNode in LowerBUILD_VECTOR");
9653 if (Subtarget.hasP10Vector()) {
9654 APInt BitMask(32, 0);
9660 BitMask != 0 && BitMask != 0xffff) {
9662 MachineSDNode *MSDNode =
9674 if (
SDValue VecPat = combineBVLoadsSpecialValue(
Op, DAG))
9678 APInt APSplatBits, APSplatUndef;
9679 unsigned SplatBitSize = 0;
9681 bool BVNIsConstantSplat =
9683 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
9689 if (BVNIsConstantSplat && (SplatBitSize == 64) &&
9690 Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
9693 if ((
Op->getValueType(0) == MVT::v2f64) &&
9696 PPCISD::XXSPLTI_SP_TO_DP, dl, MVT::v2f64,
9712 PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9718 DAG.
getNode(PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9727 LowerVecSplatSmallFP(
Op, DAG, BVNIsConstantSplat, SplatBitSize))
9730 bool IsSplat64 =
false;
9731 uint64_t SplatBits = 0;
9732 int32_t SextVal = 0;
9733 if (BVNIsConstantSplat && SplatBitSize <= 64) {
9735 if (SplatBitSize <= 32) {
9737 }
else if (SplatBitSize == 64 && Subtarget.hasP8Altivec()) {
9738 int64_t Splat64Val =
static_cast<int64_t
>(SplatBits);
9739 bool P9Vector = Subtarget.hasP9Vector();
9740 int32_t
Hi = P9Vector ? 127 : 15;
9741 int32_t
Lo = P9Vector ? -128 : -16;
9742 IsSplat64 = Splat64Val >=
Lo && Splat64Val <=
Hi;
9743 SextVal =
static_cast<int32_t
>(SplatBits);
9747 if (!BVNIsConstantSplat || (SplatBitSize > 32 && !IsSplat64)) {
9748 unsigned NewOpcode = PPCISD::LD_SPLAT;
9754 const SDValue *InputLoad = &
Op.getOperand(0);
9759 unsigned MemorySize =
LD->getMemoryVT().getScalarSizeInBits();
9760 unsigned ElementSize =
9761 MemorySize * ((NewOpcode == PPCISD::LD_SPLAT) ? 1 : 2);
9763 assert(((ElementSize == 2 * MemorySize)
9764 ? (NewOpcode == PPCISD::ZEXT_LD_SPLAT ||
9765 NewOpcode == PPCISD::SEXT_LD_SPLAT)
9766 : (NewOpcode == PPCISD::LD_SPLAT)) &&
9767 "Unmatched element size and opcode!\n");
9772 unsigned NumUsesOfInputLD = 128 / ElementSize;
9774 if (BVInOp.isUndef())
9789 if (NumUsesOfInputLD == 1 &&
9790 (
Op->getValueType(0) == MVT::v2i64 && NewOpcode != PPCISD::LD_SPLAT &&
9791 !Subtarget.isLittleEndian() && Subtarget.hasVSX() &&
9792 Subtarget.hasLFIWAX()))
9800 if (NumUsesOfInputLD == 1 && Subtarget.isLittleEndian() &&
9801 Subtarget.isISA3_1() && ElementSize <= 16)
9804 assert(NumUsesOfInputLD > 0 &&
"No uses of input LD of a build_vector?");
9806 Subtarget.hasVSX()) {
9813 NewOpcode, dl, DAG.
getVTList(
Op.getValueType(), MVT::Other),
Ops,
9814 LD->getMemoryVT(),
LD->getMemOperand());
9826 if (Subtarget.hasVSX() && Subtarget.isPPC64() &&
9828 Subtarget.hasP8Vector()))
9834 unsigned SplatSize = SplatBitSize / 8;
9839 if (SplatBits == 0) {
9841 if (
Op.getValueType() != MVT::v4i32 || HasAnyUndefs) {
9853 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 2)
9855 Op.getValueType(), DAG, dl);
9857 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 4)
9862 if (Subtarget.hasP9Vector() && SplatSize == 1)
9868 if (SextVal >= -16 && SextVal <= 15) {
9871 unsigned UseSize = SplatSize == 8 ? 4 : SplatSize;
9878 DAG.
getBitcast(MVT::v4i32, Res), DAG, dl, MVT::v2i64);
9884 if (Subtarget.hasP9Vector() && SextVal >= -128 && SextVal <= 127) {
9890 switch (SplatSize) {
9894 IID = Intrinsic::ppc_altivec_vupklsb;
9898 IID = Intrinsic::ppc_altivec_vextsb2w;
9902 IID = Intrinsic::ppc_altivec_vextsb2d;
9909 assert(!IsSplat64 &&
"Unhandled 64-bit splat pattern");
9918 if (SextVal >= -32 && SextVal <= 31) {
9923 EVT VT = (SplatSize == 1 ? MVT::v16i8 :
9924 (SplatSize == 2 ? MVT::v8i16 : MVT::v4i32));
9927 if (VT ==
Op.getValueType())
9936 if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) {
9950 static const signed char SplatCsts[] = {
9951 -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
9952 -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
9955 for (
unsigned idx = 0; idx < std::size(SplatCsts); ++idx) {
9958 int i = SplatCsts[idx];
9962 unsigned TypeShiftAmt = i & (SplatBitSize-1);
9965 if (SextVal == (
int)((
unsigned)i << TypeShiftAmt)) {
9967 static const unsigned IIDs[] = {
9968 Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
9969 Intrinsic::ppc_altivec_vslw
9976 if (SextVal == (
int)((
unsigned)i >> TypeShiftAmt)) {
9978 static const unsigned IIDs[] = {
9979 Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
9980 Intrinsic::ppc_altivec_vsrw
9987 if (SextVal == (
int)(((
unsigned)i << TypeShiftAmt) |
9988 ((
unsigned)i >> (SplatBitSize-TypeShiftAmt)))) {
9990 static const unsigned IIDs[] = {
9991 Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0,
9992 Intrinsic::ppc_altivec_vrlw
9999 if (SextVal == (
int)(((
unsigned)i << 8) | (i < 0 ? 0xFF : 0))) {
10001 unsigned Amt = Subtarget.isLittleEndian() ? 15 : 1;
10005 if (SextVal == (
int)(((
unsigned)i << 16) | (i < 0 ? 0xFFFF : 0))) {
10007 unsigned Amt = Subtarget.isLittleEndian() ? 14 : 2;
10011 if (SextVal == (
int)(((
unsigned)i << 24) | (i < 0 ? 0xFFFFFF : 0))) {
10013 unsigned Amt = Subtarget.isLittleEndian() ? 13 : 3;
10026 unsigned OpNum = (PFEntry >> 26) & 0x0F;
10027 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
10028 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
10044 if (LHSID == (1*9+2)*9+3)
return LHS;
10045 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
10057 ShufIdxs[ 0] = 0; ShufIdxs[ 1] = 1; ShufIdxs[ 2] = 2; ShufIdxs[ 3] = 3;
10058 ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19;
10059 ShufIdxs[ 8] = 4; ShufIdxs[ 9] = 5; ShufIdxs[10] = 6; ShufIdxs[11] = 7;
10060 ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23;
10063 ShufIdxs[ 0] = 8; ShufIdxs[ 1] = 9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11;
10064 ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27;
10065 ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15;
10066 ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31;
10069 for (
unsigned i = 0; i != 16; ++i)
10070 ShufIdxs[i] = (i&3)+0;
10073 for (
unsigned i = 0; i != 16; ++i)
10074 ShufIdxs[i] = (i&3)+4;
10077 for (
unsigned i = 0; i != 16; ++i)
10078 ShufIdxs[i] = (i&3)+8;
10081 for (
unsigned i = 0; i != 16; ++i)
10082 ShufIdxs[i] = (i&3)+12;
10103 const unsigned BytesInVector = 16;
10104 bool IsLE = Subtarget.isLittleEndian();
10108 unsigned ShiftElts = 0, InsertAtByte = 0;
10112 unsigned LittleEndianShifts[] = {8, 7, 6, 5, 4, 3, 2, 1,
10113 0, 15, 14, 13, 12, 11, 10, 9};
10114 unsigned BigEndianShifts[] = {9, 10, 11, 12, 13, 14, 15, 0,
10115 1, 2, 3, 4, 5, 6, 7, 8};
10117 ArrayRef<int>
Mask =
N->getMask();
10118 int OriginalOrder[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
10130 bool FoundCandidate =
false;
10134 unsigned VINSERTBSrcElem = IsLE ? 8 : 7;
10137 for (
unsigned i = 0; i < BytesInVector; ++i) {
10138 unsigned CurrentElement =
Mask[i];
10141 if (V2.
isUndef() && CurrentElement != VINSERTBSrcElem)
10144 bool OtherElementsInOrder =
true;
10147 for (
unsigned j = 0;
j < BytesInVector; ++
j) {
10154 (!V2.
isUndef() && CurrentElement < BytesInVector) ? BytesInVector : 0;
10155 if (Mask[j] != OriginalOrder[j] + MaskOffset) {
10156 OtherElementsInOrder =
false;
10163 if (OtherElementsInOrder) {
10170 ShiftElts = IsLE ? LittleEndianShifts[CurrentElement & 0xF]
10171 : BigEndianShifts[CurrentElement & 0xF];
10172 Swap = CurrentElement < BytesInVector;
10174 InsertAtByte = IsLE ? BytesInVector - (i + 1) : i;
10175 FoundCandidate =
true;
10180 if (!FoundCandidate)
10190 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10192 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8,
V1, Shl,
10195 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8,
V1, V2,
10204 const unsigned NumHalfWords = 8;
10205 const unsigned BytesInVector = NumHalfWords * 2;
10210 bool IsLE = Subtarget.isLittleEndian();
10214 unsigned ShiftElts = 0, InsertAtByte = 0;
10218 unsigned LittleEndianShifts[] = {4, 3, 2, 1, 0, 7, 6, 5};
10219 unsigned BigEndianShifts[] = {5, 6, 7, 0, 1, 2, 3, 4};
10222 uint32_t OriginalOrderLow = 0x1234567;
10223 uint32_t OriginalOrderHigh = 0x89ABCDEF;
10226 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10227 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10244 bool FoundCandidate =
false;
10247 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10248 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10250 uint32_t MaskOtherElts = ~(0xF <<
MaskShift);
10251 uint32_t TargetOrder = 0x0;
10258 unsigned VINSERTHSrcElem = IsLE ? 4 : 3;
10259 TargetOrder = OriginalOrderLow;
10263 if (MaskOneElt == VINSERTHSrcElem &&
10264 (Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10265 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10266 FoundCandidate =
true;
10272 (MaskOneElt < NumHalfWords) ? OriginalOrderHigh : OriginalOrderLow;
10274 if ((Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10276 ShiftElts = IsLE ? LittleEndianShifts[MaskOneElt & 0x7]
10277 : BigEndianShifts[MaskOneElt & 0x7];
10278 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10279 Swap = MaskOneElt < NumHalfWords;
10280 FoundCandidate =
true;
10286 if (!FoundCandidate)
10298 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10301 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10306 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10321 auto ShuffleMask = SVN->
getMask();
10336 ShuffleMask = CommutedSV->
getMask();
10345 APInt APSplatValue, APSplatUndef;
10346 unsigned SplatBitSize;
10349 HasAnyUndefs, 0, !Subtarget.isLittleEndian()) ||
10361 bool IsLE = Subtarget.isLittleEndian();
10362 if ((ShuffleMask[0] == 0 && ShuffleMask[8] == 8) &&
10363 (ShuffleMask[4] % 4 == 0 && ShuffleMask[12] % 4 == 0 &&
10364 ShuffleMask[4] > 15 && ShuffleMask[12] > 15))
10366 else if ((ShuffleMask[4] == 4 && ShuffleMask[12] == 12) &&
10367 (ShuffleMask[0] % 4 == 0 && ShuffleMask[8] % 4 == 0 &&
10368 ShuffleMask[0] > 15 && ShuffleMask[8] > 15))
10376 for (; SplatBitSize < 32; SplatBitSize <<= 1)
10377 SplatVal |= (SplatVal << SplatBitSize);
10380 PPCISD::XXSPLTI32DX,
DL, MVT::v2i64, DAG.
getBitcast(MVT::v2i64,
LHS),
10391 assert(
Op.getValueType() == MVT::v1i128 &&
10392 "Only set v1i128 as custom, other type shouldn't reach here!");
10397 if (SHLAmt % 8 == 0) {
10398 std::array<int, 16>
Mask;
10399 std::iota(
Mask.begin(),
Mask.end(), 0);
10400 std::rotate(
Mask.begin(),
Mask.begin() + SHLAmt / 8,
Mask.end());
10429 if (
SDValue NewShuffle = combineVectorShuffle(SVOp, DAG)) {
10434 V1 =
Op.getOperand(0);
10435 V2 =
Op.getOperand(1);
10437 EVT VT =
Op.getValueType();
10438 bool isLittleEndian = Subtarget.isLittleEndian();
10440 unsigned ShiftElts, InsertAtByte;
10446 bool IsPermutedLoad =
false;
10448 if (InputLoad && Subtarget.hasVSX() && V2.
isUndef() &&
10458 if (IsPermutedLoad) {
10459 assert((isLittleEndian || IsFourByte) &&
10460 "Unexpected size for permuted load on big endian target");
10461 SplatIdx += IsFourByte ? 2 : 1;
10462 assert((SplatIdx < (IsFourByte ? 4 : 2)) &&
10463 "Splat of a value outside of the loaded memory");
10468 if ((IsFourByte && Subtarget.hasP9Vector()) || !IsFourByte) {
10471 Offset = isLittleEndian ? (3 - SplatIdx) * 4 : SplatIdx * 4;
10473 Offset = isLittleEndian ? (1 - SplatIdx) * 8 : SplatIdx * 8;
10477 if (
LD->getValueType(0).getSizeInBits() == (IsFourByte ? 32 : 64))
10490 DAG.
getVTList(IsFourByte ? MVT::v4i32 : MVT::v2i64, MVT::Other);
10493 Ops,
LD->getMemoryVT(),
LD->getMemOperand());
10502 if (VT == MVT::v2i64 || VT == MVT::v2f64)
10505 if (Subtarget.hasP9Vector() &&
10515 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv2, Conv2,
10517 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Shl,
10521 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Conv2,
10526 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
10528 if ((SplatInsertNode = lowerToXXSPLTI32DX(SVOp, DAG)))
10529 return SplatInsertNode;
10532 if (Subtarget.hasP9Altivec()) {
10534 if ((NewISDNode = lowerToVINSERTH(SVOp, DAG)))
10537 if ((NewISDNode = lowerToVINSERTB(SVOp, DAG)))
10541 if (Subtarget.hasVSX() &&
10549 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv1, Conv2,
10554 if (Subtarget.hasVSX() &&
10562 SDValue PermDI = DAG.
getNode(PPCISD::XXPERMDI, dl, MVT::v2i64, Conv1, Conv2,
10567 if (Subtarget.hasP9Vector()) {
10587 if (Subtarget.hasVSX()) {
10600 SDValue Swap = DAG.
getNode(PPCISD::SWAP_NO_CHAIN, dl, MVT::v2f64, Conv);
10608 if (V2.isUndef()) {
10621 (Subtarget.hasP8Altivec() && (
10632 unsigned int ShuffleKind = isLittleEndian ? 2 : 0;
10642 (Subtarget.hasP8Altivec() && (
10650 ArrayRef<int> PermMask = SVOp->
getMask();
10653 unsigned PFIndexes[4];
10654 bool isFourElementShuffle =
true;
10655 for (
unsigned i = 0; i != 4 && isFourElementShuffle;
10657 unsigned EltNo = 8;
10658 for (
unsigned j = 0;
j != 4; ++
j) {
10659 if (PermMask[i * 4 + j] < 0)
10662 unsigned ByteSource = PermMask[i * 4 +
j];
10663 if ((ByteSource & 3) != j) {
10664 isFourElementShuffle =
false;
10669 EltNo = ByteSource / 4;
10670 }
else if (EltNo != ByteSource / 4) {
10671 isFourElementShuffle =
false;
10675 PFIndexes[i] = EltNo;
10683 if (isFourElementShuffle) {
10685 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
10686 PFIndexes[2] * 9 + PFIndexes[3];
10689 unsigned Cost = (PFEntry >> 30);
10709 if (V2.isUndef()) V2 =
V1;
10711 return LowerVPERM(
Op, DAG, PermMask, VT,
V1, V2);
10717 unsigned Opcode = PPCISD::VPERM;
10720 bool NeedSwap =
false;
10721 bool isLittleEndian = Subtarget.isLittleEndian();
10722 bool isPPC64 = Subtarget.isPPC64();
10724 if (Subtarget.hasVSX() && Subtarget.hasP9Vector() &&
10726 LLVM_DEBUG(
dbgs() <<
"At least one of two input vectors are dead - using "
10727 "XXPERM instead\n");
10728 Opcode = PPCISD::XXPERM;
10733 if ((!isLittleEndian && !V2->
hasOneUse() &&
V1->hasOneUse()) ||
10734 (isLittleEndian && !
V1->hasOneUse() && V2->
hasOneUse())) {
10736 NeedSwap = !NeedSwap;
10750 bool V1HasXXSWAPD =
V1->getOperand(0)->getOpcode() == PPCISD::XXSWAPD;
10771 unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i];
10773 if (V1HasXXSWAPD) {
10776 else if (SrcElt < 16)
10779 if (V2HasXXSWAPD) {
10782 else if (SrcElt > 15)
10791 for (
unsigned j = 0;
j != BytesPerElement; ++
j)
10792 if (isLittleEndian)
10794 DAG.
getConstant(31 - (SrcElt * BytesPerElement + j), dl, MVT::i32));
10797 DAG.
getConstant(SrcElt * BytesPerElement + j, dl, MVT::i32));
10800 if (V1HasXXSWAPD) {
10801 dl = SDLoc(
V1->getOperand(0));
10802 V1 =
V1->getOperand(0)->getOperand(1);
10804 if (V2HasXXSWAPD) {
10809 if (isPPC64 && (V1HasXXSWAPD || V2HasXXSWAPD)) {
10810 if (ValType != MVT::v2f64)
10816 ShufflesHandledWithVPERM++;
10820 if (Opcode == PPCISD::XXPERM) {
10821 dbgs() <<
"Emitting a XXPERM for the following shuffle:\n";
10823 dbgs() <<
"Emitting a VPERM for the following shuffle:\n";
10826 dbgs() <<
"With the following permute control vector:\n";
10830 if (Opcode == PPCISD::XXPERM)
10831 VPermMask = DAG.
getBitcast(MVT::v4i32, VPermMask);
10835 if (isLittleEndian)
10839 DAG.
getNode(Opcode, dl,
V1.getValueType(),
V1, V2, VPermMask);
10841 VPERMNode = DAG.
getBitcast(ValType, VPERMNode);
10853 switch (IntrinsicID) {
10857 case Intrinsic::ppc_altivec_vcmpbfp_p:
10861 case Intrinsic::ppc_altivec_vcmpeqfp_p:
10865 case Intrinsic::ppc_altivec_vcmpequb_p:
10869 case Intrinsic::ppc_altivec_vcmpequh_p:
10873 case Intrinsic::ppc_altivec_vcmpequw_p:
10877 case Intrinsic::ppc_altivec_vcmpequd_p:
10878 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10884 case Intrinsic::ppc_altivec_vcmpneb_p:
10885 case Intrinsic::ppc_altivec_vcmpneh_p:
10886 case Intrinsic::ppc_altivec_vcmpnew_p:
10887 case Intrinsic::ppc_altivec_vcmpnezb_p:
10888 case Intrinsic::ppc_altivec_vcmpnezh_p:
10889 case Intrinsic::ppc_altivec_vcmpnezw_p:
10890 if (Subtarget.hasP9Altivec()) {
10891 switch (IntrinsicID) {
10894 case Intrinsic::ppc_altivec_vcmpneb_p:
10897 case Intrinsic::ppc_altivec_vcmpneh_p:
10900 case Intrinsic::ppc_altivec_vcmpnew_p:
10903 case Intrinsic::ppc_altivec_vcmpnezb_p:
10906 case Intrinsic::ppc_altivec_vcmpnezh_p:
10909 case Intrinsic::ppc_altivec_vcmpnezw_p:
10917 case Intrinsic::ppc_altivec_vcmpgefp_p:
10921 case Intrinsic::ppc_altivec_vcmpgtfp_p:
10925 case Intrinsic::ppc_altivec_vcmpgtsb_p:
10929 case Intrinsic::ppc_altivec_vcmpgtsh_p:
10933 case Intrinsic::ppc_altivec_vcmpgtsw_p:
10937 case Intrinsic::ppc_altivec_vcmpgtsd_p:
10938 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10944 case Intrinsic::ppc_altivec_vcmpgtub_p:
10948 case Intrinsic::ppc_altivec_vcmpgtuh_p:
10952 case Intrinsic::ppc_altivec_vcmpgtuw_p:
10956 case Intrinsic::ppc_altivec_vcmpgtud_p:
10957 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10964 case Intrinsic::ppc_altivec_vcmpequq:
10965 case Intrinsic::ppc_altivec_vcmpgtsq:
10966 case Intrinsic::ppc_altivec_vcmpgtuq:
10967 if (!Subtarget.isISA3_1())
10969 switch (IntrinsicID) {
10972 case Intrinsic::ppc_altivec_vcmpequq:
10975 case Intrinsic::ppc_altivec_vcmpgtsq:
10978 case Intrinsic::ppc_altivec_vcmpgtuq:
10985 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10986 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10987 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
10988 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
10989 case Intrinsic::ppc_vsx_xvcmpgesp_p:
10990 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
10991 if (Subtarget.hasVSX()) {
10992 switch (IntrinsicID) {
10993 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10996 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10999 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
11002 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
11005 case Intrinsic::ppc_vsx_xvcmpgesp_p:
11008 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
11018 case Intrinsic::ppc_altivec_vcmpbfp:
11021 case Intrinsic::ppc_altivec_vcmpeqfp:
11024 case Intrinsic::ppc_altivec_vcmpequb:
11027 case Intrinsic::ppc_altivec_vcmpequh:
11030 case Intrinsic::ppc_altivec_vcmpequw:
11033 case Intrinsic::ppc_altivec_vcmpequd:
11034 if (Subtarget.hasP8Altivec())
11039 case Intrinsic::ppc_altivec_vcmpneb:
11040 case Intrinsic::ppc_altivec_vcmpneh:
11041 case Intrinsic::ppc_altivec_vcmpnew:
11042 case Intrinsic::ppc_altivec_vcmpnezb:
11043 case Intrinsic::ppc_altivec_vcmpnezh:
11044 case Intrinsic::ppc_altivec_vcmpnezw:
11045 if (Subtarget.hasP9Altivec())
11046 switch (IntrinsicID) {
11049 case Intrinsic::ppc_altivec_vcmpneb:
11052 case Intrinsic::ppc_altivec_vcmpneh:
11055 case Intrinsic::ppc_altivec_vcmpnew:
11058 case Intrinsic::ppc_altivec_vcmpnezb:
11061 case Intrinsic::ppc_altivec_vcmpnezh:
11064 case Intrinsic::ppc_altivec_vcmpnezw:
11071 case Intrinsic::ppc_altivec_vcmpgefp:
11074 case Intrinsic::ppc_altivec_vcmpgtfp:
11077 case Intrinsic::ppc_altivec_vcmpgtsb:
11080 case Intrinsic::ppc_altivec_vcmpgtsh:
11083 case Intrinsic::ppc_altivec_vcmpgtsw:
11086 case Intrinsic::ppc_altivec_vcmpgtsd:
11087 if (Subtarget.hasP8Altivec())
11092 case Intrinsic::ppc_altivec_vcmpgtub:
11095 case Intrinsic::ppc_altivec_vcmpgtuh:
11098 case Intrinsic::ppc_altivec_vcmpgtuw:
11101 case Intrinsic::ppc_altivec_vcmpgtud:
11102 if (Subtarget.hasP8Altivec())
11107 case Intrinsic::ppc_altivec_vcmpequq_p:
11108 case Intrinsic::ppc_altivec_vcmpgtsq_p:
11109 case Intrinsic::ppc_altivec_vcmpgtuq_p:
11110 if (!Subtarget.isISA3_1())
11112 switch (IntrinsicID) {
11115 case Intrinsic::ppc_altivec_vcmpequq_p:
11118 case Intrinsic::ppc_altivec_vcmpgtsq_p:
11121 case Intrinsic::ppc_altivec_vcmpgtuq_p:
11135 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11141 auto MapNodeWithSplatVector =
11142 [&](
unsigned Opcode,
11143 std::initializer_list<SDValue> ExtraOps = {}) ->
SDValue {
11148 Ops.append(ExtraOps.begin(), ExtraOps.end());
11149 return DAG.
getNode(Opcode, dl, MVT::v16i8,
Ops);
11152 switch (IntrinsicID) {
11153 case Intrinsic::thread_pointer:
11155 if (Subtarget.isPPC64())
11159 case Intrinsic::ppc_rldimi: {
11160 assert(Subtarget.isPPC64() &&
"rldimi is only available in 64-bit!");
11162 APInt
Mask =
Op.getConstantOperandAPInt(4);
11164 return Op.getOperand(2);
11165 if (
Mask.isAllOnes())
11167 uint64_t SH =
Op.getConstantOperandVal(3);
11168 unsigned MB = 0, ME = 0;
11172 if (ME < 63 - SH) {
11175 }
else if (ME > 63 - SH) {
11181 {Op.getOperand(2), Src,
11182 DAG.getTargetConstant(63 - ME, dl, MVT::i32),
11183 DAG.getTargetConstant(MB, dl, MVT::i32)}),
11187 case Intrinsic::ppc_rlwimi: {
11188 APInt
Mask =
Op.getConstantOperandAPInt(4);
11190 return Op.getOperand(2);
11191 if (
Mask.isAllOnes())
11194 unsigned MB = 0, ME = 0;
11198 PPC::RLWIMI, dl, MVT::i32,
11199 {Op.getOperand(2), Op.getOperand(1), Op.getOperand(3),
11200 DAG.getTargetConstant(MB, dl, MVT::i32),
11201 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11205 case Intrinsic::ppc_bcdshift:
11206 return MapNodeWithSplatVector(PPCISD::BCDSHIFT, {
Op.getOperand(3)});
11207 case Intrinsic::ppc_bcdshiftround:
11208 return MapNodeWithSplatVector(PPCISD::BCDSHIFTROUND, {
Op.getOperand(3)});
11209 case Intrinsic::ppc_bcdtruncate:
11210 return MapNodeWithSplatVector(PPCISD::BCDTRUNC, {
Op.getOperand(3)});
11211 case Intrinsic::ppc_bcdunsignedtruncate:
11212 return MapNodeWithSplatVector(PPCISD::BCDUTRUNC);
11213 case Intrinsic::ppc_bcdunsignedshift:
11214 return MapNodeWithSplatVector(PPCISD::BCDUSHIFT);
11216 case Intrinsic::ppc_rlwnm: {
11217 if (
Op.getConstantOperandVal(3) == 0)
11219 unsigned MB = 0, ME = 0;
11224 {Op.getOperand(1), Op.getOperand(2),
11225 DAG.getTargetConstant(MB, dl, MVT::i32),
11226 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11230 case Intrinsic::ppc_mma_disassemble_acc: {
11231 if (Subtarget.isISAFuture()) {
11232 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11243 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11244 Subtarget.isLittleEndian() ? Value2 :
Value,
11245 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11249 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11250 Subtarget.isLittleEndian() ? Value2 :
Value,
11251 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11255 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11256 Subtarget.isLittleEndian() ?
Value : Value2,
11257 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11261 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11262 Subtarget.isLittleEndian() ?
Value : Value2,
11263 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11270 case Intrinsic::ppc_vsx_disassemble_pair: {
11273 if (IntrinsicID == Intrinsic::ppc_mma_disassemble_acc) {
11275 WideVec = DAG.
getNode(PPCISD::XXMFACC, dl, MVT::v512i1, WideVec);
11278 for (
int VecNo = 0; VecNo < NumVecs; VecNo++) {
11280 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8, WideVec,
11281 DAG.
getConstant(Subtarget.isLittleEndian() ? NumVecs - 1 - VecNo
11289 case Intrinsic::ppc_build_dmr: {
11292 for (
int i = 1; i < 9; i += 2) {
11300 DAG.
getNode(PPCISD::PAIR_BUILD, dl, MVT::v256i1, {Hi, Lo}));
11307 case Intrinsic::ppc_mma_dmxxextfdmr512: {
11308 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr512 requires ISA Future");
11310 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11311 "Specify P of 0 or 1 for lower or upper 512 bytes");
11312 unsigned HiLo = Idx->getSExtValue();
11316 Opcode = PPC::DMXXEXTFDMR512;
11317 Subx = PPC::sub_wacc_lo;
11319 Opcode = PPC::DMXXEXTFDMR512_HI;
11320 Subx = PPC::sub_wacc_hi;
11323 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
11327 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11331 case Intrinsic::ppc_mma_dmxxextfdmr256: {
11332 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr256 requires ISA Future");
11334 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11335 "Specify a dmr row pair 0-3");
11336 unsigned IdxVal = Idx->getSExtValue();
11340 Subx = PPC::sub_dmrrowp0;
11343 Subx = PPC::sub_dmrrowp1;
11346 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11349 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11353 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v256i1,
11359 DAG.
getMachineNode(PPC::DMXXEXTFDMR256, dl, MVT::v256i1, {Subreg, P}),
11363 case Intrinsic::ppc_mma_dmxxinstdmr512: {
11364 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr512 requires ISA Future");
11366 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11367 "Specify P of 0 or 1 for lower or upper 512 bytes");
11368 unsigned HiLo = Idx->getSExtValue();
11372 Opcode = PPCISD::INST512;
11373 Subx = PPC::sub_wacc_lo;
11375 Opcode = PPCISD::INST512HI;
11376 Subx = PPC::sub_wacc_hi;
11382 Op.getOperand(1), Wacc, SubReg),
11386 case Intrinsic::ppc_mma_dmxxinstdmr256: {
11387 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr256 requires ISA Future");
11389 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11390 "Specify a dmr row pair 0-3");
11391 unsigned IdxVal = Idx->getSExtValue();
11395 Subx = PPC::sub_dmrrowp0;
11398 Subx = PPC::sub_dmrrowp1;
11401 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11404 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11410 DAG.
getNode(PPCISD::INST256, dl, MVT::v256i1,
Op.getOperand(2),
P);
11412 Op.getOperand(1), DMRRowp, SubReg),
11416 case Intrinsic::ppc_mma_xxmfacc:
11417 case Intrinsic::ppc_mma_xxmtacc: {
11419 if (!Subtarget.isISAFuture())
11430 case Intrinsic::ppc_unpack_longdouble: {
11432 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11433 "Argument of long double unpack must be 0 or 1!");
11436 Idx->getValueType(0)));
11439 case Intrinsic::ppc_compare_exp_lt:
11440 case Intrinsic::ppc_compare_exp_gt:
11441 case Intrinsic::ppc_compare_exp_eq:
11442 case Intrinsic::ppc_compare_exp_uo: {
11444 switch (IntrinsicID) {
11445 case Intrinsic::ppc_compare_exp_lt:
11448 case Intrinsic::ppc_compare_exp_gt:
11451 case Intrinsic::ppc_compare_exp_eq:
11454 case Intrinsic::ppc_compare_exp_uo:
11460 PPC::SELECT_CC_I4, dl, MVT::i32,
11461 {SDValue(DAG.getMachineNode(PPC::XSCMPEXPDP, dl, MVT::i32,
11462 Op.getOperand(1), Op.getOperand(2)),
11464 DAG.getConstant(1, dl, MVT::i32), DAG.getConstant(0, dl, MVT::i32),
11465 DAG.getTargetConstant(Pred, dl, MVT::i32)}),
11468 case Intrinsic::ppc_test_data_class: {
11469 EVT OpVT =
Op.getOperand(1).getValueType();
11470 unsigned CmprOpc = OpVT == MVT::f128 ? PPC::XSTSTDCQP
11471 : (OpVT == MVT::f64 ? PPC::XSTSTDCDP
11484 {Op.getOperand(2), Op.getOperand(1)}),
11486 if (Subtarget.isISA3_1()) {
11493 TestDataClass, SubRegIdx),
11496 return DAG.
getNode(PPCISD::SETBC, dl, MVT::i32, CRBit);
11502 {TestDataClass, DAG.getConstant(1, dl, MVT::i32),
11503 DAG.getConstant(0, dl, MVT::i32),
11504 DAG.getTargetConstant(PPC::PRED_EQ, dl, MVT::i32)}),
11507 case Intrinsic::ppc_fnmsub: {
11508 EVT VT =
Op.getOperand(1).getValueType();
11509 if (!Subtarget.hasVSX() || (!Subtarget.hasFloat128() && VT == MVT::f128))
11514 return DAG.
getNode(PPCISD::FNMSUB, dl, VT,
Op.getOperand(1),
11515 Op.getOperand(2),
Op.getOperand(3));
11517 case Intrinsic::ppc_convert_f128_to_ppcf128:
11518 case Intrinsic::ppc_convert_ppcf128_to_f128: {
11519 RTLIB::Libcall LC = IntrinsicID == Intrinsic::ppc_convert_ppcf128_to_f128
11520 ? RTLIB::CONVERT_PPCF128_F128
11521 : RTLIB::CONVERT_F128_PPCF128;
11523 std::pair<SDValue, SDValue>
Result =
11524 makeLibCall(DAG, LC,
Op.getValueType(),
Op.getOperand(1), CallOptions,
11528 case Intrinsic::ppc_maxfe:
11529 case Intrinsic::ppc_maxfl:
11530 case Intrinsic::ppc_maxfs:
11531 case Intrinsic::ppc_minfe:
11532 case Intrinsic::ppc_minfl:
11533 case Intrinsic::ppc_minfs: {
11534 EVT VT =
Op.getValueType();
11537 [VT](
const SDUse &Use) { return Use.getValueType() == VT; }) &&
11538 "ppc_[max|min]f[e|l|s] must have uniform type arguments");
11541 if (IntrinsicID == Intrinsic::ppc_minfe ||
11542 IntrinsicID == Intrinsic::ppc_minfl ||
11543 IntrinsicID == Intrinsic::ppc_minfs)
11564 SDValue Tmp = DAG.
getNode(PPCISD::VCMP, dl,
Op.getOperand(2).getValueType(),
11565 Op.getOperand(1),
Op.getOperand(2),
11576 EVT VTs[] = {
Op.getOperand(2).getValueType(), MVT::Glue };
11584 switch (
Op.getConstantOperandVal(1)) {
11589 Bitx = PPC::sub_eq;
11590 SetOp = PPCISD::SETBC;
11595 Bitx = PPC::sub_eq;
11596 SetOp = PPCISD::SETBCR;
11601 Bitx = PPC::sub_lt;
11602 SetOp = PPCISD::SETBC;
11607 Bitx = PPC::sub_lt;
11608 SetOp = PPCISD::SETBCR;
11613 if (Subtarget.isISA3_1()) {
11618 CR6Reg, SubRegIdx, GlueOp),
11620 return DAG.
getNode(SetOp, dl, MVT::i32, CRBit);
11648 switch (
Op.getConstantOperandVal(ArgStart)) {
11649 case Intrinsic::ppc_cfence: {
11650 assert(ArgStart == 1 &&
"llvm.ppc.cfence must carry a chain argument.");
11651 SDValue Val =
Op.getOperand(ArgStart + 1);
11653 if (Ty == MVT::i128) {
11658 unsigned Opcode = Subtarget.isPPC64() ? PPC::CFENCE8 : PPC::CFENCE;
11661 Opcode,
DL, MVT::Other,
11666 case Intrinsic::ppc_disassemble_dmr: {
11668 "llvm.ppc.disassemble.dmr must carry a chain argument.");
11669 return DAG.
getStore(
Op.getOperand(0),
DL,
Op.getOperand(ArgStart + 2),
11670 Op.getOperand(ArgStart + 1), MachinePointerInfo());
11681 if (!Subtarget.isPPC64())
11684 if (Subtarget.hasP9Vector()) {
11691 int VectorIndex = 0;
11692 if (Subtarget.isLittleEndian())
11702 auto CreateRotateInsert =
11703 [&](
unsigned Opcode, MVT VT,
SDValue Dest,
SDValue Src,
unsigned RotAmt,
11704 unsigned MaskBegin,
11705 std::optional<unsigned> MaskEnd = std::nullopt) ->
SDValue {
11709 if (MaskEnd.has_value())
11721 CreateRotateInsert(PPC::RLWIMI, MVT::i32, Rot, Val32, 24, 0, 7);
11723 return CreateRotateInsert(PPC::RLWIMI, MVT::i32, Swap, Val32, 24, 16, 23);
11736 return CreateRotateInsert(PPC::RLDIMI, MVT::i64, HiSwap, LoSwap, 32, 0);
11744 "Expecting an atomic compare-and-swap here.");
11747 EVT MemVT = AtomicNode->getMemoryVT();
11765 for (
int i = 0, e = AtomicNode->getNumOperands(); i < e; i++)
11766 Ops.push_back(AtomicNode->getOperand(i));
11768 MachineMemOperand *MMO = AtomicNode->getMemOperand();
11769 SDVTList Tys = DAG.
getVTList(MVT::i32, MVT::Other);
11771 (MemVT == MVT::i8) ? PPCISD::ATOMIC_CMP_SWAP_8 : PPCISD::ATOMIC_CMP_SWAP_16;
11778 EVT MemVT =
N->getMemoryVT();
11780 "Expect quadword atomic operations");
11782 unsigned Opc =
N->getOpcode();
11787 SDVTList Tys = DAG.
getVTList(MVT::i64, MVT::i64, MVT::Other);
11790 DAG.
getConstant(Intrinsic::ppc_atomic_load_i128, dl, MVT::i32)};
11791 for (
int I = 1,
E =
N->getNumOperands();
I <
E; ++
I)
11792 Ops.push_back(
N->getOperand(
I));
11794 Ops, MemVT,
N->getMemOperand());
11801 DAG.
getNode(
ISD::OR, dl, {MVT::i128, MVT::Other}, {ValLo, ValHi});
11808 SDVTList Tys = DAG.
getVTList(MVT::Other);
11811 DAG.
getConstant(Intrinsic::ppc_atomic_store_i128, dl, MVT::i32)};
11817 Ops.push_back(ValLo);
11818 Ops.push_back(ValHi);
11819 Ops.push_back(
N->getOperand(2));
11821 N->getMemOperand());
11833 enum DataClassMask {
11835 DC_NEG_INF = 1 << 4,
11836 DC_POS_INF = 1 << 5,
11837 DC_NEG_ZERO = 1 << 2,
11838 DC_POS_ZERO = 1 << 3,
11839 DC_NEG_SUBNORM = 1,
11840 DC_POS_SUBNORM = 1 << 1,
11843 EVT VT =
Op.getValueType();
11845 unsigned TestOp = VT == MVT::f128 ? PPC::XSTSTDCQP
11846 : VT == MVT::f64 ? PPC::XSTSTDCDP
11857 return DAG.
getNOT(Dl, Rev, MVT::i1);
11864 TestOp, Dl, MVT::i32,
11866 DC_NEG_ZERO | DC_POS_ZERO |
11867 DC_NEG_SUBNORM | DC_POS_SUBNORM,
11873 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11879 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11884 Sign = DAG.
getNOT(Dl, Sign, MVT::i1);
11897 bool IsQuiet = Mask &
fcQNan;
11903 if (VT == MVT::f128) {
11907 QuietMask = 0x8000;
11908 }
else if (VT == MVT::f64) {
11909 if (Subtarget.isPPC64()) {
11920 QuietMask = 0x80000;
11921 }
else if (VT == MVT::f32) {
11923 QuietMask = 0x400000;
11939 unsigned NativeMask = 0;
11941 NativeMask |= DC_NAN;
11943 NativeMask |= DC_NEG_INF;
11945 NativeMask |= DC_POS_INF;
11947 NativeMask |= DC_NEG_ZERO;
11949 NativeMask |= DC_POS_ZERO;
11951 NativeMask |= DC_NEG_SUBNORM;
11953 NativeMask |= DC_POS_SUBNORM;
11956 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1,
11958 TestOp, Dl, MVT::i32,
11967 assert(Subtarget.hasP9Vector() &&
"Test data class requires Power9");
11969 uint64_t RHSC =
Op.getConstantOperandVal(1);
11972 if (
LHS.getValueType() == MVT::ppcf128) {
11996 bool Future = Subtarget.isISAFuture();
11999 "Mask predication not supported");
12002 unsigned IID = Future ? Intrinsic::ppc_vsx_lxvrl : Intrinsic::ppc_vsx_lxvl;
12003 unsigned EltBits =
Op->getValueType(0).getScalarType().getSizeInBits();
12007 SDVTList Tys = DAG.
getVTList(
Op->getValueType(0), MVT::Other);
12010 VPLD->getMemoryVT(), VPLD->getMemOperand());
12017 "Mask predication not supported");
12022 Op->getOperand(1).getValueType().getScalarType().getSizeInBits();
12023 bool Future = Subtarget.isISAFuture();
12024 unsigned IID = Future ? Intrinsic::ppc_vsx_stxvrl : Intrinsic::ppc_vsx_stxvl;
12027 VPST->getChain(), DAG.
getConstant(IID, dl, MVT::i32),
12030 SDVTList Tys = DAG.
getVTList(MVT::Other);
12033 VPST->getMemoryVT(), VPST->getMemOperand());
12044 "Unexpected partial reduction");
12067 unsigned EltSize =
Op.getValueType().getScalarSizeInBits();
12069 int64_t
IntVal =
Op.getConstantOperandVal(0);
12070 if (IntVal >= -16 && IntVal <= 15)
12076 if (Subtarget.hasLFIWAX() && Subtarget.hasVSX() &&
12083 MMOMetadata(RLI.AAInfo, RLI.Ranges));
12086 PPCISD::LD_SPLAT, dl, DAG.
getVTList(MVT::v4i32, MVT::Other),
Ops,
12090 return Bits.getValue(0);
12106 !Subtarget.isLittleEndian() && ValVT.
isInteger() &&
12111 64 -
Op.getValueType().getScalarSizeInBits(), dl, ShiftAmountTy);
12119 MachinePointerInfo());
12126 return DAG.
getLoad(
Op.getValueType(), dl,
Store, FIdx, MachinePointerInfo());
12132 "Should only be called for ISD::INSERT_VECTOR_ELT");
12136 EVT VT =
Op.getValueType();
12141 if (VT == MVT::v2f64 &&
C)
12144 if (Subtarget.hasP9Vector()) {
12153 if ((VT == MVT::v4f32) && (V2.
getValueType() == MVT::f32) &&
12159 BitcastLoad,
Op.getOperand(2));
12160 return DAG.
getBitcast(MVT::v4f32, InsVecElt);
12164 if (Subtarget.isISA3_1()) {
12165 if ((VT == MVT::v2i64 || VT == MVT::v2f64) && !Subtarget.isPPC64())
12169 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
12170 VT == MVT::v2i64 || VT == MVT::v4f32 || VT == MVT::v2f64)
12180 if (VT == MVT::v8i16 || VT == MVT::v16i8) {
12183 unsigned InsertAtElement =
C->getZExtValue();
12184 unsigned InsertAtByte = InsertAtElement * BytesInEachElement;
12185 if (Subtarget.isLittleEndian()) {
12186 InsertAtByte = (16 - BytesInEachElement) - InsertAtByte;
12188 return DAG.
getNode(PPCISD::VECINSERT, dl, VT,
V1, Mtvsrz,
12200 EVT VT =
Op.getValueType();
12201 bool IsV1024i1 = VT == MVT::v1024i1;
12202 bool IsV2048i1 = VT == MVT::v2048i1;
12206 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12208 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12209 "Dense Math support required.");
12210 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12219 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12220 MachineMemOperand *NewMMO =
12228 DAG.
getVTList(MVT::v256i1, MVT::Other),
12229 LoadOps, MVT::v256i1, NewMMO);
12234 if (Subtarget.isLittleEndian()) {
12235 std::reverse(Loads.
begin(), Loads.
end());
12236 std::reverse(LoadChains.
begin(), LoadChains.
end());
12248 SDValue Dmr1Value = DMFInsert1024(MoreLoads, dl, DAG);
12254 const SDValue DmrPOps[] = {DmrPRC,
Value, Dmr0Sub, Dmr1Value, Dmr1Sub};
12257 DAG.
getMachineNode(PPC::REG_SEQUENCE, dl, MVT::v2048i1, DmrPOps), 0);
12266 DAG.
getNode(PPCISD::INST512, dl, MVT::v512i1, Pairs[0], Pairs[1]);
12269 DAG.
getNode(PPCISD::INST512HI, dl, MVT::v512i1, Pairs[2], Pairs[3]);
12274 {RC, Lo, LoSub, Hi, HiSub}),
12284 EVT VT =
Op.getValueType();
12286 if (VT == MVT::v1024i1 || VT == MVT::v2048i1)
12287 return LowerDMFVectorLoad(
Op, DAG);
12289 if (VT != MVT::v256i1 && VT != MVT::v512i1)
12293 assert((VT != MVT::v512i1 || Subtarget.hasMMA()) &&
12294 "Type unsupported without MMA");
12295 assert((VT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12296 "Type unsupported without paired vector support");
12300 if (VT == MVT::v256i1 && Subtarget.isISAFuture())
12309 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12311 DAG.
getLoad(MVT::v16i8, dl, LoadChain, BasePtr,
12320 if (Subtarget.isLittleEndian()) {
12321 std::reverse(Loads.
begin(), Loads.
end());
12322 std::reverse(LoadChains.
begin(), LoadChains.
end());
12326 DAG.
getNode(VT == MVT::v512i1 ? PPCISD::ACC_BUILD : PPCISD::PAIR_BUILD,
12342 bool IsV1024i1 = VT == MVT::v1024i1;
12343 bool IsV2048i1 = VT == MVT::v2048i1;
12347 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12349 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12350 "Dense Math support required.");
12351 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12353 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12356 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12361 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12365 MachineSDNode *ExtNode =
12369 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes,
Hi);
12375 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12381 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12387 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12392 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12397 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12402 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12406 MachineSDNode *ExtNode =
12407 DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr0Lo);
12411 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr0Hi);
12414 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr1Lo);
12418 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr1Hi);
12423 if (Subtarget.isLittleEndian())
12426 SDVTList Tys = DAG.
getVTList(MVT::Other);
12428 StoreChain, DAG.
getConstant(Intrinsic::ppc_vsx_stxvp, dl, MVT::i32),
12432 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12433 MachineMemOperand *NewMMO =
12442 MVT::v256i1, NewMMO);
12458 EVT StoreVT =
Value.getValueType();
12460 if (StoreVT == MVT::v1024i1 || StoreVT == MVT::v2048i1)
12461 return LowerDMFVectorStore(
Op, DAG);
12463 if (StoreVT != MVT::v256i1 && StoreVT != MVT::v512i1)
12467 assert((StoreVT != MVT::v512i1 || Subtarget.hasMMA()) &&
12468 "Type unsupported without MMA");
12469 assert((StoreVT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12470 "Type unsupported without paired vector support");
12474 if (StoreVT == MVT::v256i1 && Subtarget.isISAFuture() &&
12482 unsigned NumVecs = 2;
12483 if (StoreVT == MVT::v512i1) {
12484 if (Subtarget.isISAFuture()) {
12485 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12487 PPC::DMXXEXTFDMR512, dl, ReturnTypes,
Op.getOperand(1));
12490 Value2 =
SDValue(ExtNode, 1);
12495 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12496 unsigned VecNum = Subtarget.isLittleEndian() ? NumVecs - 1 - Idx : Idx;
12498 if (Subtarget.isISAFuture()) {
12499 VecNum = Subtarget.isLittleEndian() ? 1 - (Idx % 2) : (Idx % 2);
12500 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
12501 Idx > 1 ? Value2 :
Value,
12504 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
Value,
12508 DAG.
getStore(StoreChain, dl, Elt, BasePtr,
12522 if (
Op.getValueType() == MVT::v4i32) {
12539 LHS,
RHS, DAG, dl, MVT::v4i32);
12542 LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32);
12547 }
else if (
Op.getValueType() == MVT::v16i8) {
12549 bool isLittleEndian = Subtarget.isLittleEndian();
12553 LHS,
RHS, DAG, dl, MVT::v8i16);
12558 LHS,
RHS, DAG, dl, MVT::v8i16);
12566 for (
unsigned i = 0; i != 8; ++i) {
12567 if (isLittleEndian) {
12569 Ops[i*2+1] = 2*i+16;
12572 Ops[i*2+1] = 2*i+1+16;
12575 if (isLittleEndian)
12585 bool IsStrict =
Op->isStrictFPOpcode();
12586 if (
Op.getOperand(IsStrict ? 1 : 0).getValueType() == MVT::f128 &&
12587 !Subtarget.hasP9Vector())
12597 "Should only be called for ISD::FP_EXTEND");
12601 if (
Op.getValueType() != MVT::v2f64 ||
12602 Op.getOperand(0).getValueType() != MVT::v2f32)
12614 "Node should have 2 operands with second one being a constant!");
12626 int DWord = Idx >> 1;
12629 if (Subtarget.isLittleEndian())
12632 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64,
12646 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12648 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12649 LD->getMemoryVT(),
LD->getMemOperand());
12654 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewOp,
12659 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12661 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12662 LD->getMemoryVT(),
LD->getMemOperand());
12663 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewLd,
12674 if (STI.useCRBits())
12691 PPCISD::ADDE,
DL, DAG.
getVTList(SumType, MVT::i32), Zero, Zero, Flag);
12692 if (STI.useCRBits())
12700 SDNode *
N =
Op.getNode();
12701 EVT VT =
N->getValueType(0);
12702 EVT CarryType =
N->getValueType(1);
12703 unsigned Opc =
N->getOpcode();
12705 Opc = IsAdd ? PPCISD::ADDC : PPCISD::SUBC;
12707 N->getOperand(0),
N->getOperand(1));
12719 SDNode *
N =
Op.getNode();
12720 unsigned Opc =
N->getOpcode();
12721 EVT VT =
N->getValueType(0);
12722 EVT CarryType =
N->getValueType(1);
12723 SDValue CarryOp =
N->getOperand(2);
12725 Opc = IsAdd ? PPCISD::ADDE : PPCISD::SUBE;
12731 Op.getOperand(0),
Op.getOperand(1), CarryOp);
12745 EVT VT =
Op.getNode()->getValueType(0);
12771 EVT VT =
Op.getNode()->getValueType(0);
12803 EVT OpVT =
LHS.getValueType();
12804 EVT VT =
Op.getValueType();
12819 unsigned Opcode = PPCISD::SUBC;
12829 Opcode = PPCISD::ADDC;
12836 if (Subtarget.isPPC64() && OpVT != MVT::i64) {
12843 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12863 EVT OpVT =
A.getValueType();
12864 EVT ResVT =
Op.getValueType();
12869 if (Subtarget.isPPC64() && OpVT != MVT::i64) {
12879 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12897 switch (
Op.getOpcode()) {
12918 return LowerSSUBO(
Op, DAG);
12920 return LowerSADDO(
Op, DAG);
12932 return LowerGET_DYNAMIC_AREA_OFFSET(
Op, DAG);
12953 return LowerSET_ROUNDING(
Op, DAG);
12960 case ISD::FSHL:
return LowerFunnelShift(
Op, DAG);
12961 case ISD::FSHR:
return LowerFunnelShift(
Op, DAG);
12973 return LowerFP_ROUND(
Op, DAG);
12987 return LowerINTRINSIC_VOID(
Op, DAG);
12989 return LowerBSWAP(
Op, DAG);
12991 return LowerATOMIC_CMP_SWAP(
Op, DAG);
12993 return LowerATOMIC_LOAD_STORE(
Op, DAG);
12995 return LowerIS_FPCLASS(
Op, DAG);
12998 return LowerADDSUBO(
Op, DAG);
13001 return LowerADDSUBO_CARRY(
Op, DAG);
13003 return LowerUCMP(
Op, DAG);
13005 return LowerABDU(
Op, DAG);
13011 if (
Op->getFlags().hasNoFPExcept())
13015 return LowerVP_LOAD(
Op, DAG);
13016 case ISD::VP_STORE:
13017 return LowerVP_STORE(
Op, DAG);
13019 return LowerPartialReduce(
Op, DAG);
13027 switch (
N->getOpcode()) {
13029 llvm_unreachable(
"Do not know how to custom type legalize this operation!");
13046 if (
N->getConstantOperandVal(1) != Intrinsic::loop_decrement)
13049 assert(
N->getValueType(0) == MVT::i1 &&
13050 "Unexpected result type for CTR decrement intrinsic");
13052 N->getValueType(0));
13062 switch (
N->getConstantOperandVal(0)) {
13063 case Intrinsic::ppc_pack_longdouble:
13065 N->getOperand(2),
N->getOperand(1)));
13067 case Intrinsic::ppc_maxfe:
13068 case Intrinsic::ppc_minfe:
13069 case Intrinsic::ppc_fnmsub:
13070 case Intrinsic::ppc_convert_f128_to_ppcf128:
13077 if (!Subtarget.isSVR4ABI() || Subtarget.isPPC64())
13080 EVT VT =
N->getValueType(0);
13082 if (VT == MVT::i64) {
13095 if (
N->getOperand(
N->isStrictFPOpcode() ? 1 : 0).getValueType() ==
13099 Results.push_back(LoweredValue);
13100 if (
N->isStrictFPOpcode())
13105 if (!
N->getValueType(0).isVector())
13138 return Builder.CreateIntrinsicWithoutFolding(Id, {});
13144 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
13146 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
13147 "Only 8/16/32/64-bit atomic loads supported");
13153 IntID = Intrinsic::ppc_lbarx;
13154 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13157 IntID = Intrinsic::ppc_lharx;
13158 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13161 IntID = Intrinsic::ppc_lwarx;
13164 IntID = Intrinsic::ppc_ldarx;
13168 Builder.CreateIntrinsic(IntID, Addr,
nullptr,
"larx");
13170 return Builder.CreateTruncOrBitCast(
Call, ValueTy);
13181 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
13182 "Only 8/16/32/64-bit atomic loads supported");
13188 IntID = Intrinsic::ppc_stbcx;
13189 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13192 IntID = Intrinsic::ppc_sthcx;
13193 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13196 IntID = Intrinsic::ppc_stwcx;
13199 IntID = Intrinsic::ppc_stdcx;
13203 if (SZ == 8 || SZ == 16)
13204 Val = Builder.CreateZExt(Val, Builder.getInt32Ty());
13206 Value *
Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
13208 return Builder.CreateXor(
Call, Builder.getInt32(1));
13231 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::ppc_cfence,
13241 unsigned BinOpcode,
13242 unsigned CmpOpcode,
13243 unsigned CmpPred)
const {
13248 unsigned AtomicSize =
MI.getOperand(3).getImm();
13250 auto LoadMnemonic = PPC::LDARX;
13251 auto StoreMnemonic = PPC::STDCX;
13252 switch (AtomicSize) {
13256 LoadMnemonic = PPC::LBARX;
13257 StoreMnemonic = PPC::STBCX;
13258 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13261 LoadMnemonic = PPC::LHARX;
13262 StoreMnemonic = PPC::STHCX;
13263 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13266 LoadMnemonic = PPC::LWARX;
13267 StoreMnemonic = PPC::STWCX;
13270 LoadMnemonic = PPC::LDARX;
13271 StoreMnemonic = PPC::STDCX;
13279 if (CmpOpcode == PPC::CMPW && (AtomicSize == 1 || AtomicSize == 2))
13290 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13292 F->insert(It, loopMBB);
13294 F->insert(It, loop2MBB);
13295 F->insert(It, exitMBB);
13301 Register TmpReg = (!BinOpcode) ? incr :
13302 RegInfo.createVirtualRegister( AtomicSize == 8 ? &PPC::G8RCRegClass
13303 : &PPC::GPRCRegClass);
13328 BuildMI(BB, dl,
TII->get(LoadMnemonic), dest)
13333 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13335 if (CmpOpcode == PPC::CMPW && AtomicSize < 4) {
13336 Register ExtReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13337 BuildMI(BB, dl,
TII->get(AtomicSize == 1 ? PPC::EXTSB : PPC::EXTSH),
13367 switch(
MI.getOpcode()) {
13371 return TII->isSignExtended(
MI.getOperand(1).getReg(),
13372 &
MI.getMF()->getRegInfo());
13396 case PPC::EXTSB8_32_64:
13397 case PPC::EXTSB8_rec:
13398 case PPC::EXTSB_rec:
13401 case PPC::EXTSH8_32_64:
13402 case PPC::EXTSH8_rec:
13403 case PPC::EXTSH_rec:
13405 case PPC::EXTSWSLI:
13406 case PPC::EXTSWSLI_32_64:
13407 case PPC::EXTSWSLI_32_64_rec:
13408 case PPC::EXTSWSLI_rec:
13409 case PPC::EXTSW_32:
13410 case PPC::EXTSW_32_64:
13411 case PPC::EXTSW_32_64_rec:
13412 case PPC::EXTSW_rec:
13415 case PPC::SRAWI_rec:
13416 case PPC::SRAW_rec:
13426 unsigned OpIdx,
bool IsByte,
13431 bool IsSignExtended =
13434 if (!IsSignExtended) {
13435 Register ValueReg =
RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13437 TII->get(IsByte ? PPC::EXTSB : PPC::EXTSH), ValueReg)
13439 MI.getOperand(OpIdx).setReg(ValueReg);
13445 unsigned CmpOpcode,
unsigned CmpPred)
const {
13449 assert(!Subtarget.hasPartwordAtomics() &&
13450 "Assumes that part-word atomics are not available");
13458 const bool is8bit =
MI.getOperand(3).getImm() == 1;
13459 if (CmpOpcode == PPC::CMPW)
13467 bool is64bit = Subtarget.isPPC64();
13468 bool isLittleEndian = Subtarget.isLittleEndian();
13469 unsigned ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
13480 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13482 F->insert(It, loopMBB);
13484 F->insert(It, loop2MBB);
13485 F->insert(It, exitMBB);
13491 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13494 Register PtrReg = RegInfo.createVirtualRegister(RC);
13495 Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
13497 isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
13498 Register Incr2Reg = RegInfo.createVirtualRegister(GPRC);
13499 Register MaskReg = RegInfo.createVirtualRegister(GPRC);
13500 Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
13501 Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
13502 Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
13503 Register Tmp3Reg = RegInfo.createVirtualRegister(GPRC);
13504 Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
13505 Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
13506 Register SrwDestReg = RegInfo.createVirtualRegister(GPRC);
13509 (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(GPRC);
13536 if (ptrA != ZeroReg) {
13537 Ptr1Reg = RegInfo.createVirtualRegister(RC);
13538 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
13546 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
13547 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
13550 .
addImm(is8bit ? 28 : 27);
13551 if (!isLittleEndian)
13552 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
13554 .
addImm(is8bit ? 24 : 16);
13556 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
13561 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
13571 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
13575 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
13580 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
13584 BuildMI(BB, dl,
TII->get(BinOpcode), TmpReg)
13587 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
13594 Register SReg = RegInfo.createVirtualRegister(GPRC);
13595 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13599 unsigned ValueReg = SReg;
13600 unsigned CmpReg = Incr2Reg;
13601 if (CmpOpcode == PPC::CMPW) {
13602 ValueReg = RegInfo.createVirtualRegister(GPRC);
13603 BuildMI(BB, dl,
TII->get(PPC::SRW), ValueReg)
13606 Register ValueSReg = RegInfo.createVirtualRegister(GPRC);
13607 BuildMI(BB, dl,
TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueSReg)
13609 ValueReg = ValueSReg;
13641 .
addImm(is8bit ? 24 : 16)
13662 Register DstReg =
MI.getOperand(0).getReg();
13664 assert(
TRI->isTypeLegalForClass(*RC, MVT::i32) &&
"Invalid destination!");
13669 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13670 "Invalid Pointer Size!");
13719 Register BufReg =
MI.getOperand(1).getReg();
13721 if (Subtarget.is64BitELFABI()) {
13734 BaseReg = Subtarget.isPPC64() ? PPC::X1 : PPC::R1;
13736 BaseReg = Subtarget.isPPC64() ? PPC::BP8 : PPC::BP;
13739 TII->get(Subtarget.isPPC64() ? PPC::STD : PPC::STW))
13762 TII->get(Subtarget.isPPC64() ? PPC::MFLR8 : PPC::MFLR), LabelReg);
13765 if (Subtarget.isPPC64()) {
13783 TII->get(PPC::PHI), DstReg)
13787 MI.eraseFromParent();
13801 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13802 "Invalid Pointer Size!");
13805 (PVT == MVT::i64) ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13808 unsigned FP = (PVT == MVT::i64) ? PPC::X31 : PPC::R31;
13809 unsigned SP = (PVT == MVT::i64) ? PPC::X1 : PPC::R1;
13823 Register BufReg =
MI.getOperand(0).getReg();
13828 if (PVT == MVT::i64) {
13840 if (PVT == MVT::i64) {
13852 if (PVT == MVT::i64) {
13864 if (PVT == MVT::i64) {
13876 if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) {
13886 TII->get(PVT == MVT::i64 ? PPC::MTCTR8 : PPC::MTCTR)).
addReg(Tmp);
13889 MI.eraseFromParent();
13905 "Unexpected stack alignment");
13909 unsigned StackProbeSize =
13912 StackProbeSize &= ~(StackAlign - 1);
13913 return StackProbeSize ? StackProbeSize : StackAlign;
13925 const bool isPPC64 = Subtarget.isPPC64();
13957 MF->
insert(MBBIter, TestMBB);
13958 MF->
insert(MBBIter, BlockMBB);
13959 MF->
insert(MBBIter, TailMBB);
13964 Register DstReg =
MI.getOperand(0).getReg();
13965 Register NegSizeReg =
MI.getOperand(1).getReg();
13977 isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_64 : PPC::PREPARE_PROBED_ALLOCA_32;
13983 ProbeOpc = isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_64
13984 : PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_32;
13986 .
addDef(ActualNegSizeReg)
13988 .
add(
MI.getOperand(2))
13989 .
add(
MI.getOperand(3));
13995 .
addReg(ActualNegSizeReg);
13998 int64_t NegProbeSize = -(int64_t)ProbeSize;
14004 .
addImm(NegProbeSize >> 16);
14008 .
addImm(NegProbeSize & 0xFFFF);
14017 .
addReg(ActualNegSizeReg)
14026 .
addReg(ActualNegSizeReg);
14036 BuildMI(TestMBB,
DL,
TII->get(isPPC64 ? PPC::CMPD : PPC::CMPW), CmpResult)
14063 TII->get(isPPC64 ? PPC::DYNAREAOFFSET8 : PPC::DYNAREAOFFSET),
14064 MaxCallFrameSizeReg)
14065 .
add(
MI.getOperand(2))
14066 .
add(
MI.getOperand(3));
14067 BuildMI(TailMBB,
DL,
TII->get(isPPC64 ? PPC::ADD8 : PPC::ADD4), DstReg)
14069 .
addReg(MaxCallFrameSizeReg);
14075 MBB->addSuccessor(TestMBB);
14078 MI.eraseFromParent();
14080 ++NumDynamicAllocaProbed;
14088static bool IsSelect(
unsigned Opcode,
bool CheckOnlyCC =
false) {
14091 case PPC::SELECT_CC_I4:
14092 case PPC::SELECT_CC_I8:
14093 case PPC::SELECT_CC_F4:
14094 case PPC::SELECT_CC_F8:
14095 case PPC::SELECT_CC_F16:
14096 case PPC::SELECT_CC_VRRC:
14097 case PPC::SELECT_CC_VSFRC:
14098 case PPC::SELECT_CC_VSSRC:
14099 case PPC::SELECT_CC_VSRC:
14100 case PPC::SELECT_CC_SPE4:
14101 case PPC::SELECT_CC_SPE:
14104 case PPC::SELECT_I4:
14105 case PPC::SELECT_I8:
14106 case PPC::SELECT_F4:
14107 case PPC::SELECT_F8:
14108 case PPC::SELECT_F16:
14109 case PPC::SELECT_SPE:
14110 case PPC::SELECT_SPE4:
14111 case PPC::SELECT_VRRC:
14112 case PPC::SELECT_VSFRC:
14113 case PPC::SELECT_VSSRC:
14114 case PPC::SELECT_VSRC:
14115 return !CheckOnlyCC;
14131 assert(
IsSelect(
MI.getOpcode()) &&
"Instruction must be a SELECT variant");
14134 if (Subtarget.hasISEL() &&
14135 (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
14136 MI.getOpcode() == PPC::SELECT_CC_I8 ||
14137 MI.getOpcode() == PPC::SELECT_I4 ||
MI.getOpcode() == PPC::SELECT_I8)) {
14139 if (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
14140 MI.getOpcode() == PPC::SELECT_CC_I8)
14141 Cond.push_back(
MI.getOperand(4));
14144 Cond.push_back(
MI.getOperand(1));
14147 TII->insertSelect(*BB,
MI, dl,
MI.getOperand(0).getReg(),
Cond,
14148 MI.getOperand(2).getReg(),
MI.getOperand(3).getReg());
14149 MI.eraseFromParent();
14162 F->insert(It, copy0MBB);
14163 F->insert(It, sinkMBB);
14171 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
14187 .
addImm(
MI.getOperand(4).getImm())
14188 .
addReg(
MI.getOperand(1).getReg())
14192 .
addReg(
MI.getOperand(1).getReg())
14202 .
addReg(
MI.getOperand(3).getReg())
14204 .
addReg(
MI.getOperand(2).getReg())
14206 MI.eraseFromParent();
14221 loop1MBB =
F->CreateMachineBasicBlock(LLVM_BB);
14222 loop2MBB =
F->CreateMachineBasicBlock(LLVM_BB);
14223 exitMBB =
F->CreateMachineBasicBlock(LLVM_BB);
14224 F->insert(It, loop1MBB);
14225 F->insert(It, loop2MBB);
14226 F->insert(It, exitMBB);
14261 bool is64bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
14263 unsigned LoadMnemonic = PPC::LDARX;
14264 unsigned StoreMnemonic = PPC::STDCX;
14265 switch (
MI.getOpcode()) {
14268 case PPC::ATOMIC_CMP_SWAP_I8:
14269 LoadMnemonic = PPC::LBARX;
14270 StoreMnemonic = PPC::STBCX;
14271 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14273 case PPC::ATOMIC_CMP_SWAP_I16:
14274 LoadMnemonic = PPC::LHARX;
14275 StoreMnemonic = PPC::STHCX;
14276 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14278 case PPC::ATOMIC_CMP_SWAP_I32:
14279 LoadMnemonic = PPC::LWARX;
14280 StoreMnemonic = PPC::STWCX;
14282 case PPC::ATOMIC_CMP_SWAP_I64:
14283 LoadMnemonic = PPC::LDARX;
14284 StoreMnemonic = PPC::STDCX;
14292 Register oldval =
MI.getOperand(3).getReg();
14293 Register newval =
MI.getOperand(4).getReg();
14307 BuildMI(BB, dl,
TII->get(is64bit ? PPC::CMPD : PPC::CMPW), CrReg)
14375 bool is64bit = Subtarget.isPPC64();
14377 bool is8bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8;
14382 Register oldval =
MI.getOperand(3).getReg();
14383 Register newval =
MI.getOperand(4).getReg();
14391 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
14396 return RegInfo.createVirtualRegister(RC);
14400 Register Shift1Reg = createVReg(GPRC);
14401 Register ShiftReg = isLittleEndian ? Shift1Reg : createVReg(GPRC);
14402 Register NewVal2Reg = createVReg(GPRC);
14403 Register NewVal3Reg = createVReg(GPRC);
14404 Register OldVal2Reg = createVReg(GPRC);
14405 Register OldVal3Reg = createVReg(GPRC);
14406 Register MaskReg = createVReg(GPRC);
14407 Register Mask2Reg = createVReg(GPRC);
14408 Register Mask3Reg = createVReg(GPRC);
14409 Register Tmp2Reg = createVReg(GPRC);
14410 Register Tmp4Reg = createVReg(GPRC);
14411 Register TmpDestReg = createVReg(GPRC);
14412 Register TmpReg = createVReg(GPRC);
14413 Register ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
14414 Register CrReg = createVReg(&PPC::CRRCRegClass);
14418 if (ptrA != ZeroReg) {
14419 Ptr1Reg = createVReg(RC);
14420 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
14427 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
14428 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
14431 .
addImm(is8bit ? 28 : 27);
14432 if (!isLittleEndian)
14433 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
14435 .
addImm(is8bit ? 24 : 16);
14437 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
14442 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
14449 BuildMI(BB, dl,
TII->get(PPC::SLW), NewVal2Reg)
14452 BuildMI(BB, dl,
TII->get(PPC::SLW), OldVal2Reg)
14459 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
14463 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
14466 BuildMI(BB, dl,
TII->get(PPC::AND), NewVal3Reg)
14469 BuildMI(BB, dl,
TII->get(PPC::AND), OldVal3Reg)
14479 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
14500 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
14545 switch (
MI.getOpcode()) {
14546 case TargetOpcode::STACKMAP:
14548 case TargetOpcode::PATCHPOINT:
14554 if (Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls())
14558 case PPC::EH_SjLj_SetJmp32:
14559 case PPC::EH_SjLj_SetJmp64:
14562 case PPC::EH_SjLj_LongJmp32:
14563 case PPC::EH_SjLj_LongJmp64:
14566 case PPC::ReadTB: {
14582 F->insert(It, readMBB);
14583 F->insert(It, sinkMBB);
14594 Register ReadAgainReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
14602 Register CmpReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14604 BuildMI(BB, dl,
TII->get(PPC::CMPW), CmpReg)
14616 case PPC::ATOMIC_LOAD_ADD_NOWP:
14619 case PPC::ATOMIC_LOAD_ADD:
14622 case PPC::ATOMIC_LOAD_ADD_I64:
14625 case PPC::ATOMIC_LOAD_AND_NOWP:
14628 case PPC::ATOMIC_LOAD_AND:
14631 case PPC::ATOMIC_LOAD_AND_I64:
14634 case PPC::ATOMIC_LOAD_OR_NOWP:
14637 case PPC::ATOMIC_LOAD_OR:
14640 case PPC::ATOMIC_LOAD_OR_I64:
14643 case PPC::ATOMIC_LOAD_XOR_NOWP:
14646 case PPC::ATOMIC_LOAD_XOR:
14649 case PPC::ATOMIC_LOAD_XOR_I64:
14652 case PPC::ATOMIC_LOAD_NAND_NOWP:
14655 case PPC::ATOMIC_LOAD_NAND:
14658 case PPC::ATOMIC_LOAD_NAND_I64:
14661 case PPC::ATOMIC_LOAD_SUB_NOWP:
14664 case PPC::ATOMIC_LOAD_SUB:
14667 case PPC::ATOMIC_LOAD_SUB_I64:
14670 case PPC::ATOMIC_LOAD_MIN_NOWP:
14673 case PPC::ATOMIC_LOAD_MIN:
14676 case PPC::ATOMIC_LOAD_MIN_I64:
14679 case PPC::ATOMIC_LOAD_MAX_NOWP:
14682 case PPC::ATOMIC_LOAD_MAX:
14685 case PPC::ATOMIC_LOAD_MAX_I64:
14688 case PPC::ATOMIC_LOAD_UMIN_NOWP:
14691 case PPC::ATOMIC_LOAD_UMIN:
14694 case PPC::ATOMIC_LOAD_UMIN_I64:
14697 case PPC::ATOMIC_LOAD_UMAX_NOWP:
14700 case PPC::ATOMIC_LOAD_UMAX:
14703 case PPC::ATOMIC_LOAD_UMAX_I64:
14706 case PPC::ATOMIC_SWAP_NOWP:
14709 case PPC::ATOMIC_SWAP:
14710 case PPC::ATOMIC_SWAP_I64:
14713 case PPC::ATOMIC_CMP_SWAP_I32:
14714 case PPC::ATOMIC_CMP_SWAP_I64:
14715 case PPC::ATOMIC_CMP_SWAP_I8:
14716 case PPC::ATOMIC_CMP_SWAP_I16: {
14718 bool useHardware =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
14719 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64 ||
14720 (Subtarget.hasPartwordAtomics() &&
14721 (
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 ||
14722 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16));
14730 case PPC::FADDrtz: {
14740 Register MFFSReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14755 auto MIB =
BuildMI(*BB,
MI, dl,
TII->get(PPC::FADD), Dest)
14765 case PPC::ANDI_rec_1_EQ_BIT:
14766 case PPC::ANDI_rec_1_GT_BIT:
14767 case PPC::ANDI_rec_1_EQ_BIT8:
14768 case PPC::ANDI_rec_1_GT_BIT8: {
14769 unsigned Opcode = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
14770 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8)
14773 bool IsEQ = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
14774 MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8);
14777 Register Dest = RegInfo.createVirtualRegister(
14778 Opcode == PPC::ANDI_rec ? &PPC::GPRCRegClass : &PPC::G8RCRegClass);
14782 .
addReg(
MI.getOperand(1).getReg())
14785 MI.getOperand(0).getReg())
14786 .
addReg(IsEQ ? PPC::CR0EQ : PPC::CR0GT);
14789 case PPC::TCHECK_RET: {
14792 Register CRReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14795 MI.getOperand(0).getReg())
14799 case PPC::TBEGIN_RET: {
14801 unsigned Imm =
MI.getOperand(1).getImm();
14804 MI.getOperand(0).getReg())
14808 case PPC::SETRNDi: {
14810 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14814 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14816 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14827 unsigned Mode =
MI.getOperand(1).getImm();
14828 BuildMI(*BB,
MI, dl,
TII->get((Mode & 1) ? PPC::MTFSB1 : PPC::MTFSB0))
14832 BuildMI(*BB,
MI, dl,
TII->get((Mode & 2) ? PPC::MTFSB1 : PPC::MTFSB0))
14837 case PPC::SETRND: {
14845 auto copyRegFromG8RCOrF8RC = [&] (
unsigned DestReg,
unsigned SrcReg) {
14846 if (Subtarget.hasDirectMove()) {
14847 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::COPY), DestReg)
14851 unsigned StoreOp = PPC::STD, LoadOp = PPC::LFD;
14854 if (RC == &PPC::F8RCRegClass) {
14856 assert((RegInfo.getRegClass(DestReg) == &PPC::G8RCRegClass) &&
14857 "Unsupported RegClass.");
14859 StoreOp = PPC::STFD;
14863 assert((RegInfo.getRegClass(SrcReg) == &PPC::G8RCRegClass) &&
14864 (RegInfo.getRegClass(DestReg) == &PPC::F8RCRegClass) &&
14865 "Unsupported RegClass.");
14898 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14901 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14913 Register OldFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14915 copyRegFromG8RCOrF8RC(OldFPSCRTmpReg, OldFPSCRReg);
14917 Register ImDefReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14918 Register ExtSrcReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14923 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), ImDefReg);
14924 BuildMI(*BB,
MI, dl,
TII->get(PPC::INSERT_SUBREG), ExtSrcReg)
14929 Register NewFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14930 BuildMI(*BB,
MI, dl,
TII->get(PPC::RLDIMI), NewFPSCRTmpReg)
14936 Register NewFPSCRReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14937 copyRegFromG8RCOrF8RC(NewFPSCRReg, NewFPSCRTmpReg);
14948 case PPC::SETFLM: {
14952 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14954 BuildMI(*BB,
MI, Dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14956 BuildMI(*BB,
MI, Dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14959 Register NewFPSCRReg =
MI.getOperand(1).getReg();
14967 case PPC::PROBED_ALLOCA_32:
14968 case PPC::PROBED_ALLOCA_64:
14971 case PPC::SPLIT_QUADWORD: {
14978 .
addUse(Src, {}, PPC::sub_gp8_x1);
14981 .
addUse(Src, {}, PPC::sub_gp8_x0);
14984 case PPC::LQX_PSEUDO:
14985 case PPC::STQX_PSEUDO: {
14991 F->getRegInfo().createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass);
14997 MI.getOpcode() == PPC::LQX_PSEUDO ?
TII->get(PPC::LQ)
14998 :
TII->get(PPC::STQ))
15008 MI.eraseFromParent();
15021 int RefinementSteps = Subtarget.hasRecipPrec() ? 1 : 3;
15024 return RefinementSteps;
15031 EVT VT =
Op.getValueType();
15034 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX())))
15058PPCTargetLowering::getSqrtResultForDenormInput(
SDValue Op,
15061 EVT VT =
Op.getValueType();
15062 if (VT != MVT::f64 &&
15063 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX()))
15066 return DAG.
getNode(PPCISD::FSQRT, SDLoc(
Op), VT,
Op);
15070 int Enabled,
int &RefinementSteps,
15071 bool &UseOneConstNR,
15072 bool Reciprocal)
const {
15074 if ((VT == MVT::f32 && Subtarget.hasFRSQRTES()) ||
15075 (VT == MVT::f64 && Subtarget.hasFRSQRTE()) ||
15076 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
15077 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
15083 UseOneConstNR = !Subtarget.needsTwoConstNR();
15084 return DAG.
getNode(PPCISD::FRSQRTE, SDLoc(Operand), VT, Operand);
15091 int &RefinementSteps)
const {
15093 if ((VT == MVT::f32 && Subtarget.hasFRES()) ||
15094 (VT == MVT::f64 && Subtarget.hasFRE()) ||
15095 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
15096 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
15099 return DAG.
getNode(PPCISD::FRE, SDLoc(Operand), VT, Operand);
15115 switch (Subtarget.getCPUDirective()) {
15142 unsigned Bytes,
int Dist,
15156 if (FS != BFS || FS != (
int)Bytes)
return false;
15161 int64_t Offset1 = 0, Offset2 = 0;
15164 if (Base1 == Base2 && Offset1 == (Offset2 + Dist * Bytes))
15174 if (isGA1 && isGA2 && GV1 == GV2)
15175 return Offset1 == (Offset2 + Dist*Bytes);
15182 unsigned Bytes,
int Dist,
15185 EVT VT = LS->getMemoryVT();
15192 switch (
N->getConstantOperandVal(1)) {
15193 default:
return false;
15194 case Intrinsic::ppc_altivec_lvx:
15195 case Intrinsic::ppc_altivec_lvxl:
15196 case Intrinsic::ppc_vsx_lxvw4x:
15197 case Intrinsic::ppc_vsx_lxvw4x_be:
15200 case Intrinsic::ppc_vsx_lxvd2x:
15201 case Intrinsic::ppc_vsx_lxvd2x_be:
15204 case Intrinsic::ppc_altivec_lvebx:
15207 case Intrinsic::ppc_altivec_lvehx:
15210 case Intrinsic::ppc_altivec_lvewx:
15220 switch (
N->getConstantOperandVal(1)) {
15221 default:
return false;
15222 case Intrinsic::ppc_altivec_stvx:
15223 case Intrinsic::ppc_altivec_stvxl:
15224 case Intrinsic::ppc_vsx_stxvw4x:
15227 case Intrinsic::ppc_vsx_stxvd2x:
15230 case Intrinsic::ppc_vsx_stxvw4x_be:
15233 case Intrinsic::ppc_vsx_stxvd2x_be:
15236 case Intrinsic::ppc_altivec_stvebx:
15239 case Intrinsic::ppc_altivec_stvehx:
15242 case Intrinsic::ppc_altivec_stvewx:
15259 SDValue Chain = LD->getChain();
15260 EVT VT = LD->getMemoryVT();
15269 while (!Queue.empty()) {
15270 SDNode *ChainNext = Queue.pop_back_val();
15271 if (!Visited.
insert(ChainNext).second)
15278 if (!Visited.
count(ChainLD->getChain().getNode()))
15279 Queue.push_back(ChainLD->getChain().getNode());
15281 for (
const SDUse &O : ChainNext->
ops())
15282 if (!Visited.
count(O.getNode()))
15283 Queue.push_back(O.getNode());
15285 LoadRoots.
insert(ChainNext);
15296 for (
SDNode *
I : LoadRoots) {
15297 Queue.push_back(
I);
15299 while (!Queue.empty()) {
15300 SDNode *LoadRoot = Queue.pop_back_val();
15301 if (!Visited.
insert(LoadRoot).second)
15313 Queue.push_back(U);
15346 auto Final = Shifted;
15357 DAGCombinerInfo &DCI)
const {
15360 SelectionDAG &DAG = DCI.DAG;
15365 if (!DCI.isAfterLegalizeDAG())
15370 for (
const SDNode *U :
N->users())
15375 auto OpSize =
N->getOperand(0).getValueSizeInBits();
15379 if (OpSize <
Size) {
15397 DAGCombinerInfo &DCI)
const {
15398 SelectionDAG &DAG = DCI.DAG;
15401 assert(Subtarget.useCRBits() &&
"Expecting to be tracking CR bits");
15412 N->getValueType(0) != MVT::i1)
15415 if (
N->getOperand(0).getValueType() != MVT::i32 &&
15416 N->getOperand(0).getValueType() != MVT::i64)
15426 unsigned OpBits =
N->getOperand(0).getValueSizeInBits();
15437 return (
N->getOpcode() ==
ISD::SETCC ? ConvertSETCCToSubtract(
N, DCI)
15460 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15461 N->getOperand(0).getOpcode() !=
ISD::OR &&
15462 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15472 N->getOperand(1).getOpcode() !=
ISD::AND &&
15473 N->getOperand(1).getOpcode() !=
ISD::OR &&
15474 N->getOperand(1).getOpcode() !=
ISD::XOR &&
15485 SmallPtrSet<SDNode *, 16> Visited;
15487 for (
unsigned i = 0; i < 2; ++i) {
15491 N->getOperand(i).getOperand(0).getValueType() == MVT::i1) ||
15503 while (!BinOps.
empty()) {
15511 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15545 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15549 for (
const SDNode *User : Inputs[i].
getNode()->
users()) {
15550 if (User !=
N && !Visited.
count(User))
15559 if (
User->getOperand(0) == Inputs[i])
15562 if (
User->getOperand(0) == Inputs[i] ||
15563 User->getOperand(1) == Inputs[i])
15569 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15570 for (
const SDNode *User : PromOps[i].
getNode()->
users()) {
15571 if (User !=
N && !Visited.
count(User))
15580 if (
User->getOperand(0) == PromOps[i])
15583 if (
User->getOperand(0) == PromOps[i] ||
15584 User->getOperand(1) == PromOps[i])
15591 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15600 std::list<HandleSDNode> PromOpHandles;
15601 for (
auto &PromOp : PromOps)
15602 PromOpHandles.emplace_back(PromOp);
15609 while (!PromOpHandles.empty()) {
15610 SDValue PromOp = PromOpHandles.back().getValue();
15611 PromOpHandles.pop_back();
15620 PromOpHandles.emplace_front(PromOp);
15634 default:
C = 0;
break;
15647 PromOpHandles.emplace_front(PromOp);
15654 for (
unsigned i = 0; i < 2; ++i)
15664 return N->getOperand(0);
15672 DAGCombinerInfo &DCI)
const {
15673 SelectionDAG &DAG = DCI.DAG;
15690 if (
N->getValueType(0) != MVT::i32 &&
15691 N->getValueType(0) != MVT::i64)
15694 if (!((
N->getOperand(0).getValueType() == MVT::i1 && Subtarget.useCRBits()) ||
15695 (
N->getOperand(0).getValueType() == MVT::i32 && Subtarget.isPPC64())))
15698 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15699 N->getOperand(0).getOpcode() !=
ISD::OR &&
15700 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15707 SmallPtrSet<SDNode *, 16> Visited;
15711 while (!BinOps.
empty()) {
15719 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15745 DenseMap<SDNode *, EVT> SelectTruncOp[2];
15750 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15755 if (User !=
N && !Visited.
count(User))
15761 if (
User->getOperand(0) == Inputs[i])
15762 SelectTruncOp[0].
insert(std::make_pair(User,
15763 User->getOperand(0).getValueType()));
15765 if (
User->getOperand(0) == Inputs[i])
15766 SelectTruncOp[0].
insert(std::make_pair(User,
15767 User->getOperand(0).getValueType()));
15768 if (
User->getOperand(1) == Inputs[i])
15769 SelectTruncOp[1].
insert(std::make_pair(User,
15770 User->getOperand(1).getValueType()));
15775 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15777 if (User !=
N && !Visited.
count(User))
15783 if (
User->getOperand(0) == PromOps[i])
15784 SelectTruncOp[0].
insert(std::make_pair(User,
15785 User->getOperand(0).getValueType()));
15787 if (
User->getOperand(0) == PromOps[i])
15788 SelectTruncOp[0].
insert(std::make_pair(User,
15789 User->getOperand(0).getValueType()));
15790 if (
User->getOperand(1) == PromOps[i])
15791 SelectTruncOp[1].
insert(std::make_pair(User,
15792 User->getOperand(1).getValueType()));
15797 unsigned PromBits =
N->getOperand(0).getValueSizeInBits();
15798 bool ReallyNeedsExt =
false;
15802 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15807 Inputs[i].getOperand(0).getValueSizeInBits();
15808 assert(PromBits < OpBits &&
"Truncation not to a smaller bit count?");
15813 OpBits-PromBits))) ||
15816 (OpBits-(PromBits-1)))) {
15817 ReallyNeedsExt =
true;
15825 std::list<HandleSDNode> PromOpHandles;
15826 for (
auto &PromOp : PromOps)
15827 PromOpHandles.emplace_back(PromOp);
15831 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15838 SDValue InSrc = Inputs[i].getOperand(0);
15856 while (!PromOpHandles.empty()) {
15858 PromOpHandles.pop_back();
15862 default:
C = 0;
break;
15875 PromOpHandles.emplace_front(PromOp);
15885 (SelectTruncOp[1].count(PromOp.
getNode()) &&
15887 PromOpHandles.emplace_front(PromOp);
15895 for (
unsigned i = 0; i < 2; ++i) {
15913 auto SI0 = SelectTruncOp[0].
find(PromOp.
getNode());
15914 if (SI0 != SelectTruncOp[0].
end())
15916 auto SI1 = SelectTruncOp[1].
find(PromOp.
getNode());
15917 if (SI1 != SelectTruncOp[1].
end())
15926 if (!ReallyNeedsExt)
15927 return N->getOperand(0);
15934 N->getValueSizeInBits(0), PromBits),
15935 dl,
N->getValueType(0)));
15938 "Invalid extension type");
15941 DAG.
getConstant(
N->getValueSizeInBits(0) - PromBits, dl, ShiftAmountTy);
15951 auto isValidForConvert = [IsPPC64](
SDValue &Operand) {
15960 const APInt &Val =
C->getAPIntValue();
15966 if (IsPPC64 && Val.
ult(1ULL << 16))
15980 if (LoadNode->isVolatile())
16001 return (isValidForConvert(
LHS) && isValidForConvert(
RHS));
16011 "CC mus be ISD::SETNE or ISD::SETEQ");
16013 auto getV16i8Load = [&](
const SDValue &Operand) {
16031 LoadNode->getBasePtr(), NewMMO);
16072 SDValue LHSVec = getV16i8Load(
N->getOperand(0));
16073 SDValue RHSVec = getV16i8Load(
N->getOperand(1));
16076 DAG.
getConstant(Intrinsic::ppc_altivec_vcmpequb_p,
DL, MVT::i32);
16079 IntrID, CRSel, LHSVec, RHSVec);
16082 return DAG.
getSetCC(
DL,
N->getValueType(0), PredResult,
16100 auto IsAndWithOne = [](
SDValue &V) {
16111 auto IsCompareWithZero = [](
SDValue &V) {
16118 return (IsAndWithOne(
LHS) && IsCompareWithZero(
RHS)) ||
16119 (IsAndWithOne(
RHS) && IsCompareWithZero(
LHS));
16136 auto MakeXor1 = [&](
SDValue V) {
16137 EVT VT = V.getValueType();
16144 return MakeXor1(
LHS);
16147 return MakeXor1(
RHS);
16164 DAGCombinerInfo &DCI)
const {
16165 if (Subtarget.isISA3_1())
16168 EVT VT =
N->getValueType(0);
16169 if (VT != MVT::i32 && (VT != MVT::i64 || !Subtarget.isPPC64()))
16185 SelectionDAG &DAG = DCI.DAG;
16187 EVT XVT =
X.getValueType();
16191 MVT OpVT = Subtarget.isPPC64() ? MVT::i64 : MVT::i32;
16204 Addc, Addc, Carry);
16207 if (OpVT == MVT::i64 && VT == MVT::i32)
16214 DAGCombinerInfo &DCI)
const {
16216 "Should be called with a SETCC node");
16238 SelectionDAG &DAG = DCI.DAG;
16239 EVT VT =
N->getValueType(0);
16240 EVT OpVT =
LHS.getValueType();
16258 if (Subtarget.hasAltivec() &&
16263 return DAGCombineTruncBoolExt(
N, DCI);
16270 Op.getValueType() == MVT::f64;
16282combineElementTruncationToVectorTruncation(
SDNode *
N,
16283 DAGCombinerInfo &DCI)
const {
16285 "Should be called with a BUILD_VECTOR node");
16287 SelectionDAG &DAG = DCI.DAG;
16290 SDValue FirstInput =
N->getOperand(0);
16292 "The input operand must be an fp-to-int conversion.");
16297 if (FirstConversion == PPCISD::FCTIDZ ||
16298 FirstConversion == PPCISD::FCTIDUZ ||
16299 FirstConversion == PPCISD::FCTIWZ ||
16300 FirstConversion == PPCISD::FCTIWUZ) {
16301 bool IsSplat =
true;
16302 bool Is32Bit = FirstConversion == PPCISD::FCTIWZ ||
16303 FirstConversion == PPCISD::FCTIWUZ;
16306 EVT TargetVT =
N->getValueType(0);
16307 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
16308 SDValue NextOp =
N->getOperand(i);
16309 if (NextOp.
getOpcode() != PPCISD::MFVSR)
16312 if (NextConversion != FirstConversion)
16320 if (
N->getOperand(i) != FirstInput)
16331 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
16332 SDValue In =
N->getOperand(i).getOperand(0);
16342 Ops.push_back(Trunc);
16345 Ops.push_back(
In.isUndef() ? DAG.
getUNDEF(SrcVT) :
In.getOperand(0));
16349 if (FirstConversion == PPCISD::FCTIDZ ||
16350 FirstConversion == PPCISD::FCTIWZ)
16355 EVT NewVT = TargetVT == MVT::v2i64 ? MVT::v2f64 : MVT::v4f32;
16357 return DAG.
getNode(Opcode, dl, TargetVT, BV);
16375 static const APInt BasePattern =
APInt(128, 0x8000000000000000ULL) << 64;
16379 if (FullVal == BasePattern)
16380 return std::make_tuple(Uim,
uint8_t{0});
16383 if (FullVal ==
APInt(128, 1))
16384 return std::make_tuple(Uim,
uint8_t{127});
16386 return std::nullopt;
16406 "Expected a BuildVectorSDNode in combineBVLoadsSpecialValue");
16410 EVT VT =
Op.getValueType();
16411 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
16425 for (
const SDValue &Operand :
Op.getNode()->op_values()) {
16435 for (
unsigned Index = 0;
Index < NumElems; ++
Index) {
16439 uint64_t ElemValue =
C->getZExtValue();
16443 ElemValue &= ((1ULL << ElemBits) - 1);
16447 (IsLittleEndian) ? (Index * ElemBits) : (128 - (
Index + 1) * ElemBits);
16450 APInt ElemAPInt(128, ElemValue);
16451 ElemAPInt <<= BitPos;
16454 FullVal |= ElemAPInt;
16461 const auto &[Uim, ShiftAmount] = *UIMOpt;
16465 if (ShiftAmount == 0) {
16470 <<
"combineBVLoadsSpecialValue: Instruction Emitted ";
16471 LxvkqInstr.
dump());
16475 assert(ShiftAmount == 127 &&
"Unexpected lxvkq shift amount value");
16487 DAG.
getMachineNode(PPC::VSRQ, Dl, VT, ShiftAmountVec, ShiftAmountVec),
16490 <<
"\n combineBVLoadsSpecialValue: Instruction Emitted ";
16506 "Should be called with a BUILD_VECTOR node");
16511 if (!
N->getValueType(0).getVectorElementType().isByteSized())
16514 bool InputsAreConsecutiveLoads =
true;
16515 bool InputsAreReverseConsecutive =
true;
16516 unsigned ElemSize =
N->getValueType(0).getScalarType().getStoreSize();
16517 SDValue FirstInput =
N->getOperand(0);
16518 bool IsRoundOfExtLoad =
false;
16528 N->getNumOperands() == 1)
16531 if (!IsRoundOfExtLoad)
16536 for (
int i = 1, e =
N->getNumOperands(); i < e; ++i) {
16538 if (IsRoundOfExtLoad &&
N->getOperand(i).getOpcode() !=
ISD::FP_ROUND)
16541 SDValue NextInput = IsRoundOfExtLoad ?
N->getOperand(i).getOperand(0) :
16547 IsRoundOfExtLoad ?
N->getOperand(i-1).getOperand(0) :
N->getOperand(i-1);
16558 InputsAreConsecutiveLoads =
false;
16560 InputsAreReverseConsecutive =
false;
16563 if (!InputsAreConsecutiveLoads && !InputsAreReverseConsecutive)
16568 assert(!(InputsAreConsecutiveLoads && InputsAreReverseConsecutive) &&
16569 "The loads cannot be both consecutive and reverse consecutive.");
16573 if (InputsAreConsecutiveLoads) {
16574 assert(FirstLoad &&
"Input needs to be a LoadSDNode.");
16578 ReturnSDVal = WideLoad;
16579 }
else if (InputsAreReverseConsecutive) {
16581 assert(LastLoad &&
"Input needs to be a LoadSDNode.");
16586 for (
int i =
N->getNumOperands() - 1; i >= 0; i--)
16594 for (
auto *LD : InputLoads)
16596 return ReturnSDVal;
16607 unsigned NumElems =
Input.getValueType().getVectorNumElements();
16613 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16615 ShuffleMask[CorrectElems & 0xF] = Elems & 0xF;
16617 ShuffleMask[(CorrectElems & 0xF0) >> 4] = (Elems & 0xF0) >> 4;
16618 CorrectElems = CorrectElems >> 8;
16619 Elems = Elems >> 8;
16626 EVT VT =
N->getValueType(0);
16630 Input.getValueType().getVectorElementType(),
16664 auto isSExtOfVecExtract = [&](
SDValue Op) ->
bool {
16690 Elems = Elems << 8;
16699 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16700 if (!isSExtOfVecExtract(
N->getOperand(i))) {
16707 int TgtElemArrayIdx;
16708 int InputSize =
Input.getValueType().getScalarSizeInBits();
16709 int OutputSize =
N->getValueType(0).getScalarSizeInBits();
16710 if (InputSize + OutputSize == 40)
16711 TgtElemArrayIdx = 0;
16712 else if (InputSize + OutputSize == 72)
16713 TgtElemArrayIdx = 1;
16714 else if (InputSize + OutputSize == 48)
16715 TgtElemArrayIdx = 2;
16716 else if (InputSize + OutputSize == 80)
16717 TgtElemArrayIdx = 3;
16718 else if (InputSize + OutputSize == 96)
16719 TgtElemArrayIdx = 4;
16723 uint64_t CorrectElems = TargetElems[TgtElemArrayIdx];
16725 ? CorrectElems & 0x0F0F0F0F0F0F0F0F
16726 : CorrectElems & 0xF0F0F0F0F0F0F0F0;
16727 if (Elems != CorrectElems) {
16743 if (
N->getValueType(0) != MVT::v1i128)
16746 SDValue Operand =
N->getOperand(0);
16753 EVT MemoryType = LD->getMemoryVT();
16757 bool ValidLDType = MemoryType == MVT::i8 || MemoryType == MVT::i16 ||
16758 MemoryType == MVT::i32 || MemoryType == MVT::i64;
16761 if (!ValidLDType ||
16767 LD->getChain(), LD->getBasePtr(),
16771 DAG.
getVTList(MVT::v1i128, MVT::Other),
16772 LoadOps, MemoryType, LD->getMemOperand());
16776 DAGCombinerInfo &DCI)
const {
16778 "Should be called with a BUILD_VECTOR node");
16780 SelectionDAG &DAG = DCI.DAG;
16783 if (!Subtarget.hasVSX())
16790 if (FirstInput.
getOpcode() == PPCISD::MFVSR) {
16791 SDValue Reduced = combineElementTruncationToVectorTruncation(
N, DCI);
16806 if (Subtarget.hasP9Altivec() && !DCI.isBeforeLegalize()) {
16815 if (Subtarget.isISA3_1()) {
16821 if (
N->getValueType(0) != MVT::v2f64)
16832 if (FirstInput.
getOpcode() !=
N->getOperand(1).getOpcode())
16843 if (!Ext1Op || !Ext2Op)
16852 if (FirstElem == 0 && SecondElem == 1)
16853 SubvecIdx = Subtarget.isLittleEndian() ? 1 : 0;
16854 else if (FirstElem == 2 && SecondElem == 3)
16855 SubvecIdx = Subtarget.isLittleEndian() ? 0 : 1;
16861 PPCISD::SINT_VEC_TO_FP : PPCISD::UINT_VEC_TO_FP;
16862 return DAG.
getNode(NodeType, dl, MVT::v2f64,
16867 DAGCombinerInfo &DCI)
const {
16870 "Need an int -> FP conversion node here");
16875 SelectionDAG &DAG = DCI.DAG;
16881 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
16883 if (!
Op.getOperand(0).getValueType().isSimple())
16885 if (
Op.getOperand(0).getValueType().getSimpleVT() <= MVT(MVT::i1) ||
16886 Op.getOperand(0).getValueType().getSimpleVT() > MVT(MVT::i64))
16889 SDValue FirstOperand(
Op.getOperand(0));
16890 bool SubWordLoad = FirstOperand.getOpcode() ==
ISD::LOAD &&
16891 (FirstOperand.getValueType() == MVT::i8 ||
16892 FirstOperand.getValueType() == MVT::i16);
16893 if (Subtarget.hasP9Vector() && Subtarget.hasP9Altivec() && SubWordLoad) {
16895 bool DstDouble =
Op.getValueType() == MVT::f64;
16896 unsigned ConvOp =
Signed ?
16897 (DstDouble ? PPCISD::FCFID : PPCISD::FCFIDS) :
16898 (DstDouble ? PPCISD::FCFIDU : PPCISD::FCFIDUS);
16903 SDValue Ops[] = { LDN->getChain(), LDN->getBasePtr(), WidthConst };
16906 Ops, MVT::i8, LDN->getMemOperand());
16911 SDValue ExtOps[] = { Ld, WidthConst };
16913 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ext);
16915 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ld);
16923 if (
Op.getOperand(0).getValueType() == MVT::i32)
16927 "UINT_TO_FP is supported only with FPCVT");
16931 unsigned FCFOp = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16936 MVT FCFTy = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16943 Subtarget.hasFPCVT()) ||
16945 SDValue Src =
Op.getOperand(0).getOperand(0);
16946 if (Src.getValueType() == MVT::f32) {
16948 DCI.AddToWorklist(Src.getNode());
16949 }
else if (Src.getValueType() != MVT::f64) {
16961 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
16964 DCI.AddToWorklist(
FP.getNode());
16988 switch (
N->getOpcode()) {
16993 Chain = LD->getChain();
16994 Base = LD->getBasePtr();
16995 MMO = LD->getMemOperand();
17014 MVT VecTy =
N->getValueType(0).getSimpleVT();
17022 Chain =
Load.getValue(1);
17024 PPCISD::XXSWAPD, dl, DAG.
getVTList(MVT::v2f64, MVT::Other), Chain,
Load);
17028 if (VecTy != MVT::v2f64) {
17055 switch (
N->getOpcode()) {
17060 Chain = ST->getChain();
17061 Base = ST->getBasePtr();
17062 MMO = ST->getMemOperand();
17082 SDValue Src =
N->getOperand(SrcOpnd);
17083 MVT VecTy = Src.getValueType().getSimpleVT();
17086 if (VecTy != MVT::v2f64) {
17092 DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Src);
17098 StoreOps, VecTy, MMO);
17105 DAGCombinerInfo &DCI)
const {
17108 unsigned Opcode =
N->getOperand(1).getOpcode();
17110 bool Strict =
N->getOperand(1)->isStrictFPOpcode();
17114 &&
"Not a FP_TO_INT Instruction!");
17117 EVT Op1VT =
N->getOperand(1).getValueType();
17120 if (!Subtarget.hasVSX() || !Subtarget.hasFPCVT() || !
isTypeLegal(ResVT))
17124 bool ValidTypeForStoreFltAsInt =
17125 (Op1VT == MVT::i32 || (Op1VT == MVT::i64 && Subtarget.isPPC64()) ||
17126 (Subtarget.hasP9Vector() && (Op1VT == MVT::i16 || Op1VT == MVT::i8)));
17129 if (ResVT == MVT::ppcf128 || (ResVT == MVT::f128 && !Subtarget.hasP9Vector()))
17132 if ((Op1VT != MVT::i64 && !Subtarget.hasP8Vector()) ||
17140 SDValue Ops[] = {
N->getOperand(0), Val,
N->getOperand(2),
17155 bool PrevElemFromFirstVec = Mask[0] < NumElts;
17156 for (
int i = 1, e = Mask.size(); i < e; i++) {
17157 if (PrevElemFromFirstVec && Mask[i] < NumElts)
17159 if (!PrevElemFromFirstVec && Mask[i] >= NumElts)
17161 PrevElemFromFirstVec = !PrevElemFromFirstVec;
17172 for (
int i = 0, e =
Op.getNumOperands(); i < e; i++) {
17173 FirstOp =
Op.getOperand(i);
17179 for (
int i = 1, e =
Op.getNumOperands(); i < e; i++)
17180 if (
Op.getOperand(i) != FirstOp && !
Op.getOperand(i).isUndef())
17190 Op =
Op.getOperand(0);
17206 int RHSFirstElt,
int RHSLastElt,
int HalfVec,
unsigned LHSNumValidElts,
17207 unsigned RHSNumValidElts,
const PPCSubtarget &Subtarget) {
17209 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - LHSNumValidElts;
17211 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - RHSNumValidElts;
17212 for (
int I = 0,
E = ShuffV.
size();
I <
E; ++
I) {
17213 int Idx = ShuffV[
I];
17214 if (Idx >= LHSFirstElt && Idx <= LHSLastElt)
17215 ShuffV[
I] += LHSEltFixup;
17216 else if (Idx >= RHSFirstElt && Idx <= RHSLastElt)
17217 ShuffV[
I] += RHSEltFixup;
17228 SDLoc dl(OrigSToV);
17231 "Expecting a SCALAR_TO_VECTOR here");
17244 "Cannot produce a permuted scalar_to_vector for one element vector");
17246 unsigned ResultInElt = NumElts / 2;
17252 return DAG.
getNode(PPCISD::SCALAR_TO_VECTOR_PERMUTED, dl, VT,
17257 int HalfVec,
int LHSLastElementDefined,
17258 int RHSLastElementDefined) {
17259 for (
int Index : ShuffV) {
17263 if ((LHSLastElementDefined >= 0) && (Index < HalfVec) &&
17264 (Index > LHSLastElementDefined))
17267 if ((RHSLastElementDefined >= 0) &&
17268 (Index > HalfVec + RHSLastElementDefined))
17275 int ScalarSize,
uint64_t ShuffleEltWidth,
unsigned &NumValidElts,
17276 int FirstElt,
int &LastElt,
SDValue VecShuffOperand,
SDValue SToVNode,
17292 LastElt = (
uint64_t)ScalarSize > ShuffleEltWidth
17293 ? ScalarSize / ShuffleEltWidth - 1 + FirstElt
17296 if (SToVPermuted.
getValueType() != VecShuffOperandType)
17297 SToVPermuted = DAG.
getBitcast(VecShuffOperandType, SToVPermuted);
17298 return SToVPermuted;
17318 int NumElts =
LHS.getValueType().getVectorNumElements();
17321 bool IsLittleEndian = Subtarget.isLittleEndian();
17328 if (!Subtarget.hasDirectMove())
17348 SmallVector<int, 16> ShuffV(Mask);
17351 if (SToVLHS || SToVRHS) {
17354 int ShuffleNumElts = ShuffV.
size();
17355 int HalfVec = ShuffleNumElts / 2;
17361 unsigned LHSNumValidElts = HalfVec;
17362 unsigned RHSNumValidElts = HalfVec;
17367 int LHSFirstElt = 0;
17368 int RHSFirstElt = ShuffleNumElts;
17369 int LHSLastElt = -1;
17370 int RHSLastElt = -1;
17378 int LHSScalarSize = 0;
17379 int RHSScalarSize = 0;
17382 if (!IsLittleEndian && LHSScalarSize >= 64)
17387 if (!IsLittleEndian && RHSScalarSize >= 64)
17390 if (LHSScalarSize != 0)
17392 LHSScalarSize, ShuffleEltWidth, LHSNumValidElts, LHSFirstElt,
17393 LHSLastElt,
LHS, SToVLHS, DAG, Subtarget);
17394 if (RHSScalarSize != 0)
17396 RHSScalarSize, ShuffleEltWidth, RHSNumValidElts, RHSFirstElt,
17397 RHSLastElt,
RHS, SToVRHS, DAG, Subtarget);
17408 ShuffV, LHSFirstElt, LHSLastElt, RHSFirstElt, RHSLastElt, HalfVec,
17409 LHSNumValidElts, RHSNumValidElts, Subtarget);
17435 if (IsLittleEndian) {
17438 if (Mask[0] < NumElts)
17439 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17443 ShuffV[i] = (ShuffV[i - 1] >= 0 ? ShuffV[i - 1] : 0) + NumElts;
17448 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17452 ShuffV[i] = (ShuffV[i + 1] >= 0 ? ShuffV[i + 1] : 0) + NumElts;
17457 if (Mask[0] < NumElts)
17458 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17462 ShuffV[i] = ShuffV[i + 1] >= 0 ? ShuffV[i + 1] - NumElts : 0;
17467 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17471 ShuffV[i] = ShuffV[i - 1] >= 0 ? ShuffV[i - 1] - NumElts : 0;
17481 if (IsLittleEndian)
17490 DAGCombinerInfo &DCI)
const {
17492 "Not a reverse memop pattern!");
17494 auto IsElementReverse = [](
const ShuffleVectorSDNode *SVN) ->
bool {
17497 auto I =
Mask.rbegin();
17498 auto E =
Mask.rend();
17500 for (;
I !=
E; ++
I) {
17508 SelectionDAG &DAG = DCI.DAG;
17511 if (!
isTypeLegal(VT) || !Subtarget.isLittleEndian() || !Subtarget.hasVSX())
17517 if (!Subtarget.hasP9Vector())
17520 if(!IsElementReverse(SVN))
17527 for (SDUse &Use : LSBase->
uses())
17528 if (
Use.getResNo() == 0 &&
17535 PPCISD::LOAD_VEC_BE, dl, DAG.
getVTList(VT, MVT::Other), LoadOps,
17550 PPCISD::STORE_VEC_BE, dl, DAG.
getVTList(MVT::Other), StoreOps,
17559 if (IntrinsicID == Intrinsic::ppc_stdcx)
17561 else if (IntrinsicID == Intrinsic::ppc_stwcx)
17563 else if (IntrinsicID == Intrinsic::ppc_sthcx)
17565 else if (IntrinsicID == Intrinsic::ppc_stbcx)
17574 if (
N->getOpcode() == PPCISD::ADDC &&
N->hasAnyUseOfValue(1)) {
17578 if (
LHS->getOpcode() == PPCISD::ADDE &&
17589 if (
N->getOpcode() == PPCISD::SUBE) {
17595 if (
LHS ==
RHS &&
LHS.getOpcode() == PPCISD::ADDC) {
17598 if (AddcLHS.
getOpcode() == PPCISD::ADDE &&
17620 SDValue CmpLHS =
N->getOperand(0);
17621 SDValue CmpRHS =
N->getOperand(1);
17622 SDValue TrueVal =
N->getOperand(2);
17623 SDValue FalseVal =
N->getOperand(3);
17637 if (FalseVal.getOpcode() !=
ISD::SRL || !FalseVal.hasOneUse())
17640 SDValue ShiftVal = FalseVal.getOperand(0);
17641 SDValue ShiftAmt = FalseVal.getOperand(1);
17645 if (!ShiftConst || !ShiftConst->getAPIntValue().isMinSignedValue())
17672 if (CtlzArg != CmpLHS)
17680 DAG.
getNode(PPCISD::SRL,
DL, FalseVal.getValueType(), ShiftVal, ShiftAmt);
17727 auto isZeroOrOne = [=](
SDValue &V) {
17729 V.getConstantOperandVal(0) == Intrinsic::ppc_test_data_class)
17734 if (!isZeroOrOne(NonNullConstant))
17744 EVT VType =
N->getValueType(0);
17748 return NewNonNullConstant;
17767 EVT XorVT =
N->getValueType(0);
17768 if ((XorVT != MVT::i32 && XorVT != MVT::i64))
17776 if (!XorConst || !XorConst->
isOne()) {
17778 if (!XorConst || !XorConst->
isOne())
17785 if (!
LHS.hasOneUse())
17793 SelectNode =
LHS.getOperand(0);
17807 if (MachineOpc != PPC::SELECT_CC_I4 && MachineOpc != PPC::SELECT_CC_I8)
17817 if (!ConstOp1 || !ConstOp2)
17821 if (!((ConstOp1->
isOne() && ConstOp2->
isZero()) ||
17830 MachineOpc = (XorVT == MVT::i32) ? PPC::SELECT_CC_I4 : PPC::SELECT_CC_I8;
17832 bool ConstOp1IsOne = ConstOp1->
isOne();
17835 {SelectNode.getOperand(0),
17836 DAG.getConstant(ConstOp1IsOne ? 0 : 1, DL, XorVT),
17837 DAG.getConstant(ConstOp1IsOne ? 1 : 0, DL, XorVT),
17838 SelectNode.getOperand(3)}),
17846 switch (
N->getOpcode()) {
17849 return combineADD(
N, DCI);
17881 return combineSHL(
N, DCI);
17883 return combineSRA(
N, DCI);
17885 return combineSRL(
N, DCI);
17887 return combineMUL(
N, DCI);
17889 case PPCISD::FNMSUB:
17890 return combineFMALike(
N, DCI);
17893 return N->getOperand(0);
17897 return N->getOperand(0);
17903 return N->getOperand(0);
17907 if (
SDValue SECC = combineSignExtendSetCC(
N, DCI))
17915 return DAGCombineExtBoolTrunc(
N, DCI);
17917 return combineTRUNCATE(
N, DCI);
17919 if (
SDValue CSCC = combineSetCC(
N, DCI))
17925 return DAGCombineTruncBoolExt(
N, DCI);
17928 return combineFPToIntToFP(
N, DCI);
17937 EVT Op1VT =
N->getOperand(1).getValueType();
17938 unsigned Opcode =
N->getOperand(1).getOpcode();
17942 SDValue Val = combineStoreFPToInt(
N, DCI);
17956 N->getOperand(1).getNode()->hasOneUse() &&
17957 (Op1VT == MVT::i32 || Op1VT == MVT::i16 ||
17958 (Subtarget.hasLDBRX() && Subtarget.isPPC64() && Op1VT == MVT::i64))) {
17966 SDValue BSwapOp =
N->getOperand(1).getOperand(0);
17973 if (Op1VT.
bitsGT(mVT)) {
17978 if (Op1VT == MVT::i64)
17983 N->getOperand(0), BSwapOp,
N->getOperand(2), DAG.
getValueType(mVT)
18003 ST->getBasePtr(), ST->getOffset(), MemVT,
18004 ST->getMemOperand(), ST->getAddressingMode(),
18008 return ST->isUnindexed()
18017 if (Subtarget.needsSwapsForVSXMemOps() &&
18018 (StoreVT == MVT::v2f64 || StoreVT == MVT::v2i64 ||
18019 StoreVT == MVT::v4f32 || StoreVT == MVT::v4i32))
18026 EVT VT = LD->getValueType(0);
18032 if (Subtarget.needsSwapsForVSXMemOps() &&
18033 (LoadVT == MVT::v2f64 || LoadVT == MVT::v2i64 ||
18034 LoadVT == MVT::v4f32 || LoadVT == MVT::v4i32))
18045 auto ReplaceTwoFloatLoad = [&]() {
18046 if (VT != MVT::i64)
18061 if (!LD->hasNUsesOfValue(2, 0))
18064 auto UI = LD->user_begin();
18065 while (UI.getUse().getResNo() != 0) ++UI;
18067 while (UI.getUse().getResNo() != 0) ++UI;
18068 SDNode *RightShift = *UI;
18076 if (RightShift->getOpcode() !=
ISD::SRL ||
18078 RightShift->getConstantOperandVal(1) != 32 ||
18079 !RightShift->hasOneUse())
18082 SDNode *Trunc2 = *RightShift->user_begin();
18092 Bitcast->getValueType(0) != MVT::f32)
18098 if (Subtarget.isLittleEndian())
18104 SDValue BasePtr = LD->getBasePtr();
18105 if (LD->isIndexed()) {
18107 "Non-pre-inc AM on PPC?");
18115 SDValue FloatLoad = DAG.
getLoad(MVT::f32, dl, LD->getChain(), BasePtr,
18116 LD->getPointerInfo(), LD->getAlign(),
18117 MMOFlags, LD->getAAInfo());
18123 LD->getPointerInfo().getWithOffset(4),
18126 if (LD->isIndexed()) {
18140 if (ReplaceTwoFloatLoad())
18143 EVT MemVT = LD->getMemoryVT();
18146 if (LD->isUnindexed() && VT.
isVector() &&
18149 !Subtarget.hasP8Vector() &&
18150 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
18151 VT == MVT::v4f32))) &&
18152 LD->getAlign() < ABIAlignment) {
18154 SDValue Chain = LD->getChain();
18155 SDValue Ptr = LD->getBasePtr();
18156 bool isLittleEndian = Subtarget.isLittleEndian();
18183 MVT PermCntlTy, PermTy, LDTy;
18184 Intr = isLittleEndian ? Intrinsic::ppc_altivec_lvsr
18185 : Intrinsic::ppc_altivec_lvsl;
18186 IntrLD = Intrinsic::ppc_altivec_lvx;
18187 IntrPerm = Intrinsic::ppc_altivec_vperm;
18188 PermCntlTy = MVT::v16i8;
18189 PermTy = MVT::v4i32;
18208 SDValue BaseLoadOps[] = { Chain, LDXIntID, Ptr };
18212 BaseLoadOps, LDTy, BaseMMO);
18221 int IncValue = IncOffset;
18238 SDValue ExtraLoadOps[] = { Chain, LDXIntID, Ptr };
18242 ExtraLoadOps, LDTy, ExtraMMO);
18253 if (isLittleEndian)
18255 ExtraLoad, BaseLoad, PermCntl, DAG, dl);
18258 BaseLoad, ExtraLoad, PermCntl, DAG, dl);
18261 Perm = Subtarget.hasAltivec()
18276 bool isLittleEndian = Subtarget.isLittleEndian();
18277 unsigned IID =
N->getConstantOperandVal(0);
18278 Intrinsic::ID Intr = (isLittleEndian ? Intrinsic::ppc_altivec_lvsr
18279 : Intrinsic::ppc_altivec_lvsl);
18280 if (IID == Intr &&
N->getOperand(1)->getOpcode() ==
ISD::ADD) {
18287 .zext(
Add.getScalarValueSizeInBits()))) {
18288 SDNode *BasePtr =
Add->getOperand(0).getNode();
18289 for (
SDNode *U : BasePtr->users()) {
18291 U->getConstantOperandVal(0) == IID) {
18302 SDNode *BasePtr =
Add->getOperand(0).getNode();
18303 for (
SDNode *U : BasePtr->users()) {
18306 (
Add->getConstantOperandVal(1) - U->getConstantOperandVal(1)) %
18312 V->getConstantOperandVal(0) == IID) {
18324 (IID == Intrinsic::ppc_altivec_vmaxsw ||
18325 IID == Intrinsic::ppc_altivec_vmaxsh ||
18326 IID == Intrinsic::ppc_altivec_vmaxsb)) {
18329 if ((
V1.getSimpleValueType() == MVT::v4i32 ||
18330 V1.getSimpleValueType() == MVT::v8i16 ||
18331 V1.getSimpleValueType() == MVT::v16i8) &&
18336 V1.getOperand(1) == V2) {
18357 switch (
N->getConstantOperandVal(1)) {
18360 case Intrinsic::ppc_altivec_vsum4sbs:
18361 case Intrinsic::ppc_altivec_vsum4shs:
18362 case Intrinsic::ppc_altivec_vsum4ubs: {
18369 APInt APSplatBits, APSplatUndef;
18370 unsigned SplatBitSize;
18373 APSplatBits, APSplatUndef, SplatBitSize, HasAnyUndefs, 0,
18374 !Subtarget.isLittleEndian());
18376 if (BVNIsConstantSplat && APSplatBits == 0)
18381 case Intrinsic::ppc_vsx_lxvw4x:
18382 case Intrinsic::ppc_vsx_lxvd2x:
18385 if (Subtarget.needsSwapsForVSXMemOps())
18393 if (Subtarget.needsSwapsForVSXMemOps()) {
18394 switch (
N->getConstantOperandVal(1)) {
18397 case Intrinsic::ppc_vsx_stxvw4x:
18398 case Intrinsic::ppc_vsx_stxvd2x:
18407 bool Is64BitBswapOn64BitTgt =
18408 Subtarget.isPPC64() &&
N->getValueType(0) == MVT::i64;
18410 N->getOperand(0).hasOneUse();
18411 if (IsSingleUseNormalLd &&
18412 (
N->getValueType(0) == MVT::i32 ||
N->getValueType(0) == MVT::i16 ||
18413 (Subtarget.hasLDBRX() && Is64BitBswapOn64BitTgt))) {
18424 DAG.
getVTList(
N->getValueType(0) == MVT::i64 ?
18425 MVT::i64 : MVT::i32, MVT::Other),
18426 Ops, LD->getMemoryVT(), LD->getMemOperand());
18430 if (
N->getValueType(0) == MVT::i16)
18447 !IsSingleUseNormalLd)
18452 if (!LD->isSimple())
18454 SDValue BasePtr = LD->getBasePtr();
18456 LD->getPointerInfo(), LD->getAlign());
18461 LD->getMemOperand(), 4, 4);
18465 if (Subtarget.isLittleEndian())
18471 Hi.getOperand(0).getValue(1),
Lo.getOperand(0).getValue(1));
18480 if (!
N->getOperand(0).hasOneUse() &&
18481 !
N->getOperand(1).hasOneUse() &&
18482 !
N->getOperand(2).hasOneUse()) {
18485 SDNode *VCMPrecNode =
nullptr;
18487 SDNode *LHSN =
N->getOperand(0).getNode();
18489 if (
User->getOpcode() == PPCISD::VCMP_rec &&
18493 VCMPrecNode =
User;
18505 SDNode *FlagUser =
nullptr;
18507 FlagUser ==
nullptr; ++UI) {
18508 assert(UI != VCMPrecNode->
use_end() &&
"Didn't find user!");
18521 return SDValue(VCMPrecNode, 0);
18532 SDValue LHS =
N->getOperand(2), RHS =
N->getOperand(3);
18543 auto RHSAPInt = RHS->getAsAPIntVal();
18544 if (!RHSAPInt.isIntN(64))
18547 unsigned Val = RHSAPInt.getZExtValue();
18548 auto isImpossibleCompare = [&]() {
18551 if (Val != 0 && Val != 1) {
18553 return N->getOperand(0);
18556 N->getOperand(0),
N->getOperand(4));
18561 unsigned StoreWidth = 0;
18564 if (
SDValue Impossible = isImpossibleCompare())
18576 SDValue Ops[] = {LHS.getOperand(0), LHS.getOperand(2), LHS.getOperand(3),
18580 PPCISD::STORE_COND, dl,
18582 MemNode->getMemoryVT(), MemNode->getMemOperand());
18586 if (
N->getOperand(0) == LHS.getValue(1))
18597 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other, InChain,
18599 DAG.
getRegister(PPC::CR0, MVT::i32),
N->getOperand(4),
18605 assert(isDot &&
"Can't compare against a vector result!");
18607 if (
SDValue Impossible = isImpossibleCompare())
18610 bool BranchOnWhenPredTrue = (CC ==
ISD::SETEQ) ^ (Val == 0);
18617 EVT VTs[] = { LHS.getOperand(2).getValueType(), MVT::Glue };
18622 switch (LHS.getConstantOperandVal(1)) {
18638 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other,
N->getOperand(0),
18641 N->getOperand(4), CompNode.
getValue(1));
18646 return DAGCombineBuildVector(
N, DCI);
18653 return DAGCombineBitcast(
N, DCI);
18664 EVT VT =
N->getValueType(0);
18665 if (VT == MVT::i64 && !Subtarget.isPPC64())
18667 if ((VT != MVT::i32 && VT != MVT::i64) ||
18675 unsigned Lg2 = (IsNegPow2 ? -Divisor : Divisor).
countr_zero();
18695 const APInt &DemandedElts,
18697 unsigned Depth)
const {
18699 switch (
Op.getOpcode()) {
18701 case PPCISD::LBRX: {
18704 Known.Zero = 0xFFFF0000;
18707 case PPCISD::ADDE: {
18708 if (
Op.getResNo() == 0) {
18713 Known.Zero = ~1ULL;
18718 switch (
Op.getConstantOperandVal(0)) {
18720 case Intrinsic::ppc_altivec_vcmpbfp_p:
18721 case Intrinsic::ppc_altivec_vcmpeqfp_p:
18722 case Intrinsic::ppc_altivec_vcmpequb_p:
18723 case Intrinsic::ppc_altivec_vcmpequh_p:
18724 case Intrinsic::ppc_altivec_vcmpequw_p:
18725 case Intrinsic::ppc_altivec_vcmpequd_p:
18726 case Intrinsic::ppc_altivec_vcmpequq_p:
18727 case Intrinsic::ppc_altivec_vcmpgefp_p:
18728 case Intrinsic::ppc_altivec_vcmpgtfp_p:
18729 case Intrinsic::ppc_altivec_vcmpgtsb_p:
18730 case Intrinsic::ppc_altivec_vcmpgtsh_p:
18731 case Intrinsic::ppc_altivec_vcmpgtsw_p:
18732 case Intrinsic::ppc_altivec_vcmpgtsd_p:
18733 case Intrinsic::ppc_altivec_vcmpgtsq_p:
18734 case Intrinsic::ppc_altivec_vcmpgtub_p:
18735 case Intrinsic::ppc_altivec_vcmpgtuh_p:
18736 case Intrinsic::ppc_altivec_vcmpgtuw_p:
18737 case Intrinsic::ppc_altivec_vcmpgtud_p:
18738 case Intrinsic::ppc_altivec_vcmpgtuq_p:
18745 switch (
Op.getConstantOperandVal(1)) {
18748 case Intrinsic::ppc_load2r:
18750 Known.Zero = 0xFFFF0000;
18759 switch (Subtarget.getCPUDirective()) {
18781 if (
ML->getLoopDepth() > 1 &&
ML->getSubLoops().empty())
18790 for (
auto I =
ML->block_begin(), IE =
ML->block_end();
I != IE; ++
I)
18792 LoopSize +=
TII->getInstSizeInBytes(J);
18797 if (LoopSize > 16 && LoopSize <= 32)
18811 if (Constraint.
size() == 1) {
18812 switch (Constraint[0]) {
18830 }
else if (Constraint ==
"wc") {
18832 }
else if (Constraint ==
"wa" || Constraint ==
"wd" ||
18833 Constraint ==
"wf" || Constraint ==
"ws" ||
18834 Constraint ==
"wi" || Constraint ==
"ww") {
18847 Value *CallOperandVal =
info.CallOperandVal;
18850 if (!CallOperandVal)
18857 else if ((
StringRef(constraint) ==
"wa" ||
18869 switch (*constraint) {
18899std::pair<unsigned, const TargetRegisterClass *>
18903 if (Constraint.
size() == 1) {
18905 switch (Constraint[0]) {
18907 if (VT == MVT::i64 && Subtarget.isPPC64())
18908 return std::make_pair(0U, &PPC::G8RC_NOX0RegClass);
18909 return std::make_pair(0U, &PPC::GPRC_NOR0RegClass);
18911 if (VT == MVT::i64 && Subtarget.isPPC64())
18912 return std::make_pair(0U, &PPC::G8RCRegClass);
18913 return std::make_pair(0U, &PPC::GPRCRegClass);
18919 if (Subtarget.hasSPE()) {
18920 if (VT == MVT::f32 || VT == MVT::i32)
18921 return std::make_pair(0U, &PPC::GPRCRegClass);
18922 if (VT == MVT::f64 || VT == MVT::i64)
18923 return std::make_pair(0U, &PPC::SPERCRegClass);
18925 if (VT == MVT::f32 || VT == MVT::i32)
18926 return std::make_pair(0U, &PPC::F4RCRegClass);
18927 if (VT == MVT::f64 || VT == MVT::i64)
18928 return std::make_pair(0U, &PPC::F8RCRegClass);
18932 if (Subtarget.hasAltivec() && VT.
isVector())
18933 return std::make_pair(0U, &PPC::VRRCRegClass);
18934 else if (Subtarget.hasVSX())
18936 return std::make_pair(0U, &PPC::VFRCRegClass);
18939 return std::make_pair(0U, &PPC::CRRCRegClass);
18941 }
else if (Constraint ==
"wc" && Subtarget.useCRBits()) {
18943 return std::make_pair(0U, &PPC::CRBITRCRegClass);
18944 }
else if ((Constraint ==
"wa" || Constraint ==
"wd" ||
18945 Constraint ==
"wf" || Constraint ==
"wi") &&
18946 Subtarget.hasVSX()) {
18950 return std::make_pair(0U, &PPC::VSRCRegClass);
18951 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18952 return std::make_pair(0U, &PPC::VSSRCRegClass);
18953 return std::make_pair(0U, &PPC::VSFRCRegClass);
18954 }
else if ((Constraint ==
"ws" || Constraint ==
"ww") && Subtarget.hasVSX()) {
18955 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18956 return std::make_pair(0U, &PPC::VSSRCRegClass);
18958 return std::make_pair(0U, &PPC::VSFRCRegClass);
18959 }
else if (Constraint ==
"lr") {
18960 if (VT == MVT::i64)
18961 return std::make_pair(0U, &PPC::LR8RCRegClass);
18963 return std::make_pair(0U, &PPC::LRRCRegClass);
18968 if (Constraint[0] ==
'{' && Constraint[Constraint.
size() - 1] ==
'}') {
18972 if (Constraint.
size() > 3 && Constraint[1] ==
'v' && Constraint[2] ==
's') {
18973 int VSNum = atoi(Constraint.
data() + 3);
18974 assert(VSNum >= 0 && VSNum <= 63 &&
18975 "Attempted to access a vsr out of range");
18977 return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass);
18978 return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass);
18983 if (Constraint.
size() > 3 && Constraint[1] ==
'f') {
18984 int RegNum = atoi(Constraint.
data() + 2);
18985 if (RegNum > 31 || RegNum < 0)
18987 if (VT == MVT::f32 || VT == MVT::i32)
18988 return Subtarget.hasSPE()
18989 ? std::make_pair(PPC::R0 + RegNum, &PPC::GPRCRegClass)
18990 : std::make_pair(PPC::F0 + RegNum, &PPC::F4RCRegClass);
18991 if (VT == MVT::f64 || VT == MVT::i64)
18992 return Subtarget.hasSPE()
18993 ? std::make_pair(PPC::S0 + RegNum, &PPC::SPERCRegClass)
18994 : std::make_pair(PPC::F0 + RegNum, &PPC::F8RCRegClass);
18998 std::pair<unsigned, const TargetRegisterClass *> R =
19007 if (R.first && VT == MVT::i64 && Subtarget.isPPC64() &&
19008 PPC::GPRCRegClass.contains(R.first))
19009 return std::make_pair(
TRI->getMatchingSuperReg(R.first,
19010 PPC::sub_32, &PPC::G8RCRegClass),
19011 &PPC::G8RCRegClass);
19014 if (!R.second &&
StringRef(
"{cc}").equals_insensitive(Constraint)) {
19015 R.first = PPC::CR0;
19016 R.second = &PPC::CRRCRegClass;
19020 if (Subtarget.isAIXABI() && !TM.getAIXExtendedAltivecABI()) {
19021 if (((R.first >= PPC::V20 && R.first <= PPC::V31) ||
19022 (R.first >= PPC::VF20 && R.first <= PPC::VF31)) &&
19023 (R.second == &PPC::VSRCRegClass || R.second == &PPC::VSFRCRegClass))
19024 errs() <<
"warning: vector registers 20 to 32 are reserved in the "
19025 "default AIX AltiVec ABI and cannot be used\n";
19035 std::vector<SDValue> &
Ops,
19040 if (Constraint.
size() > 1)
19043 char Letter = Constraint[0];
19058 EVT TCVT = MVT::i64;
19099 if (Result.getNode()) {
19100 Ops.push_back(Result);
19111 if (
I.getNumOperands() <= 1)
19115 auto IntrinsicID =
Ops[1].getNode()->getAsZExtVal();
19116 if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw &&
19117 IntrinsicID != Intrinsic::ppc_trapd && IntrinsicID != Intrinsic::ppc_trap)
19120 if (
MDNode *MDN =
I.getMetadata(LLVMContext::MD_annotation))
19136 if (Ty->isVectorTy() && AM.
BaseOffs != 0 && !Subtarget.hasP9Vector())
19148 switch (AM.
Scale) {
19176 unsigned Depth =
Op.getConstantOperandVal(0);
19200 SDValue RetAddrFI = getReturnAddrFrameIndex(DAG);
19208 unsigned Depth =
Op.getConstantOperandVal(0);
19215 bool isPPC64 = PtrVT == MVT::i64;
19221 FrameReg = isPPC64 ? PPC::X1 : PPC::R1;
19223 FrameReg = isPPC64 ? PPC::FP8 : PPC::FP;
19229 FrameAddr, MachinePointerInfo());
19233#define GET_REGISTER_MATCHER
19234#include "PPCGenAsmMatcher.inc"
19238 bool IsPPC64 = Subtarget.isPPC64();
19250 if ((IsPPC64 && Reg == PPC::R2) || Reg == PPC::R0)
19256 Reg = Reg.id() - PPC::R0 + PPC::X0;
19263 if (Subtarget.is32BitELFABI())
19268 if (Subtarget.isAIXABI())
19282 return Subtarget.isGVIndirectSymbol(
G->getGlobal());
19298 case Intrinsic::ppc_atomicrmw_xchg_i128:
19299 case Intrinsic::ppc_atomicrmw_add_i128:
19300 case Intrinsic::ppc_atomicrmw_sub_i128:
19301 case Intrinsic::ppc_atomicrmw_nand_i128:
19302 case Intrinsic::ppc_atomicrmw_and_i128:
19303 case Intrinsic::ppc_atomicrmw_or_i128:
19304 case Intrinsic::ppc_atomicrmw_xor_i128:
19305 case Intrinsic::ppc_cmpxchg_i128:
19307 Info.memVT = MVT::i128;
19308 Info.ptrVal =
I.getArgOperand(0);
19310 Info.align =
Align(16);
19315 case Intrinsic::ppc_atomic_load_i128:
19317 Info.memVT = MVT::i128;
19318 Info.ptrVal =
I.getArgOperand(0);
19320 Info.align =
Align(16);
19324 case Intrinsic::ppc_atomic_store_i128:
19326 Info.memVT = MVT::i128;
19327 Info.ptrVal =
I.getArgOperand(2);
19329 Info.align =
Align(16);
19333 case Intrinsic::ppc_altivec_lvx:
19334 case Intrinsic::ppc_altivec_lvxl:
19335 case Intrinsic::ppc_altivec_lvebx:
19336 case Intrinsic::ppc_altivec_lvehx:
19337 case Intrinsic::ppc_altivec_lvewx:
19338 case Intrinsic::ppc_vsx_lxvd2x:
19339 case Intrinsic::ppc_vsx_lxvw4x:
19340 case Intrinsic::ppc_vsx_lxvd2x_be:
19341 case Intrinsic::ppc_vsx_lxvw4x_be:
19342 case Intrinsic::ppc_vsx_lxvl:
19343 case Intrinsic::ppc_vsx_lxvll: {
19346 case Intrinsic::ppc_altivec_lvebx:
19349 case Intrinsic::ppc_altivec_lvehx:
19352 case Intrinsic::ppc_altivec_lvewx:
19355 case Intrinsic::ppc_vsx_lxvd2x:
19356 case Intrinsic::ppc_vsx_lxvd2x_be:
19366 Info.ptrVal =
I.getArgOperand(0);
19369 Info.align =
Align(1);
19374 case Intrinsic::ppc_altivec_stvx:
19375 case Intrinsic::ppc_altivec_stvxl:
19376 case Intrinsic::ppc_altivec_stvebx:
19377 case Intrinsic::ppc_altivec_stvehx:
19378 case Intrinsic::ppc_altivec_stvewx:
19379 case Intrinsic::ppc_vsx_stxvd2x:
19380 case Intrinsic::ppc_vsx_stxvw4x:
19381 case Intrinsic::ppc_vsx_stxvd2x_be:
19382 case Intrinsic::ppc_vsx_stxvw4x_be:
19383 case Intrinsic::ppc_vsx_stxvl:
19384 case Intrinsic::ppc_vsx_stxvll: {
19387 case Intrinsic::ppc_altivec_stvebx:
19390 case Intrinsic::ppc_altivec_stvehx:
19393 case Intrinsic::ppc_altivec_stvewx:
19396 case Intrinsic::ppc_vsx_stxvd2x:
19397 case Intrinsic::ppc_vsx_stxvd2x_be:
19407 Info.ptrVal =
I.getArgOperand(1);
19410 Info.align =
Align(1);
19415 case Intrinsic::ppc_stdcx:
19416 case Intrinsic::ppc_stwcx:
19417 case Intrinsic::ppc_sthcx:
19418 case Intrinsic::ppc_stbcx: {
19420 auto Alignment =
Align(8);
19422 case Intrinsic::ppc_stdcx:
19425 case Intrinsic::ppc_stwcx:
19427 Alignment =
Align(4);
19429 case Intrinsic::ppc_sthcx:
19431 Alignment =
Align(2);
19433 case Intrinsic::ppc_stbcx:
19435 Alignment =
Align(1);
19440 Info.ptrVal =
I.getArgOperand(0);
19442 Info.align = Alignment;
19456 const AttributeList &FuncAttributes)
const {
19460 if (Subtarget.hasAltivec() &&
Op.size() >= 16) {
19461 if (
Op.isMemset() && Subtarget.hasVSX()) {
19466 if (TailSize > 2 && TailSize <= 4) {
19471 if (
Op.isAligned(
Align(16)) || Subtarget.hasP8Vector())
19476 if (Subtarget.isPPC64()) {
19487 assert(Ty->isIntegerTy());
19489 unsigned BitSize = Ty->getPrimitiveSizeInBits();
19490 return !(BitSize == 0 || BitSize > 64);
19498 return NumBits1 == 64 && NumBits2 == 32;
19506 return NumBits1 == 64 && NumBits2 == 32;
19513 EVT MemVT = LD->getMemoryVT();
19514 if ((MemVT == MVT::i1 || MemVT == MVT::i8 || MemVT == MVT::i16 ||
19515 (Subtarget.isPPC64() && MemVT == MVT::i32)) &&
19531 "invalid fpext types");
19533 if (DestVT == MVT::f128)
19548 unsigned *
Fast)
const {
19562 !Subtarget.allowsUnalignedFPAccess())
19566 if (Subtarget.hasVSX()) {
19567 if (VT != MVT::v2f64 && VT != MVT::v2i64 &&
19568 VT != MVT::v4f32 && VT != MVT::v4i32)
19575 if (VT == MVT::ppcf128)
19590 if (!ConstNode->getAPIntValue().isSignedIntN(64))
19598 int64_t Imm = ConstNode->getSExtValue();
19619 if (Subtarget.hasSPE() || Subtarget.useSoftFloat())
19621 switch (Ty->getScalarType()->getTypeID()) {
19626 return Subtarget.hasP9Vector();
19634 if (!
I->hasOneUse())
19638 assert(
User &&
"A single use instruction with no uses.");
19640 switch (
I->getOpcode()) {
19641 case Instruction::FMul: {
19643 if (
User->getOpcode() != Instruction::FSub &&
19644 User->getOpcode() != Instruction::FAdd)
19651 bool AllowContract =
I->getFastMathFlags().allowContract() &&
19652 User->getFastMathFlags().allowContract();
19658 case Instruction::Load: {
19671 if (
User->getOpcode() != Instruction::Store)
19691 static const MCPhysReg ScratchRegs[] = {
19692 PPC::X12, PPC::LR8, PPC::CTR8, 0
19695 return ScratchRegs;
19700 return Subtarget.isPPC64() ? PPC::X3 : PPC::R3;
19705 return Subtarget.isPPC64() ? PPC::X4 : PPC::R4;
19710 EVT VT ,
unsigned DefinedValues)
const {
19711 if (VT == MVT::v2i64)
19712 return Subtarget.hasDirectMove();
19714 if (Subtarget.hasVSX())
19741 return PPCISD::FNMSUB;
19742 case PPCISD::FNMSUB:
19748 bool LegalOps,
bool OptForSize,
19750 unsigned Depth)
const {
19754 unsigned Opc =
Op.getOpcode();
19755 EVT VT =
Op.getValueType();
19759 case PPCISD::FNMSUB:
19779 if (Flags.hasNoSignedZeros()) {
19783 N0Cost,
Depth + 1);
19787 N1Cost,
Depth + 1);
19789 if (NegN0 && N0Cost <= N1Cost) {
19790 Cost = std::min(N0Cost, N2Cost);
19792 }
else if (NegN1) {
19793 Cost = std::min(N1Cost, N2Cost);
19813 if (M.getStackProtectorGuard() ==
"tls" || Subtarget.isTargetLinux())
19819 bool ForCodeSize)
const {
19820 if (!VT.
isSimple() || !Subtarget.hasVSX())
19830 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
19835 APSInt IntResult(16,
false);
19840 if (IsExact && IntResult <= 15 && IntResult >= -16)
19842 return Imm.isZero();
19845 return Imm.isPosZero();
19857 unsigned Opcode =
N->getOpcode();
19877 if (Mask->getZExtValue() == OpSizeInBits - 1)
19884 DAGCombinerInfo &DCI)
const {
19885 EVT VT =
N->getValueType(0);
19888 unsigned Opc =
N->getOpcode();
19890 "Unexpected opcode.");
19897 if (EltTy != MVT::i64 && EltTy != MVT::i32)
19901 uint64_t SplatBits = 0;
19902 bool AddSplatCase =
false;
19906 AddSplatCase =
true;
19910 if (!AddSplatCase) {
19914 unsigned SplatBitSize;
19916 APInt APSplatBits, APSplatUndef;
19918 bool BVNIsConstantSplat =
19920 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
19921 if (!BVNIsConstantSplat || SplatBitSize != EltBits)
19932 if (SplatBits == (EltBits - 1)) {
19936 NewOpc = PPCISD::SHL;
19939 NewOpc = PPCISD::SRL;
19942 NewOpc = PPCISD::SRA;
19946 return DCI.DAG.getNode(NewOpc,
DL, VT, N0, SplatOnes);
19954 if (EltTy != MVT::i64 || SplatBits != 1)
19957 return DCI.DAG.getNode(
ISD::ADD, SDLoc(
N), VT, N0, N0);
19960SDValue PPCTargetLowering::combineSHL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19964 if (
N->getValueType(0).isVector())
19965 return combineVectorShift(
N, DCI);
19969 if (!Subtarget.isISA3_0() || !Subtarget.isPPC64() ||
19972 N->getValueType(0) != MVT::i64)
19987 ShiftBy = DCI.DAG.getConstant(CN1->
getZExtValue(),
DL, MVT::i32);
19993SDValue PPCTargetLowering::combineSRA(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19997 if (
N->getValueType(0).isVector())
19998 return combineVectorShift(
N, DCI);
20003SDValue PPCTargetLowering::combineSRL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20007 if (
N->getValueType(0).isVector())
20008 return combineVectorShift(
N, DCI);
20019 if (!Subtarget.isPPC64())
20025 auto isZextOfCompareWithConstant = [](
SDValue Op) {
20027 Op.getValueType() != MVT::i64)
20031 if (Cmp.getOpcode() !=
ISD::SETCC || !Cmp.hasOneUse() ||
20032 Cmp.getOperand(0).getValueType() != MVT::i64)
20036 int64_t NegConstant = 0 -
Constant->getSExtValue();
20045 bool LHSHasPattern = isZextOfCompareWithConstant(
LHS);
20046 bool RHSHasPattern = isZextOfCompareWithConstant(
RHS);
20049 if (LHSHasPattern && !RHSHasPattern)
20051 else if (!LHSHasPattern && !RHSHasPattern)
20055 EVT CarryType = Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
20058 SDValue Z = Cmp.getOperand(0);
20060 int64_t NegConstant = 0 -
Constant->getSExtValue();
20073 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
20091 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
20121 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
20124 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
20132 if (!GSDN || !ConstNode)
20160 EVT VT =
N->getValueType(0);
20161 if (!Subtarget.hasVSX())
20165 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
20177 unsigned NumOfEles =
RHS.getNumOperands();
20178 for (
unsigned i = 0; i < NumOfEles; ++i) {
20180 if (!CN || CN->getSExtValue() != 1)
20195SDValue PPCTargetLowering::combineADD(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20217 DAGCombinerInfo &DCI)
const {
20219 if (Subtarget.useCRBits()) {
20221 if (
SDValue CRTruncValue = DAGCombineTruncBoolExt(
N, DCI))
20222 return CRTruncValue;
20229 if (Op0.
getValueType() != MVT::i128 ||
N->getValueType(0) != MVT::i64)
20232 int EltToExtract = DCI.DAG.getDataLayout().isBigEndian() ? 1 : 0;
20242 EltToExtract = EltToExtract ? 0 : 1;
20252 return DCI.DAG.getNode(
20254 DCI.DAG.getTargetConstant(EltToExtract, dl, MVT::i32));
20259SDValue PPCTargetLowering::combineMUL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20260 SelectionDAG &DAG = DCI.DAG;
20263 if (!ConstOpOrElement)
20271 auto IsProfitable = [
this](
bool IsNeg,
bool IsAddOne, EVT VT) ->
bool {
20272 switch (this->Subtarget.getCPUDirective()) {
20295 return IsAddOne && IsNeg ? VT.
isVector() :
true;
20299 EVT VT =
N->getValueType(0);
20304 APInt MulAmtAbs = MulAmt.
abs();
20306 if ((MulAmtAbs - 1).isPowerOf2()) {
20310 if (!IsProfitable(IsNeg,
true, VT))
20323 }
else if ((MulAmtAbs + 1).isPowerOf2()) {
20327 if (!IsProfitable(IsNeg,
false, VT))
20348 DAGCombinerInfo &DCI)
const {
20352 SDNodeFlags
Flags =
N->getFlags();
20353 EVT VT =
N->getValueType(0);
20354 SelectionDAG &DAG = DCI.DAG;
20355 unsigned Opc =
N->getOpcode();
20357 bool LegalOps = !DCI.isBeforeLegalizeOps();
20365 if (!
Flags.hasNoSignedZeros())
20381bool PPCTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
20383 if (!Subtarget.is64BitELFABI())
20393 if (!TM.Options.GuaranteedTailCallOpt &&
DisableSCO)
20398 if (!Callee ||
Callee->isVarArg())
20411bool PPCTargetLowering::
20412isMaskAndCmp0FoldingBeneficial(
const Instruction &AndI)
const {
20417 if (CI->getBitWidth() > 64)
20419 int64_t ConstVal = CI->getZExtValue();
20421 (
isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF));
20430PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(
unsigned Flags)
const {
20436 if ((Flags & FlagSet) == FlagSet)
20439 if ((Flags & FlagSet) == FlagSet)
20442 if ((Flags & FlagSet) == FlagSet)
20445 if ((Flags & FlagSet) == FlagSet)
20466 if ((FrameIndexAlign % 4) != 0)
20467 FlagSet &=
~PPC::MOF_RPlusSImm16Mult4;
20468 if ((FrameIndexAlign % 16) != 0)
20469 FlagSet &=
~PPC::MOF_RPlusSImm16Mult16;
20473 if ((FrameIndexAlign % 4) == 0)
20475 if ((FrameIndexAlign % 16) == 0)
20488 auto SetAlignFlagsForImm = [&](
uint64_t Imm) {
20489 if ((Imm & 0x3) == 0)
20491 if ((Imm & 0xf) == 0)
20497 const APInt &ConstImm = CN->getAPIntValue();
20516 const APInt &ConstImm = CN->getAPIntValue();
20526 }
else if (
RHS.getOpcode() == PPCISD::Lo && !
RHS.getConstantOperandVal(1))
20537 return (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR ||
20546unsigned PPCTargetLowering::computeMOFlags(
const SDNode *Parent,
SDValue N,
20551 if (!Subtarget.hasP9Vector())
20556 if (Subtarget.hasPrefixInstrs())
20559 if (Subtarget.hasSPE())
20568 unsigned ParentOp = Parent->
getOpcode();
20572 if ((ID == Intrinsic::ppc_vsx_lxvp) || (ID == Intrinsic::ppc_vsx_stxvp)) {
20573 SDValue IntrinOp = (
ID == Intrinsic::ppc_vsx_lxvp)
20585 if (LSB->isIndexed())
20591 assert(MN &&
"Parent should be a MemSDNode!");
20596 "Not expecting scalar integers larger than 16 bytes!");
20599 else if (
Size == 32)
20606 else if (
Size == 256) {
20607 assert(Subtarget.pairedVectorMemops() &&
20608 "256-bit vectors are only available when paired vector memops is "
20616 else if (MemVT == MVT::f128 || MemVT.
isVector())
20647 FlagSet &= ~PPC::MOF_NoExt;
20652 bool IsNonP1034BitConst =
20656 IsNonP1034BitConst)
20669 int16_t ForceXFormImm = 0;
20672 Disp =
N.getOperand(0);
20673 Base =
N.getOperand(1);
20684 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
20685 Disp =
N.getOperand(0);
20686 Base =
N.getOperand(1);
20691 Disp = DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20700 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
20706 if (PartVT == MVT::f64 &&
20707 (ValVT == MVT::i32 || ValVT == MVT::i16 || ValVT == MVT::i8)) {
20716SDValue PPCTargetLowering::lowerToLibCall(
const char *LibCallName,
SDValue Op,
20720 EVT RetVT =
Op.getValueType();
20727 EVT ArgVT =
N.getValueType();
20731 Entry.IsZExt = !Entry.IsSExt;
20732 Args.push_back(Entry);
20740 (RetTy ==
F.getReturnType() ||
F.getReturnType()->isVoidTy());
20753SDValue PPCTargetLowering::lowerLibCallBasedOnType(
20754 const char *LibCallFloatName,
const char *LibCallDoubleName,
SDValue Op,
20756 if (
Op.getValueType() == MVT::f32)
20757 return lowerToLibCall(LibCallFloatName,
Op, DAG);
20759 if (
Op.getValueType() == MVT::f64)
20760 return lowerToLibCall(LibCallDoubleName,
Op, DAG);
20765bool PPCTargetLowering::isLowringToMASSFiniteSafe(
SDValue Op)
const {
20766 SDNodeFlags
Flags =
Op.getNode()->getFlags();
20767 return isLowringToMASSSafe(
Op) &&
Flags.hasNoSignedZeros() &&
20771bool PPCTargetLowering::isLowringToMASSSafe(
SDValue Op)
const {
20772 return Op.getNode()->getFlags().hasApproximateFuncs();
20775bool PPCTargetLowering::isScalarMASSConversionEnabled()
const {
20779SDValue PPCTargetLowering::lowerLibCallBase(
const char *LibCallDoubleName,
20780 const char *LibCallFloatName,
20781 const char *LibCallDoubleNameFinite,
20782 const char *LibCallFloatNameFinite,
20785 if (!isScalarMASSConversionEnabled() || !isLowringToMASSSafe(
Op))
20788 if (!isLowringToMASSFiniteSafe(
Op))
20789 return lowerLibCallBasedOnType(LibCallFloatName, LibCallDoubleName,
Op,
20792 return lowerLibCallBasedOnType(LibCallFloatNameFinite,
20793 LibCallDoubleNameFinite,
Op, DAG);
20797 return lowerLibCallBase(
"__xl_pow",
"__xl_powf",
"__xl_pow_finite",
20798 "__xl_powf_finite",
Op, DAG);
20802 return lowerLibCallBase(
"__xl_sin",
"__xl_sinf",
"__xl_sin_finite",
20803 "__xl_sinf_finite",
Op, DAG);
20807 return lowerLibCallBase(
"__xl_cos",
"__xl_cosf",
"__xl_cos_finite",
20808 "__xl_cosf_finite",
Op, DAG);
20812 return lowerLibCallBase(
"__xl_log",
"__xl_logf",
"__xl_log_finite",
20813 "__xl_logf_finite",
Op, DAG);
20817 return lowerLibCallBase(
"__xl_log10",
"__xl_log10f",
"__xl_log10_finite",
20818 "__xl_log10f_finite",
Op, DAG);
20822 return lowerLibCallBase(
"__xl_exp",
"__xl_expf",
"__xl_exp_finite",
20823 "__xl_expf_finite",
Op, DAG);
20848 unsigned Flags = computeMOFlags(Parent,
N, DAG);
20859 assert(Subtarget.isUsingPCRelativeCalls() &&
20860 "Must be using PC-Relative calls when a valid PC-Relative node is "
20890 Disp =
N.getOperand(1).getOperand(0);
20895 Base =
N.getOperand(0);
20903 EVT CNType = CN->getValueType(0);
20904 uint64_t CNImm = CN->getZExtValue();
20915 if ((CNType == MVT::i32 ||
isInt<32>(CNImm)) &&
20917 int32_t Addr = (int32_t)CNImm;
20922 uint32_t LIS = CNType == MVT::i32 ? PPC::LIS : PPC::LIS8;
20938 unsigned Opcode =
N.getOpcode();
20946 Base =
N.getOperand(0);
20965 Base = FI ?
N :
N.getOperand(1);
20966 Disp = FI ? DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20977 bool IsVarArg)
const {
20987 return Subtarget.isPPC64() && Subtarget.hasQuadwordAtomics();
21024 return Intrinsic::ppc_atomicrmw_xchg_i128;
21026 return Intrinsic::ppc_atomicrmw_add_i128;
21028 return Intrinsic::ppc_atomicrmw_sub_i128;
21030 return Intrinsic::ppc_atomicrmw_and_i128;
21032 return Intrinsic::ppc_atomicrmw_or_i128;
21034 return Intrinsic::ppc_atomicrmw_xor_i128;
21036 return Intrinsic::ppc_atomicrmw_nand_i128;
21044 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21048 Value *IncrLo = Builder.CreateTrunc(Incr, Int64Ty,
"incr_lo");
21050 Builder.CreateTrunc(Builder.CreateLShr(Incr, 64), Int64Ty,
"incr_hi");
21051 Value *LoHi = Builder.CreateIntrinsic(
21053 {AlignedAddr, IncrLo, IncrHi});
21054 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21055 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21056 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
21057 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
21058 return Builder.CreateOr(
21059 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
21066 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21072 Value *CmpLo = Builder.CreateTrunc(CmpVal, Int64Ty,
"cmp_lo");
21074 Builder.CreateTrunc(Builder.CreateLShr(CmpVal, 64), Int64Ty,
"cmp_hi");
21075 Value *NewLo = Builder.CreateTrunc(NewVal, Int64Ty,
"new_lo");
21077 Builder.CreateTrunc(Builder.CreateLShr(NewVal, 64), Int64Ty,
"new_hi");
21080 Builder.CreateCall(IntCmpXchg, {AlignedAddr, CmpLo, CmpHi, NewLo, NewHi});
21082 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21083 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21084 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
21085 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
21086 return Builder.CreateOr(
21087 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
21091 return Subtarget.useCRBits();
21096bool PPCTargetLowering::isShuffleMaskLegal(
ArrayRef<int> Mask,
EVT VT)
const {
21107 DAGCombinerInfo &DCI)
const {
21112 EVT ResVT =
N->getValueType(0);
21114 EVT SrcVT = Src.getValueType();
21119 if (ResVT != MVT::i16 && ResVT != MVT::i8)
21122 GenerateVBPERM(DAG, dl, Src, SrcVT, TruncResVT, IsLittleEndian);
21135 bool IsV16i8 = (ResVT == MVT::v16i1 && SrcVT == MVT::v16i8);
21136 bool IsV8i16 = (ResVT == MVT::v8i1 && SrcVT == MVT::v8i16);
21137 bool IsV8i8 = (ResVT == MVT::v8i1 && SrcVT == MVT::v8i8);
21139 if (!IsV16i8 && !IsV8i16 && !IsV8i8)
21147 SmallVector<int, 16> BitIndices(16, 128);
21151 BitIndices[Idx] = EltSize * (NumElts - Idx) - 1;
21152 if (IsV8i8 && IsLE)
21153 BitIndices[Idx] += 64;
21156 std::reverse(BitIndices.begin(), BitIndices.end());
21158 for (
auto Idx : BitIndices)
21163 DAG.
getConstant(Intrinsic::ppc_altivec_vbpermq, dl, MVT::i32),
21171 bool BVNIsConstantSplat,
21172 unsigned SplatBitSize)
const {
21174 if (!BVNIsConstantSplat || !Subtarget.hasVSX() || !Subtarget.hasP8Vector() ||
21175 Subtarget.hasP10Vector())
21178 EVT VT =
Op->getValueType(0);
21179 if (!((SplatBitSize == 64 && VT == MVT::v2f64) ||
21180 (SplatBitSize == 32 && VT == MVT::v4f32)))
21187 APFloat APFloatVal = CN->getValueAPF();
21189 APSInt IntResult(16,
false);
21192 if (!(IsExact && IntResult <= 15 && IntResult >= -16 && !APFloatVal.
isZero()))
21195 int64_t
IntVal = IntResult.getSExtValue();
21200 if (SplatBitSize == 64)
21203 DAG.
getConstant(Intrinsic::ppc_vsx_xvcvsxwdp, dl, MVT::i32), IntSplat);
21205 return DAG.
getNode(PPCISD::XVCVSXWSP, dl, MVT::v4f32, IntSplat);
static MCRegister MatchRegisterName(StringRef Name)
static unsigned getCallOpcode(const MachineFunction &CallerF, bool IsIndirect, bool IsTailCall, std::optional< CallLowering::PtrAuthInfo > &PAI, MachineRegisterInfo &MRI)
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
static std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isLoad(int Opcode)
static bool isFloatingPointZero(SDValue Op)
isFloatingPointZero - Return true if this is +0.0.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
Atomic ordering constants.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
This file defines the DenseMap class.
const HexagonInstrInfo * TII
static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl)
CreateCopyOfByValArgument - Make a copy of an aggregate at address specified by "Src" to address "Dst...
Module.h This file contains the declarations for the Module class.
This defines the Use class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
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 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 MachineBasicBlock * emitAtomicCmpSwapSoftware(MachineInstr &MI, MachineBasicBlock *BB, const TargetInstrInfo *TII, const PPCSubtarget &Subtarget)
Emit software-emulated atomic compare-and-swap for I8/I16 without hardware partword atomic support.
static SDValue DAGCombineSube(SDNode *N, llvm::PPCTargetLowering::DAGCombinerInfo &DCI)
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 IsSelect(unsigned Opcode, bool CheckOnlyCC=false)
Check if the opcode is a SELECT or SELECT_CC variant.
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 void prepareOutOfLineGlueCall(SelectionDAG &DAG, SDValue &Callee, SDValue &Glue, SDValue &Chain, SDValue CallSeqStart, const CallBase *CB, const SDLoc &dl, bool hasNest, const PPCSubtarget &Subtarget)
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 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 IsSelectCC(unsigned Opcode)
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 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 combineXorSelectCC(SDNode *N, SelectionDAG &DAG)
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 bool canConvertToVcmpequb(SDValue &LHS, SDValue &RHS, bool IsPPC64)
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 CallInst * callIntrinsic(IRBuilderBase &Builder, Intrinsic::ID Id)
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 void prepareIndirectCall(SelectionDAG &DAG, SDValue &Callee, SDValue &Glue, SDValue &Chain, const SDLoc &dl)
static SDValue combineSELECT_CCBitFloor(SDNode *N, SelectionDAG &DAG)
Optimize the bitfloor(X) pattern for PowerPC.
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 MachineBasicBlock * emitSelect(MachineInstr &MI, MachineBasicBlock *BB, const TargetInstrInfo *TII, const PPCSubtarget &Subtarget)
Emit SELECT instruction, using ISEL if available, otherwise use branch-based control flow.
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 void createAtomicLoopBlocks(MachineFunction *F, MachineBasicBlock *BB, MachineBasicBlock *&loop1MBB, MachineBasicBlock *&loop2MBB, MachineBasicBlock *&exitMBB, MachineInstr &MI, MachineFunction::iterator It)
Helper function to create basic blocks for atomic compare-and-swap.
static SDValue combineBVZEXTLOAD(SDNode *N, SelectionDAG &DAG)
static SDValue combineZextSetccWithZero(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...
static MachineBasicBlock * emitAtomicCmpSwapHardware(MachineInstr &MI, MachineBasicBlock *BB, const TargetInstrInfo *TII, const PPCSubtarget &Subtarget)
Emit hardware-supported atomic compare-and-swap for I32/I64 and I8/I16 with partword atomic support.
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 void signExtendOperandIfUnknown(MachineInstr &MI, MachineBasicBlock *BB, unsigned OpIdx, bool IsByte, const PPCInstrInfo *TII)
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")
This file describes how to lower LLVM code to machine code.
static constexpr int TPOffset
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
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) 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 ult(const APInt &RHS) const
Unsigned less than comparison.
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
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 constexpr BranchProbability getOne()
static constexpr BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
CCState - This class holds information needed while lowering arguments and return values.
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool isStrictFP() const
Determine if the call requires strict floating point semantics.
CallingConv::ID getCallingConv() const
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getCalledOperand() const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
This class represents a function call, abstracting a target machine's calling convention.
ConstantFP - Floating Point Values [float, double].
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
LLVM_ABI unsigned getLargestLegalIntTypeSizeInBits() const
Returns the size of largest legal integer type size, or 0 if none are set.
LLVM_ABI IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
int64_t getOffset() const
unsigned getTargetFlags() const
const GlobalValue * getGlobal() const
LLVM_ABI const GlobalObject * getAliaseeObject() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
void setThreadLocalMode(ThreadLocalMode Val)
bool hasHiddenVisibility() const
LLVM_ABI StringRef getSection() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Type * getValueType() const
bool hasProtectedVisibility() const
Common base class shared among various IRBuilders.
LLVM_ABI bool hasAtomicLoad() const LLVM_READONLY
Return true if this atomic instruction loads from memory.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
This is an important class for using LLVM in a threaded context.
Base class for LoadSDNode and StoreSDNode.
Tracks which library functions to use for a particular subtarget.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
TypeSize getValue() const
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
Wrapper class representing physical registers. Should be passed by value.
MCSymbolXCOFF * getQualNameSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
@ INVALID_SIMPLE_VALUE_TYPE
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
MCSymbol * getPICBaseSymbol() const
getPICBaseSymbol - Return a function-local symbol to represent the PIC base.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
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...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
AtomicOrdering getFailureOrdering() const
For cmpxchg atomic operations, return the atomic ordering requirements when store does not occur.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID for this memory operation.
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.
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
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 bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
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 the unique 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
MCRegister getGlueCodeDescriptorRegister() 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 isTruncateFree(Type *Ty1, Type *Ty2) const override
isTruncateFree - Return true if it's free to truncate a value of type Ty1 to type Ty2.
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isFPExtFree(EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation is free (for instance, because single-precision floating-point numb...
PPC::AddrMode SelectForceXFormMode(SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG) const
SelectForceXFormMode - Given the specified address, force it to be represented as an indexed [r+r] op...
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool hasInlineStackProbe(const MachineFunction &MF) const override
MachineBasicBlock * emitEHSjLjSetJmp(MachineInstr &MI, MachineBasicBlock *MBB) const
bool supportsTailCallFor(const CallBase *CB) const
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
MachineBasicBlock * emitProbedAlloca(MachineInstr &MI, MachineBasicBlock *MBB) const
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, NegatibleCost &Cost, unsigned Depth=0) const override
Return the newly negated expression if the cost is not expensive and set the cost in Cost to indicate...
bool SelectAddressRegImm(SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG, MaybeAlign EncodingAlignment) const
SelectAddressRegImm - Returns true if the address N can be represented by a base register plus a sign...
SDValue expandVSXLoadForLE(SDNode *N, DAGCombinerInfo &DCI) const
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
LowerAsmOperandForConstraint - Lower the specified operand into the Ops vector.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
bool hasMultipleConditionRegisters(EVT VT) const override
Does the target have multiple (allocatable) condition registers that can be used to store the results...
Align getByValTypeAlignment(Type *Ty, const DataLayout &DL) const override
getByValTypeAlignment - Return the desired alignment for ByVal aggregate function arguments in the ca...
bool SelectAddressRegReg(SDValue N, SDValue &Base, SDValue &Index, SelectionDAG &DAG, MaybeAlign EncodingAlignment=std::nullopt) const
SelectAddressRegReg - Given the specified addressed, check to see if it can be more efficiently repre...
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.
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, 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...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
bool preferIncOfAddToSubOfNot(EVT VT) const override
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
const MCPhysReg * getScratchRegisters(CallingConv::ID CC) const override
Returns a 0 terminated array of registers that can be safely used as scratch registers.
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
getPreIndexedAddressParts - returns true by value, base pointer and offset pointer and addressing mod...
FastISel * createFastISel(FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo, const LibcallLoweringInfo *LibcallLowering) const override
createFastISel - This method returns a target-specific FastISel object, or null if the target does no...
bool isProfitableToHoist(Instruction *I) const override
isProfitableToHoist - Check if it is profitable to hoist instruction I to its dominator block.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint, return the type of constraint it is for this target.
const MCExpr * getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const override
This returns the relocation base for the given PIC jumptable, the same as getPICJumpTableRelocBase,...
bool shallExtractConstSplatVectorElementToStore(Type *VectorTy, unsigned ElemSizeInBits, unsigned &Index) const override
Return true if the target shall perform extract vector element and store given that the vector is kno...
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
It returns EVT::Other if the type should be determined using generic target-independent logic.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue expandVSXStoreForLE(SDNode *N, DAGCombinerInfo &DCI) const
void CollectTargetIntrinsicOperands(const CallInst &I, SmallVectorImpl< SDValue > &Ops, SelectionDAG &DAG) const override
unsigned getStackProbeSize(const MachineFunction &MF) const
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
PPCTargetLowering(const PPCTargetMachine &TM, const PPCSubtarget &STI)
bool useLoadStackGuardNode(const Module &M) const override
Override to support customized stack guard loading.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
isFMAFasterThanFMulAndFAdd - Return true if an FMA operation is faster than a pair of fmul and fadd i...
MachineBasicBlock * EmitAtomicBinary(MachineInstr &MI, MachineBasicBlock *MBB, unsigned BinOpcode, unsigned CmpOpcode=0, unsigned CmpPred=0) const
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.
bool isJumpTableRelative() const override
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,...
MachineBasicBlock * EmitPartwordAtomicBinary(MachineInstr &MI, MachineBasicBlock *MBB, unsigned Opcode, unsigned CmpOpcode=0, unsigned CmpPred=0) const
bool isAccessedAsGotIndirect(SDValue N) const
Align getPrefLoopAlignment(MachineLoop *ML) const override
Return the preferred loop alignment.
bool shouldInlineQuadwordAtomics() const
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool isLegalAddImmediate(int64_t Imm) const override
isLegalAddImmediate - Return true if the specified immediate is legal add immediate,...
Common code between 32-bit and 64-bit PowerPC targets.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
Wrapper class representing virtual and physical registers.
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, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
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 getMachineOpcode() const
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...
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...
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 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.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool willNotOverflowSub(bool IsSigned, SDValue N0, SDValue N1) const
Determine if the result of the sub of 2 nodes can never overflow.
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).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
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 getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
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 SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
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 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 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 MMOMetadata &Metadata=MMOMetadata())
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 ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
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 getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
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
Represent a constant reference to a string, i.e.
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
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...
virtual bool isShuffleMaskLegal(ArrayRef< int >, EVT) const
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual bool shouldExpandBuildVectorWithShuffles(EVT, unsigned DefinedValues) const
void setMinimumBitTestCmps(unsigned Val)
Set the minimum of largest of number of comparisons to generate BitTest.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
MVT getVectorIdxTy(const DataLayout &DL) const
Returns the type to be used for the index operand of: ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT...
const TargetMachine & getTargetMachine() const
unsigned MaxLoadsPerMemcmp
Specify maximum number of load instructions per memcmp call.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Sched::Preference getSchedulingPreference() const
Return target scheduling preference.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
bool hasBigEndianPartOrdering(EVT VT, const DataLayout &DL) const
When splitting a value of the specified type into parts, does the Lo or Hi part come first?
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const
Returns the type for the shift amount of a shift opcode.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr) const
Return the preferred loop alignment.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual bool isJumpTableRelative() const
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setMinimumJumpTableEntries(unsigned Val)
Indicate the minimum number of blocks to generate jump tables.
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
unsigned MaxLoadsPerMemcmpOptSize
Likewise for functions with the OptSize attribute.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
unsigned GatherAllAliasesMaxDepth
Depth that GatherAllAliases should continue looking for chain dependencies when trying to find a more...
NegatibleCost
Enum that specifies when a float negation is beneficial.
virtual bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const
Returns true if arguments should be sign-extended in lib calls.
std::vector< ArgListEntry > ArgListTy
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
void setJumpIsExpensive(bool isExpensive=true)
Tells the code generator not to expand logic operations on comparison predicates into separate sequen...
virtual MCSymbol * getFunctionEntryPointSymbol(const GlobalValue *Func, const TargetMachine &TM) const
If supported, return the function entry point symbol.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual const MCExpr * getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const
This returns the relocation base for the given PIC jumptable, the same as getPICJumpTableRelocBase,...
SDValue lowerCmpEqZeroToCtlzSrl(SDValue Op, SelectionDAG &DAG) const
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, const SDLoc &DL, const SDValue OldLHS, const SDValue OldRHS) const
Soften the operands of a comparison.
SDValue getCheaperNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, unsigned Depth=0) const
This is the helper function to return the newly negated expression only when the cost is cheaper.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, NegatibleCost &Cost, unsigned Depth=0) const
Return the newly negated expression if the cost is not expensive and set the cost in Cost to indicate...
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
virtual SDValue 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 SDValue getSqrtInputTest(SDValue Operand, SelectionDAG &DAG, const DenormalMode &Mode, SDNodeFlags Flags={}) const
Return a target-dependent comparison result if the input operand is suitable for use with a square ro...
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 PPCGenScalarMASSEntries
Enables scalar MASS conversions.
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI bool isEmptyTy() const
Return true if this type is empty, that is, it has no elements or all of its elements are empty.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
@ FloatTyID
32-bit floating point type
@ DoubleTyID
64-bit floating point type
@ FP128TyID
128-bit floating point type (112-bit significand)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFunctionTy() const
True if this is an instance of FunctionType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ 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...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ INIT_TRAMPOLINE
INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ BR_JT
BR_JT - Jumptable branch.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ CALLSEQ_START
CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of a call sequence,...
@ GET_DYNAMIC_AREA_OFFSET
GET_DYNAMIC_AREA_OFFSET - get offset from native SP to the address of the most recent dynamic alloca.
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ ADJUST_TRAMPOLINE
ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isUnsignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs an unsigned comparison when used with intege...
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ MO_TLSLDM_FLAG
MO_TLSLDM_FLAG - on AIX the ML relocation type is only valid for a reference to a TOC symbol from the...
@ MO_PIC_LO_FLAG
MO_PIC_LO_FLAG = MO_PIC_FLAG | MO_LO.
@ MO_TPREL_PCREL_FLAG
MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TPREL_FLAG.
@ MO_GOT_TPREL_PCREL_FLAG
MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
@ MO_GOT_PCREL_FLAG
MO_GOT_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG.
@ MO_TLSGDM_FLAG
MO_TLSGDM_FLAG - If this bit is set the symbol reference is relative to the region handle of TLS Gene...
@ MO_PCREL_FLAG
MO_PCREL_FLAG - If this bit is set, the symbol reference is relative to the current instruction addre...
@ MO_TLSLD_FLAG
MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to TLS Local Dynamic model.
@ MO_TLS_PCREL_FLAG
MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TLS.
@ MO_PLT
On PPC, the 12 bits are not enough for all target operand flags.
@ MO_TLS
Symbol for VK_TLS fixup attached to an ADD instruction.
@ MO_TPREL_FLAG
MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to the thread pointer and the sy...
@ MO_LO
MO_LO, MO_HA - lo16(symbol) and ha16(symbol)
@ MO_GOT_TLSLD_PCREL_FLAG
MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
@ MO_PIC_HA_FLAG
MO_PIC_HA_FLAG = MO_PIC_FLAG | MO_HA.
@ MO_TLSGD_FLAG
MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to TLS General Dynamic model for ...
@ MO_GOT_TLSGD_PCREL_FLAG
MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
@ MO_PIC_FLAG
MO_PIC_FLAG - If this bit is set, the symbol reference is relative to the function's picbase,...
@ MFOCRF
R32 = MFOCRF(CRREG, INFLAG) - Represents the MFOCRF instruction.
@ VADD_SPLAT
VRRC = VADD_SPLAT Elt, EltSize - Temporary node to be expanded during instruction selection to optimi...
@ PPC32_PICGOT
GPRC = address of GLOBAL_OFFSET_TABLE.
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
@ SRA_ADDZE
The combination of sra[wd]i and addze used to implemented signed integer division by a power of 2.
Define some predicates that are used for node matching.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
SDValue get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG)
get_VSPLTI_elt - If this is a build_vector of constants which can be formed by using a vspltis[bhw] i...
bool isXXBRDShuffleMask(ShuffleVectorSDNode *N)
isXXBRDShuffleMask - Return true if this is a shuffle mask suitable for a XXBRD instruction.
bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, unsigned ShuffleKind, SelectionDAG &DAG)
isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for a VRGH* instruction with the ...
bool isVPKUDUMShuffleMask(ShuffleVectorSDNode *N, unsigned ShuffleKind, SelectionDAG &DAG)
isVPKUDUMShuffleMask - Return true if this is the shuffle mask for a VPKUDUM instruction.
bool isVMRGEOShuffleMask(ShuffleVectorSDNode *N, bool CheckEven, unsigned ShuffleKind, SelectionDAG &DAG)
isVMRGEOShuffleMask - Return true if this is a shuffle mask suitable for a VMRGEW or VMRGOW instructi...
bool isXXBRQShuffleMask(ShuffleVectorSDNode *N)
isXXBRQShuffleMask - Return true if this is a shuffle mask suitable for a XXBRQ instruction.
bool isXXBRWShuffleMask(ShuffleVectorSDNode *N)
isXXBRWShuffleMask - Return true if this is a shuffle mask suitable for a XXBRW instruction.
bool isXXPERMDIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, bool &Swap, bool IsLE)
isXXPERMDIShuffleMask - Return true if this is a shuffle mask suitable for a XXPERMDI instruction.
bool isXXBRHShuffleMask(ShuffleVectorSDNode *N)
isXXBRHShuffleMask - Return true if this is a shuffle mask suitable for a XXBRH instruction.
unsigned getSplatIdxForPPCMnemonics(SDNode *N, unsigned EltSize, SelectionDAG &DAG)
getSplatIdxForPPCMnemonics - Return the splat index as a value that is appropriate for PPC mnemonics ...
bool isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, bool &Swap, bool IsLE)
isXXSLDWIShuffleMask - Return true if this is a shuffle mask suitable for a XXSLDWI instruction.
FastISel * createFastISel(FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo, const LibcallLoweringInfo *LibcallLowering)
int isVSLDOIShuffleMask(SDNode *N, unsigned ShuffleKind, SelectionDAG &DAG)
isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift amount, otherwise return -1.
bool isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, unsigned ShuffleKind, SelectionDAG &DAG)
isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for a VRGL* instruction with the ...
bool isXXINSERTWMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, unsigned &InsertAtByte, bool &Swap, bool IsLE)
isXXINSERTWMask - Return true if this VECTOR_SHUFFLE can be handled by the XXINSERTW instruction intr...
bool isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize)
isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand specifies a splat of a singl...
bool isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, unsigned ShuffleKind, SelectionDAG &DAG)
isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a VPKUWUM instruction.
bool isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, unsigned ShuffleKind, SelectionDAG &DAG)
isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a VPKUHUM instruction.
Invariant opcodes: All instruction sets have these as their low opcodes.
@ XTY_ER
External reference.
initializer< Ty > init(const Ty &Val)
constexpr uint64_t PointerSize
aarch64 pointer size.
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
NodeAddr< FuncNode * > Func
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
static bool isIndirectCall(const MachineInstr &MI)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool checkConvertToNonDenormSingle(APFloat &ArgAPFloat)
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
bool isIntS16Immediate(SDNode *N, int16_t &Imm)
isIntS16Immediate - This method tests to see if the node is either a 32-bit or 64-bit immediate,...
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
static bool isRunOfOnes64(uint64_t Val, unsigned &MB, unsigned &ME)
bool isa_and_nonnull(const Y &Val)
bool RetCC_PPC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool CC_PPC64_ELF(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool convertToNonDenormSingle(APInt &ArgAPInt)
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
bool CC_PPC32_SVR4_ByVal(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool CC_PPC32_SVR4(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr RegState getDefRegState(bool B)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool RetCC_PPC_Cold(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
@ Success
The lock was released successfully.
LLVM_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
const unsigned PerfectShuffleTable[6561+1]
AtomicOrdering
Atomic ordering for LLVM's memory model.
bool isIntS34Immediate(SDNode *N, int64_t &Imm)
isIntS34Immediate - This method tests if value of node given can be accurately represented as a sign ...
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
DWARFExpression::Operation Op
LLVM_ABI bool isPhysRegUsedAfter(Register Reg, MachineBasicBlock::iterator MBI)
Check if physical register Reg is used after MBI.
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
constexpr unsigned BitWidth
bool CC_PPC32_SVR4_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME)
Returns true iff Val consists of one contiguous run of 1s with any number of 0s on either side.
@ Increment
Incrementally increasing token ID.
@ Enabled
Convert any .debug_str_offsets tables to DWARF64 if needed.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This is used by foldLoadsRecursive() to capture a Root Load node which is of type or(load,...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Represent subnormal handling kind for floating point instruction inputs and outputs.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
LLVM_ABI std::string getEVTString() const
This function returns value type as a string, e.g. "i32".
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isExtended() const
Test if the given EVT is extended (as opposed to being simple).
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
unsigned getByValSize() const
void setByValSize(unsigned S)
Align getNonZeroByValAlign() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
bool isConstant() const
Returns true if we know the value of all bits.
const APInt & getConstant() const
Returns the value when all bits have a known value.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Structure that collects some common arguments that get passed around between the functions for call l...
const CallingConv::ID CallConv
These are IR-level optimization flags that may be propagated to SDNodes.
void setNoFPExcept(bool b)
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setIsPostTypeLegalization(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setTailCall(bool Value=true)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
bool isBeforeLegalizeOps() const
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.