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(), RLI.AAInfo, RLI.Ranges);
8607bool PPCTargetLowering::canReuseLoadAddress(
SDValue Op,
EVT MemVT,
8612 if (
Op->isStrictFPOpcode())
8617 (Subtarget.hasFPCVT() ||
Op.getValueType() == MVT::i32);
8621 Op.getOperand(0).getValueType())) {
8623 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8628 if (!LD ||
LD->getExtensionType() != ET ||
LD->isVolatile() ||
8629 LD->isNonTemporal())
8631 if (
LD->getMemoryVT() != MemVT)
8641 RLI.Ptr =
LD->getBasePtr();
8642 if (
LD->isIndexed() && !
LD->getOffset().isUndef()) {
8644 "Non-pre-inc AM on PPC?");
8649 RLI.Chain =
LD->getChain();
8650 RLI.MPI =
LD->getPointerInfo();
8651 RLI.IsDereferenceable =
LD->isDereferenceable();
8652 RLI.IsInvariant =
LD->isInvariant();
8653 RLI.Alignment =
LD->getAlign();
8654 RLI.AAInfo =
LD->getAAInfo();
8655 RLI.Ranges =
LD->getRanges();
8657 RLI.ResChain =
SDValue(LD,
LD->isIndexed() ? 2 : 1);
8664bool PPCTargetLowering::directMoveIsProfitable(
const SDValue &
Op)
const {
8665 SDNode *Origin =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0).getNode();
8672 if (!Subtarget.hasP9Vector() &&
8676 for (SDUse &Use : Origin->
uses()) {
8679 if (
Use.getResNo() != 0)
8706 bool IsSingle =
Op.getValueType() == MVT::f32 && Subtarget.hasFPCVT();
8707 unsigned ConvOpc = IsSingle ? (IsSigned ? PPCISD::FCFIDS : PPCISD::FCFIDUS)
8708 : (IsSigned ? PPCISD::FCFID : PPCISD::FCFIDU);
8709 EVT ConvTy = IsSingle ? MVT::f32 : MVT::f64;
8710 if (
Op->isStrictFPOpcode()) {
8712 Chain =
Op.getOperand(0);
8714 DAG.
getVTList(ConvTy, MVT::Other), {Chain, Src}, Flags);
8716 return DAG.
getNode(ConvOpc, dl, ConvTy, Src);
8724 const SDLoc &dl)
const {
8725 assert((
Op.getValueType() == MVT::f32 ||
8726 Op.getValueType() == MVT::f64) &&
8727 "Invalid floating point type as target of conversion");
8728 assert(Subtarget.hasFPCVT() &&
8729 "Int to FP conversions with direct moves require FPCVT");
8730 SDValue Src =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0);
8731 bool WordInt = Src.getSimpleValueType().SimpleTy == MVT::i32;
8734 unsigned MovOpc = (WordInt && !
Signed) ? PPCISD::MTVSRZ : PPCISD::MTVSRA;
8753 for (
unsigned i = 1; i < NumConcat; ++i)
8760 const SDLoc &dl)
const {
8761 bool IsStrict =
Op->isStrictFPOpcode();
8762 unsigned Opc =
Op.getOpcode();
8763 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8766 "Unexpected conversion type");
8767 assert((
Op.getValueType() == MVT::v2f64 ||
Op.getValueType() == MVT::v4f32) &&
8768 "Supports conversions to v2f64/v4f32 only.");
8772 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8775 bool FourEltRes =
Op.getValueType() == MVT::v4f32;
8780 MVT IntermediateVT = FourEltRes ? MVT::v4i32 : MVT::v2i64;
8782 SmallVector<int, 16> ShuffV;
8783 for (
unsigned i = 0; i < WideNumElts; ++i)
8786 int Stride = FourEltRes ? WideNumElts / 4 : WideNumElts / 2;
8787 int SaveElts = FourEltRes ? 4 : 2;
8788 if (Subtarget.isLittleEndian())
8789 for (
int i = 0; i < SaveElts; i++)
8790 ShuffV[i * Stride] = i;
8792 for (
int i = 1; i <= SaveElts; i++)
8793 ShuffV[i * Stride - 1] = i - 1;
8801 Arrange = DAG.
getBitcast(IntermediateVT, Arrange);
8802 EVT ExtVT = Src.getValueType();
8803 if (Subtarget.hasP9Altivec())
8814 {Op.getOperand(0), Extend}, Flags);
8816 return DAG.
getNode(
Opc, dl,
Op.getValueType(), Extend);
8824 bool IsStrict =
Op->isStrictFPOpcode();
8825 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8830 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8832 EVT InVT = Src.getValueType();
8833 EVT OutVT =
Op.getValueType();
8836 return LowerINT_TO_FPVector(
Op, DAG, dl);
8839 if (
Op.getValueType() == MVT::f128)
8840 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8843 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
8846 if (Src.getValueType() == MVT::i1) {
8858 if (Subtarget.hasDirectMove() && directMoveIsProfitable(
Op) &&
8859 Subtarget.isPPC64() && Subtarget.hasFPCVT())
8860 return LowerINT_TO_FPDirectMove(
Op, DAG, dl);
8862 assert((IsSigned || Subtarget.hasFPCVT()) &&
8863 "UINT_TO_FP is supported only with FPCVT");
8865 if (Src.getValueType() == MVT::i64) {
8880 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT() &&
8881 !
Op->getFlags().hasApproximateFuncs()) {
8921 if (canReuseLoadAddress(SINT, MVT::i64, RLI, DAG)) {
8924 Bits = DAG.
getLoad(MVT::f64, dl, RLI.Chain, RLI.Ptr, RLI.MPI,
8925 RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo,
nullptr);
8928 }
else if (Subtarget.hasLFIWAX() &&
8929 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::SEXTLOAD)) {
8930 MachineMemOperand *MMO =
8932 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8936 Ops, MVT::i32, MMO);
8939 }
else if (Subtarget.hasFPCVT() &&
8940 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::ZEXTLOAD)) {
8941 MachineMemOperand *MMO =
8943 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8947 Ops, MVT::i32, MMO);
8950 }
else if (((Subtarget.hasLFIWAX() &&
8952 (Subtarget.hasFPCVT() &&
8967 "Expected an i32 store");
8973 RLI.Alignment =
Align(4);
8975 MachineMemOperand *MMO =
8977 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8980 PPCISD::LFIWZX : PPCISD::LFIWAX,
8981 dl, DAG.
getVTList(MVT::f64, MVT::Other),
8982 Ops, MVT::i32, MMO);
8983 Chain =
Bits.getValue(1);
8991 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
8995 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)},
9004 assert(Src.getValueType() == MVT::i32 &&
9005 "Unhandled INT_TO_FP type in custom expander!");
9015 if (Subtarget.hasLFIWAX() || Subtarget.hasFPCVT()) {
9018 if (!(ReusingLoad = canReuseLoadAddress(Src, MVT::i32, RLI, DAG))) {
9028 "Expected an i32 store");
9034 RLI.Alignment =
Align(4);
9037 MachineMemOperand *MMO =
9039 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
9045 if (ReusingLoad && RLI.ResChain) {
9049 assert(Subtarget.isPPC64() &&
9050 "i32->FP without LFIWAX supported only on PPC64");
9059 Chain, dl, Ext64, FIdx,
9065 MVT::f64, dl, Chain, FIdx,
9074 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
9078 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)}, Flags);
9095 uint64_t
Mode = CVal->getZExtValue();
9096 assert(
Mode < 4 &&
"Unsupported rounding mode!");
9097 unsigned InternalRnd =
Mode ^ (~(
Mode >> 1) & 1);
9098 if (Subtarget.isISA3_0())
9101 PPC::MFFSCRNI, Dl, {MVT::f64, MVT::Other},
9102 {DAG.getConstant(InternalRnd, Dl, MVT::i32, true), Chain}),
9105 (InternalRnd & 2) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
9106 {DAG.
getConstant(30, Dl, MVT::i32,
true), Chain});
9108 (InternalRnd & 1) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
9126 if (!Subtarget.isISA3_0()) {
9127 MFFS = DAG.
getNode(PPCISD::MFFS, Dl, {MVT::f64, MVT::Other}, Chain);
9131 if (Subtarget.isPPC64()) {
9132 if (Subtarget.isISA3_0()) {
9137 PPC::RLDIMI, Dl, MVT::i64,
9142 NewFPSCR =
SDValue(InsertRN, 0);
9149 SDValue Addr = Subtarget.isLittleEndian()
9153 if (Subtarget.isISA3_0()) {
9154 Chain = DAG.
getStore(Chain, Dl, DstFlag, Addr, MachinePointerInfo());
9156 Chain = DAG.
getStore(Chain, Dl, MFFS, StackSlot, MachinePointerInfo());
9158 DAG.
getLoad(MVT::i32, Dl, Chain, Addr, MachinePointerInfo());
9161 PPC::RLWIMI, Dl, MVT::i32,
9162 {Tmp, DstFlag, DAG.getTargetConstant(0, Dl, MVT::i32),
9163 DAG.getTargetConstant(30, Dl, MVT::i32),
9164 DAG.getTargetConstant(31, Dl, MVT::i32)}),
9166 Chain = DAG.
getStore(Chain, Dl, Tmp, Addr, MachinePointerInfo());
9169 DAG.
getLoad(MVT::f64, Dl, Chain, StackSlot, MachinePointerInfo());
9172 if (Subtarget.isISA3_0())
9178 PPC::MTFSF, Dl, MVT::Other,
9206 EVT VT =
Op.getValueType();
9211 SDValue MFFS = DAG.
getNode(PPCISD::MFFS, dl, {MVT::f64, MVT::Other}, Chain);
9222 Chain = DAG.
getStore(Chain, dl, MFFS, StackSlot, MachinePointerInfo());
9226 "Stack slot adjustment is valid only on big endian subtargets!");
9229 CWD = DAG.
getLoad(MVT::i32, dl, Chain, Addr, MachinePointerInfo());
9256 EVT VT =
Op.getValueType();
9260 VT ==
Op.getOperand(1).getValueType() &&
9280 SDValue OutOps[] = { OutLo, OutHi };
9285 EVT VT =
Op.getValueType();
9289 VT ==
Op.getOperand(1).getValueType() &&
9309 SDValue OutOps[] = { OutLo, OutHi };
9315 EVT VT =
Op.getValueType();
9318 VT ==
Op.getOperand(1).getValueType() &&
9338 SDValue OutOps[] = { OutLo, OutHi };
9345 EVT VT =
Op.getValueType();
9352 EVT AmtVT =
Z.getValueType();
9362 X = DAG.
getNode(PPCISD::SHL, dl, VT,
X, IsFSHL ? Z : SubZ);
9363 Y = DAG.
getNode(PPCISD::SRL, dl, VT,
Y, IsFSHL ? SubZ : Z);
9375 static const MVT VTys[] = {
9376 MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
9379 EVT ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1];
9382 if (Val == ((1LLU << (SplatSize * 8)) - 1)) {
9387 EVT CanonicalVT = VTys[SplatSize-1];
9400 const SDLoc &dl,
EVT DestVT = MVT::Other) {
9401 if (DestVT == MVT::Other) DestVT =
Op.getValueType();
9410 EVT DestVT = MVT::Other) {
9411 if (DestVT == MVT::Other) DestVT =
LHS.getValueType();
9420 EVT DestVT = MVT::Other) {
9423 DAG.
getConstant(IID, dl, MVT::i32), Op0, Op1, Op2);
9435 for (
unsigned i = 0; i != 16; ++i)
9456 EVT VecVT = V->getValueType(0);
9457 bool RightType = VecVT == MVT::v2f64 ||
9458 (HasP8Vector && VecVT == MVT::v4f32) ||
9459 (HasDirectMove && (VecVT == MVT::v2i64 || VecVT == MVT::v4i32));
9463 bool IsSplat =
true;
9464 bool IsLoad =
false;
9470 if (V->isConstant())
9472 for (
int i = 0, e = V->getNumOperands(); i < e; ++i) {
9473 if (V->getOperand(i).isUndef())
9477 if (V->getOperand(i).getOpcode() ==
ISD::LOAD ||
9479 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD) ||
9481 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD) ||
9483 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD))
9487 if (V->getOperand(i) != Op0 ||
9488 (!IsLoad && !V->isOnlyUserOf(V->getOperand(i).getNode())))
9491 return !(IsSplat && IsLoad);
9501 (
Op.getValueType() != MVT::f128))
9506 if ((
Lo.getValueType() != MVT::i64) || (
Hi.getValueType() != MVT::i64))
9509 if (!Subtarget.isLittleEndian())
9512 return DAG.
getNode(PPCISD::BUILD_FP128, dl, MVT::f128,
Lo,
Hi);
9520 InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED) {
9521 IsPermuted = InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED;
9534 APFloat APFloatToConvert = ArgAPFloat;
9535 bool LosesInfo =
true;
9540 ArgAPFloat = APFloatToConvert;
9562 APFloat APFloatToConvert = ArgAPFloat;
9563 bool LosesInfo =
true;
9567 return (!LosesInfo && !APFloatToConvert.
isDenormal());
9576 EVT Ty =
Op->getValueType(0);
9579 if ((Ty == MVT::v2f64 || Ty == MVT::v4f32 || Ty == MVT::v4i32) &&
9588 if ((Ty == MVT::v8i16 || Ty == MVT::v16i8) &&
ISD::isEXTLoad(InputNode) &&
9592 if (Ty == MVT::v2i64) {
9595 if (MemVT == MVT::i32) {
9597 Opcode = PPCISD::ZEXT_LD_SPLAT;
9599 Opcode = PPCISD::SEXT_LD_SPLAT;
9607 bool IsLittleEndian) {
9613 APInt ConstValue(VTSize, 0);
9617 unsigned BitPos = 0;
9625 ConstValue.
insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth),
9626 IsLittleEndian ? BitPos : VTSize - EltWidth - BitPos);
9630 for (
unsigned J = 0; J < 16; ++J) {
9632 if (ExtractValue != 0x00 && ExtractValue != 0xFF)
9634 if (ExtractValue == 0xFF)
9649 assert(BVN &&
"Expected a BuildVectorSDNode in LowerBUILD_VECTOR");
9651 if (Subtarget.hasP10Vector()) {
9652 APInt BitMask(32, 0);
9658 BitMask != 0 && BitMask != 0xffff) {
9660 MachineSDNode *MSDNode =
9672 if (
SDValue VecPat = combineBVLoadsSpecialValue(
Op, DAG))
9676 APInt APSplatBits, APSplatUndef;
9677 unsigned SplatBitSize = 0;
9679 bool BVNIsConstantSplat =
9681 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
9687 if (BVNIsConstantSplat && (SplatBitSize == 64) &&
9688 Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
9691 if ((
Op->getValueType(0) == MVT::v2f64) &&
9694 PPCISD::XXSPLTI_SP_TO_DP, dl, MVT::v2f64,
9710 PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9716 DAG.
getNode(PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9725 LowerVecSplatSmallFP(
Op, DAG, BVNIsConstantSplat, SplatBitSize))
9728 bool IsSplat64 =
false;
9729 uint64_t SplatBits = 0;
9730 int32_t SextVal = 0;
9731 if (BVNIsConstantSplat && SplatBitSize <= 64) {
9733 if (SplatBitSize <= 32) {
9735 }
else if (SplatBitSize == 64 && Subtarget.hasP8Altivec()) {
9736 int64_t Splat64Val =
static_cast<int64_t
>(SplatBits);
9737 bool P9Vector = Subtarget.hasP9Vector();
9738 int32_t
Hi = P9Vector ? 127 : 15;
9739 int32_t
Lo = P9Vector ? -128 : -16;
9740 IsSplat64 = Splat64Val >=
Lo && Splat64Val <=
Hi;
9741 SextVal =
static_cast<int32_t
>(SplatBits);
9745 if (!BVNIsConstantSplat || (SplatBitSize > 32 && !IsSplat64)) {
9746 unsigned NewOpcode = PPCISD::LD_SPLAT;
9752 const SDValue *InputLoad = &
Op.getOperand(0);
9757 unsigned MemorySize =
LD->getMemoryVT().getScalarSizeInBits();
9758 unsigned ElementSize =
9759 MemorySize * ((NewOpcode == PPCISD::LD_SPLAT) ? 1 : 2);
9761 assert(((ElementSize == 2 * MemorySize)
9762 ? (NewOpcode == PPCISD::ZEXT_LD_SPLAT ||
9763 NewOpcode == PPCISD::SEXT_LD_SPLAT)
9764 : (NewOpcode == PPCISD::LD_SPLAT)) &&
9765 "Unmatched element size and opcode!\n");
9770 unsigned NumUsesOfInputLD = 128 / ElementSize;
9772 if (BVInOp.isUndef())
9787 if (NumUsesOfInputLD == 1 &&
9788 (
Op->getValueType(0) == MVT::v2i64 && NewOpcode != PPCISD::LD_SPLAT &&
9789 !Subtarget.isLittleEndian() && Subtarget.hasVSX() &&
9790 Subtarget.hasLFIWAX()))
9798 if (NumUsesOfInputLD == 1 && Subtarget.isLittleEndian() &&
9799 Subtarget.isISA3_1() && ElementSize <= 16)
9802 assert(NumUsesOfInputLD > 0 &&
"No uses of input LD of a build_vector?");
9804 Subtarget.hasVSX()) {
9811 NewOpcode, dl, DAG.
getVTList(
Op.getValueType(), MVT::Other),
Ops,
9812 LD->getMemoryVT(),
LD->getMemOperand());
9824 if (Subtarget.hasVSX() && Subtarget.isPPC64() &&
9826 Subtarget.hasP8Vector()))
9832 unsigned SplatSize = SplatBitSize / 8;
9837 if (SplatBits == 0) {
9839 if (
Op.getValueType() != MVT::v4i32 || HasAnyUndefs) {
9851 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 2)
9853 Op.getValueType(), DAG, dl);
9855 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 4)
9860 if (Subtarget.hasP9Vector() && SplatSize == 1)
9866 if (SextVal >= -16 && SextVal <= 15) {
9869 unsigned UseSize = SplatSize == 8 ? 4 : SplatSize;
9876 DAG.
getBitcast(MVT::v4i32, Res), DAG, dl, MVT::v2i64);
9882 if (Subtarget.hasP9Vector() && SextVal >= -128 && SextVal <= 127) {
9888 switch (SplatSize) {
9892 IID = Intrinsic::ppc_altivec_vupklsb;
9896 IID = Intrinsic::ppc_altivec_vextsb2w;
9900 IID = Intrinsic::ppc_altivec_vextsb2d;
9907 assert(!IsSplat64 &&
"Unhandled 64-bit splat pattern");
9916 if (SextVal >= -32 && SextVal <= 31) {
9921 EVT VT = (SplatSize == 1 ? MVT::v16i8 :
9922 (SplatSize == 2 ? MVT::v8i16 : MVT::v4i32));
9925 if (VT ==
Op.getValueType())
9934 if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) {
9948 static const signed char SplatCsts[] = {
9949 -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
9950 -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
9953 for (
unsigned idx = 0; idx < std::size(SplatCsts); ++idx) {
9956 int i = SplatCsts[idx];
9960 unsigned TypeShiftAmt = i & (SplatBitSize-1);
9963 if (SextVal == (
int)((
unsigned)i << TypeShiftAmt)) {
9965 static const unsigned IIDs[] = {
9966 Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
9967 Intrinsic::ppc_altivec_vslw
9974 if (SextVal == (
int)((
unsigned)i >> TypeShiftAmt)) {
9976 static const unsigned IIDs[] = {
9977 Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
9978 Intrinsic::ppc_altivec_vsrw
9985 if (SextVal == (
int)(((
unsigned)i << TypeShiftAmt) |
9986 ((
unsigned)i >> (SplatBitSize-TypeShiftAmt)))) {
9988 static const unsigned IIDs[] = {
9989 Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0,
9990 Intrinsic::ppc_altivec_vrlw
9997 if (SextVal == (
int)(((
unsigned)i << 8) | (i < 0 ? 0xFF : 0))) {
9999 unsigned Amt = Subtarget.isLittleEndian() ? 15 : 1;
10003 if (SextVal == (
int)(((
unsigned)i << 16) | (i < 0 ? 0xFFFF : 0))) {
10005 unsigned Amt = Subtarget.isLittleEndian() ? 14 : 2;
10009 if (SextVal == (
int)(((
unsigned)i << 24) | (i < 0 ? 0xFFFFFF : 0))) {
10011 unsigned Amt = Subtarget.isLittleEndian() ? 13 : 3;
10024 unsigned OpNum = (PFEntry >> 26) & 0x0F;
10025 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
10026 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
10042 if (LHSID == (1*9+2)*9+3)
return LHS;
10043 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
10055 ShufIdxs[ 0] = 0; ShufIdxs[ 1] = 1; ShufIdxs[ 2] = 2; ShufIdxs[ 3] = 3;
10056 ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19;
10057 ShufIdxs[ 8] = 4; ShufIdxs[ 9] = 5; ShufIdxs[10] = 6; ShufIdxs[11] = 7;
10058 ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23;
10061 ShufIdxs[ 0] = 8; ShufIdxs[ 1] = 9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11;
10062 ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27;
10063 ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15;
10064 ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31;
10067 for (
unsigned i = 0; i != 16; ++i)
10068 ShufIdxs[i] = (i&3)+0;
10071 for (
unsigned i = 0; i != 16; ++i)
10072 ShufIdxs[i] = (i&3)+4;
10075 for (
unsigned i = 0; i != 16; ++i)
10076 ShufIdxs[i] = (i&3)+8;
10079 for (
unsigned i = 0; i != 16; ++i)
10080 ShufIdxs[i] = (i&3)+12;
10101 const unsigned BytesInVector = 16;
10102 bool IsLE = Subtarget.isLittleEndian();
10106 unsigned ShiftElts = 0, InsertAtByte = 0;
10110 unsigned LittleEndianShifts[] = {8, 7, 6, 5, 4, 3, 2, 1,
10111 0, 15, 14, 13, 12, 11, 10, 9};
10112 unsigned BigEndianShifts[] = {9, 10, 11, 12, 13, 14, 15, 0,
10113 1, 2, 3, 4, 5, 6, 7, 8};
10115 ArrayRef<int>
Mask =
N->getMask();
10116 int OriginalOrder[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
10128 bool FoundCandidate =
false;
10132 unsigned VINSERTBSrcElem = IsLE ? 8 : 7;
10135 for (
unsigned i = 0; i < BytesInVector; ++i) {
10136 unsigned CurrentElement =
Mask[i];
10139 if (V2.
isUndef() && CurrentElement != VINSERTBSrcElem)
10142 bool OtherElementsInOrder =
true;
10145 for (
unsigned j = 0;
j < BytesInVector; ++
j) {
10152 (!V2.
isUndef() && CurrentElement < BytesInVector) ? BytesInVector : 0;
10153 if (Mask[j] != OriginalOrder[j] + MaskOffset) {
10154 OtherElementsInOrder =
false;
10161 if (OtherElementsInOrder) {
10168 ShiftElts = IsLE ? LittleEndianShifts[CurrentElement & 0xF]
10169 : BigEndianShifts[CurrentElement & 0xF];
10170 Swap = CurrentElement < BytesInVector;
10172 InsertAtByte = IsLE ? BytesInVector - (i + 1) : i;
10173 FoundCandidate =
true;
10178 if (!FoundCandidate)
10188 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10190 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8,
V1, Shl,
10193 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8,
V1, V2,
10202 const unsigned NumHalfWords = 8;
10203 const unsigned BytesInVector = NumHalfWords * 2;
10208 bool IsLE = Subtarget.isLittleEndian();
10212 unsigned ShiftElts = 0, InsertAtByte = 0;
10216 unsigned LittleEndianShifts[] = {4, 3, 2, 1, 0, 7, 6, 5};
10217 unsigned BigEndianShifts[] = {5, 6, 7, 0, 1, 2, 3, 4};
10220 uint32_t OriginalOrderLow = 0x1234567;
10221 uint32_t OriginalOrderHigh = 0x89ABCDEF;
10224 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10225 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10242 bool FoundCandidate =
false;
10245 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10246 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10248 uint32_t MaskOtherElts = ~(0xF <<
MaskShift);
10249 uint32_t TargetOrder = 0x0;
10256 unsigned VINSERTHSrcElem = IsLE ? 4 : 3;
10257 TargetOrder = OriginalOrderLow;
10261 if (MaskOneElt == VINSERTHSrcElem &&
10262 (Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10263 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10264 FoundCandidate =
true;
10270 (MaskOneElt < NumHalfWords) ? OriginalOrderHigh : OriginalOrderLow;
10272 if ((Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10274 ShiftElts = IsLE ? LittleEndianShifts[MaskOneElt & 0x7]
10275 : BigEndianShifts[MaskOneElt & 0x7];
10276 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10277 Swap = MaskOneElt < NumHalfWords;
10278 FoundCandidate =
true;
10284 if (!FoundCandidate)
10296 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10299 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10304 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10319 auto ShuffleMask = SVN->
getMask();
10334 ShuffleMask = CommutedSV->
getMask();
10343 APInt APSplatValue, APSplatUndef;
10344 unsigned SplatBitSize;
10347 HasAnyUndefs, 0, !Subtarget.isLittleEndian()) ||
10359 bool IsLE = Subtarget.isLittleEndian();
10360 if ((ShuffleMask[0] == 0 && ShuffleMask[8] == 8) &&
10361 (ShuffleMask[4] % 4 == 0 && ShuffleMask[12] % 4 == 0 &&
10362 ShuffleMask[4] > 15 && ShuffleMask[12] > 15))
10364 else if ((ShuffleMask[4] == 4 && ShuffleMask[12] == 12) &&
10365 (ShuffleMask[0] % 4 == 0 && ShuffleMask[8] % 4 == 0 &&
10366 ShuffleMask[0] > 15 && ShuffleMask[8] > 15))
10374 for (; SplatBitSize < 32; SplatBitSize <<= 1)
10375 SplatVal |= (SplatVal << SplatBitSize);
10378 PPCISD::XXSPLTI32DX,
DL, MVT::v2i64, DAG.
getBitcast(MVT::v2i64,
LHS),
10389 assert(
Op.getValueType() == MVT::v1i128 &&
10390 "Only set v1i128 as custom, other type shouldn't reach here!");
10395 if (SHLAmt % 8 == 0) {
10396 std::array<int, 16>
Mask;
10397 std::iota(
Mask.begin(),
Mask.end(), 0);
10398 std::rotate(
Mask.begin(),
Mask.begin() + SHLAmt / 8,
Mask.end());
10427 if (
SDValue NewShuffle = combineVectorShuffle(SVOp, DAG)) {
10432 V1 =
Op.getOperand(0);
10433 V2 =
Op.getOperand(1);
10435 EVT VT =
Op.getValueType();
10436 bool isLittleEndian = Subtarget.isLittleEndian();
10438 unsigned ShiftElts, InsertAtByte;
10444 bool IsPermutedLoad =
false;
10446 if (InputLoad && Subtarget.hasVSX() && V2.
isUndef() &&
10456 if (IsPermutedLoad) {
10457 assert((isLittleEndian || IsFourByte) &&
10458 "Unexpected size for permuted load on big endian target");
10459 SplatIdx += IsFourByte ? 2 : 1;
10460 assert((SplatIdx < (IsFourByte ? 4 : 2)) &&
10461 "Splat of a value outside of the loaded memory");
10466 if ((IsFourByte && Subtarget.hasP9Vector()) || !IsFourByte) {
10469 Offset = isLittleEndian ? (3 - SplatIdx) * 4 : SplatIdx * 4;
10471 Offset = isLittleEndian ? (1 - SplatIdx) * 8 : SplatIdx * 8;
10475 if (
LD->getValueType(0).getSizeInBits() == (IsFourByte ? 32 : 64))
10488 DAG.
getVTList(IsFourByte ? MVT::v4i32 : MVT::v2i64, MVT::Other);
10491 Ops,
LD->getMemoryVT(),
LD->getMemOperand());
10500 if (VT == MVT::v2i64 || VT == MVT::v2f64)
10503 if (Subtarget.hasP9Vector() &&
10513 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv2, Conv2,
10515 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Shl,
10519 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Conv2,
10524 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
10526 if ((SplatInsertNode = lowerToXXSPLTI32DX(SVOp, DAG)))
10527 return SplatInsertNode;
10530 if (Subtarget.hasP9Altivec()) {
10532 if ((NewISDNode = lowerToVINSERTH(SVOp, DAG)))
10535 if ((NewISDNode = lowerToVINSERTB(SVOp, DAG)))
10539 if (Subtarget.hasVSX() &&
10547 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv1, Conv2,
10552 if (Subtarget.hasVSX() &&
10560 SDValue PermDI = DAG.
getNode(PPCISD::XXPERMDI, dl, MVT::v2i64, Conv1, Conv2,
10565 if (Subtarget.hasP9Vector()) {
10585 if (Subtarget.hasVSX()) {
10598 SDValue Swap = DAG.
getNode(PPCISD::SWAP_NO_CHAIN, dl, MVT::v2f64, Conv);
10606 if (V2.isUndef()) {
10619 (Subtarget.hasP8Altivec() && (
10630 unsigned int ShuffleKind = isLittleEndian ? 2 : 0;
10640 (Subtarget.hasP8Altivec() && (
10648 ArrayRef<int> PermMask = SVOp->
getMask();
10651 unsigned PFIndexes[4];
10652 bool isFourElementShuffle =
true;
10653 for (
unsigned i = 0; i != 4 && isFourElementShuffle;
10655 unsigned EltNo = 8;
10656 for (
unsigned j = 0;
j != 4; ++
j) {
10657 if (PermMask[i * 4 + j] < 0)
10660 unsigned ByteSource = PermMask[i * 4 +
j];
10661 if ((ByteSource & 3) != j) {
10662 isFourElementShuffle =
false;
10667 EltNo = ByteSource / 4;
10668 }
else if (EltNo != ByteSource / 4) {
10669 isFourElementShuffle =
false;
10673 PFIndexes[i] = EltNo;
10681 if (isFourElementShuffle) {
10683 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
10684 PFIndexes[2] * 9 + PFIndexes[3];
10687 unsigned Cost = (PFEntry >> 30);
10707 if (V2.isUndef()) V2 =
V1;
10709 return LowerVPERM(
Op, DAG, PermMask, VT,
V1, V2);
10715 unsigned Opcode = PPCISD::VPERM;
10718 bool NeedSwap =
false;
10719 bool isLittleEndian = Subtarget.isLittleEndian();
10720 bool isPPC64 = Subtarget.isPPC64();
10722 if (Subtarget.hasVSX() && Subtarget.hasP9Vector() &&
10724 LLVM_DEBUG(
dbgs() <<
"At least one of two input vectors are dead - using "
10725 "XXPERM instead\n");
10726 Opcode = PPCISD::XXPERM;
10731 if ((!isLittleEndian && !V2->
hasOneUse() &&
V1->hasOneUse()) ||
10732 (isLittleEndian && !
V1->hasOneUse() && V2->
hasOneUse())) {
10734 NeedSwap = !NeedSwap;
10748 bool V1HasXXSWAPD =
V1->getOperand(0)->getOpcode() == PPCISD::XXSWAPD;
10769 unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i];
10771 if (V1HasXXSWAPD) {
10774 else if (SrcElt < 16)
10777 if (V2HasXXSWAPD) {
10780 else if (SrcElt > 15)
10789 for (
unsigned j = 0;
j != BytesPerElement; ++
j)
10790 if (isLittleEndian)
10792 DAG.
getConstant(31 - (SrcElt * BytesPerElement + j), dl, MVT::i32));
10795 DAG.
getConstant(SrcElt * BytesPerElement + j, dl, MVT::i32));
10798 if (V1HasXXSWAPD) {
10799 dl = SDLoc(
V1->getOperand(0));
10800 V1 =
V1->getOperand(0)->getOperand(1);
10802 if (V2HasXXSWAPD) {
10807 if (isPPC64 && (V1HasXXSWAPD || V2HasXXSWAPD)) {
10808 if (ValType != MVT::v2f64)
10814 ShufflesHandledWithVPERM++;
10818 if (Opcode == PPCISD::XXPERM) {
10819 dbgs() <<
"Emitting a XXPERM for the following shuffle:\n";
10821 dbgs() <<
"Emitting a VPERM for the following shuffle:\n";
10824 dbgs() <<
"With the following permute control vector:\n";
10828 if (Opcode == PPCISD::XXPERM)
10829 VPermMask = DAG.
getBitcast(MVT::v4i32, VPermMask);
10833 if (isLittleEndian)
10837 DAG.
getNode(Opcode, dl,
V1.getValueType(),
V1, V2, VPermMask);
10839 VPERMNode = DAG.
getBitcast(ValType, VPERMNode);
10851 switch (IntrinsicID) {
10855 case Intrinsic::ppc_altivec_vcmpbfp_p:
10859 case Intrinsic::ppc_altivec_vcmpeqfp_p:
10863 case Intrinsic::ppc_altivec_vcmpequb_p:
10867 case Intrinsic::ppc_altivec_vcmpequh_p:
10871 case Intrinsic::ppc_altivec_vcmpequw_p:
10875 case Intrinsic::ppc_altivec_vcmpequd_p:
10876 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10882 case Intrinsic::ppc_altivec_vcmpneb_p:
10883 case Intrinsic::ppc_altivec_vcmpneh_p:
10884 case Intrinsic::ppc_altivec_vcmpnew_p:
10885 case Intrinsic::ppc_altivec_vcmpnezb_p:
10886 case Intrinsic::ppc_altivec_vcmpnezh_p:
10887 case Intrinsic::ppc_altivec_vcmpnezw_p:
10888 if (Subtarget.hasP9Altivec()) {
10889 switch (IntrinsicID) {
10892 case Intrinsic::ppc_altivec_vcmpneb_p:
10895 case Intrinsic::ppc_altivec_vcmpneh_p:
10898 case Intrinsic::ppc_altivec_vcmpnew_p:
10901 case Intrinsic::ppc_altivec_vcmpnezb_p:
10904 case Intrinsic::ppc_altivec_vcmpnezh_p:
10907 case Intrinsic::ppc_altivec_vcmpnezw_p:
10915 case Intrinsic::ppc_altivec_vcmpgefp_p:
10919 case Intrinsic::ppc_altivec_vcmpgtfp_p:
10923 case Intrinsic::ppc_altivec_vcmpgtsb_p:
10927 case Intrinsic::ppc_altivec_vcmpgtsh_p:
10931 case Intrinsic::ppc_altivec_vcmpgtsw_p:
10935 case Intrinsic::ppc_altivec_vcmpgtsd_p:
10936 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10942 case Intrinsic::ppc_altivec_vcmpgtub_p:
10946 case Intrinsic::ppc_altivec_vcmpgtuh_p:
10950 case Intrinsic::ppc_altivec_vcmpgtuw_p:
10954 case Intrinsic::ppc_altivec_vcmpgtud_p:
10955 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10962 case Intrinsic::ppc_altivec_vcmpequq:
10963 case Intrinsic::ppc_altivec_vcmpgtsq:
10964 case Intrinsic::ppc_altivec_vcmpgtuq:
10965 if (!Subtarget.isISA3_1())
10967 switch (IntrinsicID) {
10970 case Intrinsic::ppc_altivec_vcmpequq:
10973 case Intrinsic::ppc_altivec_vcmpgtsq:
10976 case Intrinsic::ppc_altivec_vcmpgtuq:
10983 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10984 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10985 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
10986 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
10987 case Intrinsic::ppc_vsx_xvcmpgesp_p:
10988 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
10989 if (Subtarget.hasVSX()) {
10990 switch (IntrinsicID) {
10991 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10994 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10997 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
11000 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
11003 case Intrinsic::ppc_vsx_xvcmpgesp_p:
11006 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
11016 case Intrinsic::ppc_altivec_vcmpbfp:
11019 case Intrinsic::ppc_altivec_vcmpeqfp:
11022 case Intrinsic::ppc_altivec_vcmpequb:
11025 case Intrinsic::ppc_altivec_vcmpequh:
11028 case Intrinsic::ppc_altivec_vcmpequw:
11031 case Intrinsic::ppc_altivec_vcmpequd:
11032 if (Subtarget.hasP8Altivec())
11037 case Intrinsic::ppc_altivec_vcmpneb:
11038 case Intrinsic::ppc_altivec_vcmpneh:
11039 case Intrinsic::ppc_altivec_vcmpnew:
11040 case Intrinsic::ppc_altivec_vcmpnezb:
11041 case Intrinsic::ppc_altivec_vcmpnezh:
11042 case Intrinsic::ppc_altivec_vcmpnezw:
11043 if (Subtarget.hasP9Altivec())
11044 switch (IntrinsicID) {
11047 case Intrinsic::ppc_altivec_vcmpneb:
11050 case Intrinsic::ppc_altivec_vcmpneh:
11053 case Intrinsic::ppc_altivec_vcmpnew:
11056 case Intrinsic::ppc_altivec_vcmpnezb:
11059 case Intrinsic::ppc_altivec_vcmpnezh:
11062 case Intrinsic::ppc_altivec_vcmpnezw:
11069 case Intrinsic::ppc_altivec_vcmpgefp:
11072 case Intrinsic::ppc_altivec_vcmpgtfp:
11075 case Intrinsic::ppc_altivec_vcmpgtsb:
11078 case Intrinsic::ppc_altivec_vcmpgtsh:
11081 case Intrinsic::ppc_altivec_vcmpgtsw:
11084 case Intrinsic::ppc_altivec_vcmpgtsd:
11085 if (Subtarget.hasP8Altivec())
11090 case Intrinsic::ppc_altivec_vcmpgtub:
11093 case Intrinsic::ppc_altivec_vcmpgtuh:
11096 case Intrinsic::ppc_altivec_vcmpgtuw:
11099 case Intrinsic::ppc_altivec_vcmpgtud:
11100 if (Subtarget.hasP8Altivec())
11105 case Intrinsic::ppc_altivec_vcmpequq_p:
11106 case Intrinsic::ppc_altivec_vcmpgtsq_p:
11107 case Intrinsic::ppc_altivec_vcmpgtuq_p:
11108 if (!Subtarget.isISA3_1())
11110 switch (IntrinsicID) {
11113 case Intrinsic::ppc_altivec_vcmpequq_p:
11116 case Intrinsic::ppc_altivec_vcmpgtsq_p:
11119 case Intrinsic::ppc_altivec_vcmpgtuq_p:
11133 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11139 auto MapNodeWithSplatVector =
11140 [&](
unsigned Opcode,
11141 std::initializer_list<SDValue> ExtraOps = {}) ->
SDValue {
11146 Ops.append(ExtraOps.begin(), ExtraOps.end());
11147 return DAG.
getNode(Opcode, dl, MVT::v16i8,
Ops);
11150 switch (IntrinsicID) {
11151 case Intrinsic::thread_pointer:
11153 if (Subtarget.isPPC64())
11157 case Intrinsic::ppc_rldimi: {
11158 assert(Subtarget.isPPC64() &&
"rldimi is only available in 64-bit!");
11160 APInt
Mask =
Op.getConstantOperandAPInt(4);
11162 return Op.getOperand(2);
11163 if (
Mask.isAllOnes())
11165 uint64_t SH =
Op.getConstantOperandVal(3);
11166 unsigned MB = 0, ME = 0;
11170 if (ME < 63 - SH) {
11173 }
else if (ME > 63 - SH) {
11179 {Op.getOperand(2), Src,
11180 DAG.getTargetConstant(63 - ME, dl, MVT::i32),
11181 DAG.getTargetConstant(MB, dl, MVT::i32)}),
11185 case Intrinsic::ppc_rlwimi: {
11186 APInt
Mask =
Op.getConstantOperandAPInt(4);
11188 return Op.getOperand(2);
11189 if (
Mask.isAllOnes())
11192 unsigned MB = 0, ME = 0;
11196 PPC::RLWIMI, dl, MVT::i32,
11197 {Op.getOperand(2), Op.getOperand(1), Op.getOperand(3),
11198 DAG.getTargetConstant(MB, dl, MVT::i32),
11199 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11203 case Intrinsic::ppc_bcdshift:
11204 return MapNodeWithSplatVector(PPCISD::BCDSHIFT, {
Op.getOperand(3)});
11205 case Intrinsic::ppc_bcdshiftround:
11206 return MapNodeWithSplatVector(PPCISD::BCDSHIFTROUND, {
Op.getOperand(3)});
11207 case Intrinsic::ppc_bcdtruncate:
11208 return MapNodeWithSplatVector(PPCISD::BCDTRUNC, {
Op.getOperand(3)});
11209 case Intrinsic::ppc_bcdunsignedtruncate:
11210 return MapNodeWithSplatVector(PPCISD::BCDUTRUNC);
11211 case Intrinsic::ppc_bcdunsignedshift:
11212 return MapNodeWithSplatVector(PPCISD::BCDUSHIFT);
11214 case Intrinsic::ppc_rlwnm: {
11215 if (
Op.getConstantOperandVal(3) == 0)
11217 unsigned MB = 0, ME = 0;
11222 {Op.getOperand(1), Op.getOperand(2),
11223 DAG.getTargetConstant(MB, dl, MVT::i32),
11224 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11228 case Intrinsic::ppc_mma_disassemble_acc: {
11229 if (Subtarget.isISAFuture()) {
11230 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11241 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11242 Subtarget.isLittleEndian() ? Value2 :
Value,
11243 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11247 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11248 Subtarget.isLittleEndian() ? Value2 :
Value,
11249 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11253 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11254 Subtarget.isLittleEndian() ?
Value : Value2,
11255 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11259 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11260 Subtarget.isLittleEndian() ?
Value : Value2,
11261 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11268 case Intrinsic::ppc_vsx_disassemble_pair: {
11271 if (IntrinsicID == Intrinsic::ppc_mma_disassemble_acc) {
11273 WideVec = DAG.
getNode(PPCISD::XXMFACC, dl, MVT::v512i1, WideVec);
11276 for (
int VecNo = 0; VecNo < NumVecs; VecNo++) {
11278 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8, WideVec,
11279 DAG.
getConstant(Subtarget.isLittleEndian() ? NumVecs - 1 - VecNo
11287 case Intrinsic::ppc_build_dmr: {
11290 for (
int i = 1; i < 9; i += 2) {
11298 DAG.
getNode(PPCISD::PAIR_BUILD, dl, MVT::v256i1, {Hi, Lo}));
11305 case Intrinsic::ppc_mma_dmxxextfdmr512: {
11306 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr512 requires ISA Future");
11308 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11309 "Specify P of 0 or 1 for lower or upper 512 bytes");
11310 unsigned HiLo = Idx->getSExtValue();
11314 Opcode = PPC::DMXXEXTFDMR512;
11315 Subx = PPC::sub_wacc_lo;
11317 Opcode = PPC::DMXXEXTFDMR512_HI;
11318 Subx = PPC::sub_wacc_hi;
11321 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
11325 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11329 case Intrinsic::ppc_mma_dmxxextfdmr256: {
11330 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr256 requires ISA Future");
11332 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11333 "Specify a dmr row pair 0-3");
11334 unsigned IdxVal = Idx->getSExtValue();
11338 Subx = PPC::sub_dmrrowp0;
11341 Subx = PPC::sub_dmrrowp1;
11344 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11347 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11351 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v256i1,
11357 DAG.
getMachineNode(PPC::DMXXEXTFDMR256, dl, MVT::v256i1, {Subreg, P}),
11361 case Intrinsic::ppc_mma_dmxxinstdmr512: {
11362 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr512 requires ISA Future");
11364 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11365 "Specify P of 0 or 1 for lower or upper 512 bytes");
11366 unsigned HiLo = Idx->getSExtValue();
11370 Opcode = PPCISD::INST512;
11371 Subx = PPC::sub_wacc_lo;
11373 Opcode = PPCISD::INST512HI;
11374 Subx = PPC::sub_wacc_hi;
11380 Op.getOperand(1), Wacc, SubReg),
11384 case Intrinsic::ppc_mma_dmxxinstdmr256: {
11385 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr256 requires ISA Future");
11387 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11388 "Specify a dmr row pair 0-3");
11389 unsigned IdxVal = Idx->getSExtValue();
11393 Subx = PPC::sub_dmrrowp0;
11396 Subx = PPC::sub_dmrrowp1;
11399 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11402 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11408 DAG.
getNode(PPCISD::INST256, dl, MVT::v256i1,
Op.getOperand(2),
P);
11410 Op.getOperand(1), DMRRowp, SubReg),
11414 case Intrinsic::ppc_mma_xxmfacc:
11415 case Intrinsic::ppc_mma_xxmtacc: {
11417 if (!Subtarget.isISAFuture())
11428 case Intrinsic::ppc_unpack_longdouble: {
11430 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11431 "Argument of long double unpack must be 0 or 1!");
11434 Idx->getValueType(0)));
11437 case Intrinsic::ppc_compare_exp_lt:
11438 case Intrinsic::ppc_compare_exp_gt:
11439 case Intrinsic::ppc_compare_exp_eq:
11440 case Intrinsic::ppc_compare_exp_uo: {
11442 switch (IntrinsicID) {
11443 case Intrinsic::ppc_compare_exp_lt:
11446 case Intrinsic::ppc_compare_exp_gt:
11449 case Intrinsic::ppc_compare_exp_eq:
11452 case Intrinsic::ppc_compare_exp_uo:
11458 PPC::SELECT_CC_I4, dl, MVT::i32,
11459 {SDValue(DAG.getMachineNode(PPC::XSCMPEXPDP, dl, MVT::i32,
11460 Op.getOperand(1), Op.getOperand(2)),
11462 DAG.getConstant(1, dl, MVT::i32), DAG.getConstant(0, dl, MVT::i32),
11463 DAG.getTargetConstant(Pred, dl, MVT::i32)}),
11466 case Intrinsic::ppc_test_data_class: {
11467 EVT OpVT =
Op.getOperand(1).getValueType();
11468 unsigned CmprOpc = OpVT == MVT::f128 ? PPC::XSTSTDCQP
11469 : (OpVT == MVT::f64 ? PPC::XSTSTDCDP
11482 {Op.getOperand(2), Op.getOperand(1)}),
11484 if (Subtarget.isISA3_1()) {
11491 TestDataClass, SubRegIdx),
11494 return DAG.
getNode(PPCISD::SETBC, dl, MVT::i32, CRBit);
11500 {TestDataClass, DAG.getConstant(1, dl, MVT::i32),
11501 DAG.getConstant(0, dl, MVT::i32),
11502 DAG.getTargetConstant(PPC::PRED_EQ, dl, MVT::i32)}),
11505 case Intrinsic::ppc_fnmsub: {
11506 EVT VT =
Op.getOperand(1).getValueType();
11507 if (!Subtarget.hasVSX() || (!Subtarget.hasFloat128() && VT == MVT::f128))
11512 return DAG.
getNode(PPCISD::FNMSUB, dl, VT,
Op.getOperand(1),
11513 Op.getOperand(2),
Op.getOperand(3));
11515 case Intrinsic::ppc_convert_f128_to_ppcf128:
11516 case Intrinsic::ppc_convert_ppcf128_to_f128: {
11517 RTLIB::Libcall LC = IntrinsicID == Intrinsic::ppc_convert_ppcf128_to_f128
11518 ? RTLIB::CONVERT_PPCF128_F128
11519 : RTLIB::CONVERT_F128_PPCF128;
11521 std::pair<SDValue, SDValue>
Result =
11522 makeLibCall(DAG, LC,
Op.getValueType(),
Op.getOperand(1), CallOptions,
11526 case Intrinsic::ppc_maxfe:
11527 case Intrinsic::ppc_maxfl:
11528 case Intrinsic::ppc_maxfs:
11529 case Intrinsic::ppc_minfe:
11530 case Intrinsic::ppc_minfl:
11531 case Intrinsic::ppc_minfs: {
11532 EVT VT =
Op.getValueType();
11535 [VT](
const SDUse &Use) { return Use.getValueType() == VT; }) &&
11536 "ppc_[max|min]f[e|l|s] must have uniform type arguments");
11539 if (IntrinsicID == Intrinsic::ppc_minfe ||
11540 IntrinsicID == Intrinsic::ppc_minfl ||
11541 IntrinsicID == Intrinsic::ppc_minfs)
11562 SDValue Tmp = DAG.
getNode(PPCISD::VCMP, dl,
Op.getOperand(2).getValueType(),
11563 Op.getOperand(1),
Op.getOperand(2),
11574 EVT VTs[] = {
Op.getOperand(2).getValueType(), MVT::Glue };
11582 switch (
Op.getConstantOperandVal(1)) {
11587 Bitx = PPC::sub_eq;
11588 SetOp = PPCISD::SETBC;
11593 Bitx = PPC::sub_eq;
11594 SetOp = PPCISD::SETBCR;
11599 Bitx = PPC::sub_lt;
11600 SetOp = PPCISD::SETBC;
11605 Bitx = PPC::sub_lt;
11606 SetOp = PPCISD::SETBCR;
11611 if (Subtarget.isISA3_1()) {
11616 CR6Reg, SubRegIdx, GlueOp),
11618 return DAG.
getNode(SetOp, dl, MVT::i32, CRBit);
11646 switch (
Op.getConstantOperandVal(ArgStart)) {
11647 case Intrinsic::ppc_cfence: {
11648 assert(ArgStart == 1 &&
"llvm.ppc.cfence must carry a chain argument.");
11649 SDValue Val =
Op.getOperand(ArgStart + 1);
11651 if (Ty == MVT::i128) {
11656 unsigned Opcode = Subtarget.isPPC64() ? PPC::CFENCE8 : PPC::CFENCE;
11659 Opcode,
DL, MVT::Other,
11664 case Intrinsic::ppc_disassemble_dmr: {
11666 "llvm.ppc.disassemble.dmr must carry a chain argument.");
11667 return DAG.
getStore(
Op.getOperand(0),
DL,
Op.getOperand(ArgStart + 2),
11668 Op.getOperand(ArgStart + 1), MachinePointerInfo());
11679 if (!Subtarget.isPPC64())
11682 if (Subtarget.hasP9Vector()) {
11689 int VectorIndex = 0;
11690 if (Subtarget.isLittleEndian())
11700 auto CreateRotateInsert =
11701 [&](
unsigned Opcode, MVT VT,
SDValue Dest,
SDValue Src,
unsigned RotAmt,
11702 unsigned MaskBegin,
11703 std::optional<unsigned> MaskEnd = std::nullopt) ->
SDValue {
11707 if (MaskEnd.has_value())
11719 CreateRotateInsert(PPC::RLWIMI, MVT::i32, Rot, Val32, 24, 0, 7);
11721 return CreateRotateInsert(PPC::RLWIMI, MVT::i32, Swap, Val32, 24, 16, 23);
11734 return CreateRotateInsert(PPC::RLDIMI, MVT::i64, HiSwap, LoSwap, 32, 0);
11742 "Expecting an atomic compare-and-swap here.");
11745 EVT MemVT = AtomicNode->getMemoryVT();
11763 for (
int i = 0, e = AtomicNode->getNumOperands(); i < e; i++)
11764 Ops.push_back(AtomicNode->getOperand(i));
11766 MachineMemOperand *MMO = AtomicNode->getMemOperand();
11767 SDVTList Tys = DAG.
getVTList(MVT::i32, MVT::Other);
11769 (MemVT == MVT::i8) ? PPCISD::ATOMIC_CMP_SWAP_8 : PPCISD::ATOMIC_CMP_SWAP_16;
11776 EVT MemVT =
N->getMemoryVT();
11778 "Expect quadword atomic operations");
11780 unsigned Opc =
N->getOpcode();
11785 SDVTList Tys = DAG.
getVTList(MVT::i64, MVT::i64, MVT::Other);
11788 DAG.
getConstant(Intrinsic::ppc_atomic_load_i128, dl, MVT::i32)};
11789 for (
int I = 1,
E =
N->getNumOperands();
I <
E; ++
I)
11790 Ops.push_back(
N->getOperand(
I));
11792 Ops, MemVT,
N->getMemOperand());
11799 DAG.
getNode(
ISD::OR, dl, {MVT::i128, MVT::Other}, {ValLo, ValHi});
11806 SDVTList Tys = DAG.
getVTList(MVT::Other);
11809 DAG.
getConstant(Intrinsic::ppc_atomic_store_i128, dl, MVT::i32)};
11815 Ops.push_back(ValLo);
11816 Ops.push_back(ValHi);
11817 Ops.push_back(
N->getOperand(2));
11819 N->getMemOperand());
11831 enum DataClassMask {
11833 DC_NEG_INF = 1 << 4,
11834 DC_POS_INF = 1 << 5,
11835 DC_NEG_ZERO = 1 << 2,
11836 DC_POS_ZERO = 1 << 3,
11837 DC_NEG_SUBNORM = 1,
11838 DC_POS_SUBNORM = 1 << 1,
11841 EVT VT =
Op.getValueType();
11843 unsigned TestOp = VT == MVT::f128 ? PPC::XSTSTDCQP
11844 : VT == MVT::f64 ? PPC::XSTSTDCDP
11855 return DAG.
getNOT(Dl, Rev, MVT::i1);
11862 TestOp, Dl, MVT::i32,
11864 DC_NEG_ZERO | DC_POS_ZERO |
11865 DC_NEG_SUBNORM | DC_POS_SUBNORM,
11871 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11877 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11882 Sign = DAG.
getNOT(Dl, Sign, MVT::i1);
11895 bool IsQuiet = Mask &
fcQNan;
11901 if (VT == MVT::f128) {
11905 QuietMask = 0x8000;
11906 }
else if (VT == MVT::f64) {
11907 if (Subtarget.isPPC64()) {
11918 QuietMask = 0x80000;
11919 }
else if (VT == MVT::f32) {
11921 QuietMask = 0x400000;
11937 unsigned NativeMask = 0;
11939 NativeMask |= DC_NAN;
11941 NativeMask |= DC_NEG_INF;
11943 NativeMask |= DC_POS_INF;
11945 NativeMask |= DC_NEG_ZERO;
11947 NativeMask |= DC_POS_ZERO;
11949 NativeMask |= DC_NEG_SUBNORM;
11951 NativeMask |= DC_POS_SUBNORM;
11954 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1,
11956 TestOp, Dl, MVT::i32,
11965 assert(Subtarget.hasP9Vector() &&
"Test data class requires Power9");
11967 uint64_t RHSC =
Op.getConstantOperandVal(1);
11970 if (
LHS.getValueType() == MVT::ppcf128) {
11994 bool Future = Subtarget.isISAFuture();
11997 "Mask predication not supported");
12000 unsigned IID = Future ? Intrinsic::ppc_vsx_lxvrl : Intrinsic::ppc_vsx_lxvl;
12001 unsigned EltBits =
Op->getValueType(0).getScalarType().getSizeInBits();
12005 SDVTList Tys = DAG.
getVTList(
Op->getValueType(0), MVT::Other);
12008 VPLD->getMemoryVT(), VPLD->getMemOperand());
12015 "Mask predication not supported");
12020 Op->getOperand(1).getValueType().getScalarType().getSizeInBits();
12021 bool Future = Subtarget.isISAFuture();
12022 unsigned IID = Future ? Intrinsic::ppc_vsx_stxvrl : Intrinsic::ppc_vsx_stxvl;
12025 VPST->getChain(), DAG.
getConstant(IID, dl, MVT::i32),
12028 SDVTList Tys = DAG.
getVTList(MVT::Other);
12031 VPST->getMemoryVT(), VPST->getMemOperand());
12042 "Unexpected partial reduction");
12065 unsigned EltSize =
Op.getValueType().getScalarSizeInBits();
12067 int64_t
IntVal =
Op.getConstantOperandVal(0);
12068 if (IntVal >= -16 && IntVal <= 15)
12074 if (Subtarget.hasLFIWAX() && Subtarget.hasVSX() &&
12079 MachineMemOperand *MMO =
12081 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
12084 PPCISD::LD_SPLAT, dl, DAG.
getVTList(MVT::v4i32, MVT::Other),
Ops,
12088 return Bits.getValue(0);
12104 !Subtarget.isLittleEndian() && ValVT.
isInteger() &&
12109 64 -
Op.getValueType().getScalarSizeInBits(), dl, ShiftAmountTy);
12117 MachinePointerInfo());
12124 return DAG.
getLoad(
Op.getValueType(), dl,
Store, FIdx, MachinePointerInfo());
12130 "Should only be called for ISD::INSERT_VECTOR_ELT");
12134 EVT VT =
Op.getValueType();
12139 if (VT == MVT::v2f64 &&
C)
12142 if (Subtarget.hasP9Vector()) {
12151 if ((VT == MVT::v4f32) && (V2.
getValueType() == MVT::f32) &&
12157 BitcastLoad,
Op.getOperand(2));
12158 return DAG.
getBitcast(MVT::v4f32, InsVecElt);
12162 if (Subtarget.isISA3_1()) {
12163 if ((VT == MVT::v2i64 || VT == MVT::v2f64) && !Subtarget.isPPC64())
12167 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
12168 VT == MVT::v2i64 || VT == MVT::v4f32 || VT == MVT::v2f64)
12178 if (VT == MVT::v8i16 || VT == MVT::v16i8) {
12181 unsigned InsertAtElement =
C->getZExtValue();
12182 unsigned InsertAtByte = InsertAtElement * BytesInEachElement;
12183 if (Subtarget.isLittleEndian()) {
12184 InsertAtByte = (16 - BytesInEachElement) - InsertAtByte;
12186 return DAG.
getNode(PPCISD::VECINSERT, dl, VT,
V1, Mtvsrz,
12198 EVT VT =
Op.getValueType();
12199 bool IsV1024i1 = VT == MVT::v1024i1;
12200 bool IsV2048i1 = VT == MVT::v2048i1;
12204 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12206 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12207 "Dense Math support required.");
12208 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12217 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12218 MachineMemOperand *NewMMO =
12226 DAG.
getVTList(MVT::v256i1, MVT::Other),
12227 LoadOps, MVT::v256i1, NewMMO);
12232 if (Subtarget.isLittleEndian()) {
12233 std::reverse(Loads.
begin(), Loads.
end());
12234 std::reverse(LoadChains.
begin(), LoadChains.
end());
12246 SDValue Dmr1Value = DMFInsert1024(MoreLoads, dl, DAG);
12252 const SDValue DmrPOps[] = {DmrPRC,
Value, Dmr0Sub, Dmr1Value, Dmr1Sub};
12255 DAG.
getMachineNode(PPC::REG_SEQUENCE, dl, MVT::v2048i1, DmrPOps), 0);
12264 DAG.
getNode(PPCISD::INST512, dl, MVT::v512i1, Pairs[0], Pairs[1]);
12267 DAG.
getNode(PPCISD::INST512HI, dl, MVT::v512i1, Pairs[2], Pairs[3]);
12272 {RC, Lo, LoSub, Hi, HiSub}),
12282 EVT VT =
Op.getValueType();
12284 if (VT == MVT::v1024i1 || VT == MVT::v2048i1)
12285 return LowerDMFVectorLoad(
Op, DAG);
12287 if (VT != MVT::v256i1 && VT != MVT::v512i1)
12291 assert((VT != MVT::v512i1 || Subtarget.hasMMA()) &&
12292 "Type unsupported without MMA");
12293 assert((VT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12294 "Type unsupported without paired vector support");
12298 if (VT == MVT::v256i1 && Subtarget.isISAFuture())
12307 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12309 DAG.
getLoad(MVT::v16i8, dl, LoadChain, BasePtr,
12318 if (Subtarget.isLittleEndian()) {
12319 std::reverse(Loads.
begin(), Loads.
end());
12320 std::reverse(LoadChains.
begin(), LoadChains.
end());
12324 DAG.
getNode(VT == MVT::v512i1 ? PPCISD::ACC_BUILD : PPCISD::PAIR_BUILD,
12340 bool IsV1024i1 = VT == MVT::v1024i1;
12341 bool IsV2048i1 = VT == MVT::v2048i1;
12345 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12347 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12348 "Dense Math support required.");
12349 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12351 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12354 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12359 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12363 MachineSDNode *ExtNode =
12367 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes,
Hi);
12373 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12379 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12385 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12390 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12395 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12400 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12404 MachineSDNode *ExtNode =
12405 DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr0Lo);
12409 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr0Hi);
12412 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr1Lo);
12416 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr1Hi);
12421 if (Subtarget.isLittleEndian())
12424 SDVTList Tys = DAG.
getVTList(MVT::Other);
12426 StoreChain, DAG.
getConstant(Intrinsic::ppc_vsx_stxvp, dl, MVT::i32),
12430 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12431 MachineMemOperand *NewMMO =
12440 MVT::v256i1, NewMMO);
12456 EVT StoreVT =
Value.getValueType();
12458 if (StoreVT == MVT::v1024i1 || StoreVT == MVT::v2048i1)
12459 return LowerDMFVectorStore(
Op, DAG);
12461 if (StoreVT != MVT::v256i1 && StoreVT != MVT::v512i1)
12465 assert((StoreVT != MVT::v512i1 || Subtarget.hasMMA()) &&
12466 "Type unsupported without MMA");
12467 assert((StoreVT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12468 "Type unsupported without paired vector support");
12472 if (StoreVT == MVT::v256i1 && Subtarget.isISAFuture() &&
12480 unsigned NumVecs = 2;
12481 if (StoreVT == MVT::v512i1) {
12482 if (Subtarget.isISAFuture()) {
12483 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12485 PPC::DMXXEXTFDMR512, dl, ReturnTypes,
Op.getOperand(1));
12488 Value2 =
SDValue(ExtNode, 1);
12493 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12494 unsigned VecNum = Subtarget.isLittleEndian() ? NumVecs - 1 - Idx : Idx;
12496 if (Subtarget.isISAFuture()) {
12497 VecNum = Subtarget.isLittleEndian() ? 1 - (Idx % 2) : (Idx % 2);
12498 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
12499 Idx > 1 ? Value2 :
Value,
12502 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
Value,
12506 DAG.
getStore(StoreChain, dl, Elt, BasePtr,
12520 if (
Op.getValueType() == MVT::v4i32) {
12537 LHS,
RHS, DAG, dl, MVT::v4i32);
12540 LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32);
12545 }
else if (
Op.getValueType() == MVT::v16i8) {
12547 bool isLittleEndian = Subtarget.isLittleEndian();
12551 LHS,
RHS, DAG, dl, MVT::v8i16);
12556 LHS,
RHS, DAG, dl, MVT::v8i16);
12564 for (
unsigned i = 0; i != 8; ++i) {
12565 if (isLittleEndian) {
12567 Ops[i*2+1] = 2*i+16;
12570 Ops[i*2+1] = 2*i+1+16;
12573 if (isLittleEndian)
12583 bool IsStrict =
Op->isStrictFPOpcode();
12584 if (
Op.getOperand(IsStrict ? 1 : 0).getValueType() == MVT::f128 &&
12585 !Subtarget.hasP9Vector())
12595 "Should only be called for ISD::FP_EXTEND");
12599 if (
Op.getValueType() != MVT::v2f64 ||
12600 Op.getOperand(0).getValueType() != MVT::v2f32)
12612 "Node should have 2 operands with second one being a constant!");
12624 int DWord = Idx >> 1;
12627 if (Subtarget.isLittleEndian())
12630 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64,
12644 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12646 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12647 LD->getMemoryVT(),
LD->getMemOperand());
12652 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewOp,
12657 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12659 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12660 LD->getMemoryVT(),
LD->getMemOperand());
12661 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewLd,
12672 if (STI.useCRBits())
12689 PPCISD::ADDE,
DL, DAG.
getVTList(SumType, MVT::i32), Zero, Zero, Flag);
12690 if (STI.useCRBits())
12698 SDNode *
N =
Op.getNode();
12699 EVT VT =
N->getValueType(0);
12700 EVT CarryType =
N->getValueType(1);
12701 unsigned Opc =
N->getOpcode();
12703 Opc = IsAdd ? PPCISD::ADDC : PPCISD::SUBC;
12705 N->getOperand(0),
N->getOperand(1));
12717 SDNode *
N =
Op.getNode();
12718 unsigned Opc =
N->getOpcode();
12719 EVT VT =
N->getValueType(0);
12720 EVT CarryType =
N->getValueType(1);
12721 SDValue CarryOp =
N->getOperand(2);
12723 Opc = IsAdd ? PPCISD::ADDE : PPCISD::SUBE;
12729 Op.getOperand(0),
Op.getOperand(1), CarryOp);
12743 EVT VT =
Op.getNode()->getValueType(0);
12769 EVT VT =
Op.getNode()->getValueType(0);
12801 EVT OpVT =
LHS.getValueType();
12802 EVT VT =
Op.getValueType();
12817 unsigned Opcode = PPCISD::SUBC;
12827 Opcode = PPCISD::ADDC;
12834 if (Subtarget.isPPC64() && OpVT != MVT::i64) {
12841 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12861 EVT OpVT =
A.getValueType();
12862 EVT ResVT =
Op.getValueType();
12867 if (Subtarget.isPPC64() && OpVT != MVT::i64) {
12877 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12895 switch (
Op.getOpcode()) {
12916 return LowerSSUBO(
Op, DAG);
12918 return LowerSADDO(
Op, DAG);
12930 return LowerGET_DYNAMIC_AREA_OFFSET(
Op, DAG);
12951 return LowerSET_ROUNDING(
Op, DAG);
12958 case ISD::FSHL:
return LowerFunnelShift(
Op, DAG);
12959 case ISD::FSHR:
return LowerFunnelShift(
Op, DAG);
12971 return LowerFP_ROUND(
Op, DAG);
12985 return LowerINTRINSIC_VOID(
Op, DAG);
12987 return LowerBSWAP(
Op, DAG);
12989 return LowerATOMIC_CMP_SWAP(
Op, DAG);
12991 return LowerATOMIC_LOAD_STORE(
Op, DAG);
12993 return LowerIS_FPCLASS(
Op, DAG);
12996 return LowerADDSUBO(
Op, DAG);
12999 return LowerADDSUBO_CARRY(
Op, DAG);
13001 return LowerUCMP(
Op, DAG);
13003 return LowerABDU(
Op, DAG);
13009 if (
Op->getFlags().hasNoFPExcept())
13013 return LowerVP_LOAD(
Op, DAG);
13014 case ISD::VP_STORE:
13015 return LowerVP_STORE(
Op, DAG);
13017 return LowerPartialReduce(
Op, DAG);
13025 switch (
N->getOpcode()) {
13027 llvm_unreachable(
"Do not know how to custom type legalize this operation!");
13044 if (
N->getConstantOperandVal(1) != Intrinsic::loop_decrement)
13047 assert(
N->getValueType(0) == MVT::i1 &&
13048 "Unexpected result type for CTR decrement intrinsic");
13050 N->getValueType(0));
13060 switch (
N->getConstantOperandVal(0)) {
13061 case Intrinsic::ppc_pack_longdouble:
13063 N->getOperand(2),
N->getOperand(1)));
13065 case Intrinsic::ppc_maxfe:
13066 case Intrinsic::ppc_minfe:
13067 case Intrinsic::ppc_fnmsub:
13068 case Intrinsic::ppc_convert_f128_to_ppcf128:
13075 if (!Subtarget.isSVR4ABI() || Subtarget.isPPC64())
13078 EVT VT =
N->getValueType(0);
13080 if (VT == MVT::i64) {
13093 if (
N->getOperand(
N->isStrictFPOpcode() ? 1 : 0).getValueType() ==
13097 Results.push_back(LoweredValue);
13098 if (
N->isStrictFPOpcode())
13103 if (!
N->getValueType(0).isVector())
13136 return Builder.CreateIntrinsicWithoutFolding(Id, {});
13142 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
13144 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
13145 "Only 8/16/32/64-bit atomic loads supported");
13151 IntID = Intrinsic::ppc_lbarx;
13152 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13155 IntID = Intrinsic::ppc_lharx;
13156 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13159 IntID = Intrinsic::ppc_lwarx;
13162 IntID = Intrinsic::ppc_ldarx;
13166 Builder.CreateIntrinsic(IntID, Addr,
nullptr,
"larx");
13168 return Builder.CreateTruncOrBitCast(
Call, ValueTy);
13179 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
13180 "Only 8/16/32/64-bit atomic loads supported");
13186 IntID = Intrinsic::ppc_stbcx;
13187 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13190 IntID = Intrinsic::ppc_sthcx;
13191 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13194 IntID = Intrinsic::ppc_stwcx;
13197 IntID = Intrinsic::ppc_stdcx;
13201 if (SZ == 8 || SZ == 16)
13202 Val = Builder.CreateZExt(Val, Builder.getInt32Ty());
13204 Value *
Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
13206 return Builder.CreateXor(
Call, Builder.getInt32(1));
13229 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::ppc_cfence,
13239 unsigned BinOpcode,
13240 unsigned CmpOpcode,
13241 unsigned CmpPred)
const {
13246 unsigned AtomicSize =
MI.getOperand(3).getImm();
13248 auto LoadMnemonic = PPC::LDARX;
13249 auto StoreMnemonic = PPC::STDCX;
13250 switch (AtomicSize) {
13254 LoadMnemonic = PPC::LBARX;
13255 StoreMnemonic = PPC::STBCX;
13256 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13259 LoadMnemonic = PPC::LHARX;
13260 StoreMnemonic = PPC::STHCX;
13261 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13264 LoadMnemonic = PPC::LWARX;
13265 StoreMnemonic = PPC::STWCX;
13268 LoadMnemonic = PPC::LDARX;
13269 StoreMnemonic = PPC::STDCX;
13277 if (CmpOpcode == PPC::CMPW && (AtomicSize == 1 || AtomicSize == 2))
13288 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13290 F->insert(It, loopMBB);
13292 F->insert(It, loop2MBB);
13293 F->insert(It, exitMBB);
13299 Register TmpReg = (!BinOpcode) ? incr :
13300 RegInfo.createVirtualRegister( AtomicSize == 8 ? &PPC::G8RCRegClass
13301 : &PPC::GPRCRegClass);
13326 BuildMI(BB, dl,
TII->get(LoadMnemonic), dest)
13331 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13333 if (CmpOpcode == PPC::CMPW && AtomicSize < 4) {
13334 Register ExtReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13335 BuildMI(BB, dl,
TII->get(AtomicSize == 1 ? PPC::EXTSB : PPC::EXTSH),
13365 switch(
MI.getOpcode()) {
13369 return TII->isSignExtended(
MI.getOperand(1).getReg(),
13370 &
MI.getMF()->getRegInfo());
13394 case PPC::EXTSB8_32_64:
13395 case PPC::EXTSB8_rec:
13396 case PPC::EXTSB_rec:
13399 case PPC::EXTSH8_32_64:
13400 case PPC::EXTSH8_rec:
13401 case PPC::EXTSH_rec:
13403 case PPC::EXTSWSLI:
13404 case PPC::EXTSWSLI_32_64:
13405 case PPC::EXTSWSLI_32_64_rec:
13406 case PPC::EXTSWSLI_rec:
13407 case PPC::EXTSW_32:
13408 case PPC::EXTSW_32_64:
13409 case PPC::EXTSW_32_64_rec:
13410 case PPC::EXTSW_rec:
13413 case PPC::SRAWI_rec:
13414 case PPC::SRAW_rec:
13424 unsigned OpIdx,
bool IsByte,
13429 bool IsSignExtended =
13432 if (!IsSignExtended) {
13433 Register ValueReg =
RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13435 TII->get(IsByte ? PPC::EXTSB : PPC::EXTSH), ValueReg)
13437 MI.getOperand(
OpIdx).setReg(ValueReg);
13443 unsigned CmpOpcode,
unsigned CmpPred)
const {
13447 assert(!Subtarget.hasPartwordAtomics() &&
13448 "Assumes that part-word atomics are not available");
13456 const bool is8bit =
MI.getOperand(3).getImm() == 1;
13457 if (CmpOpcode == PPC::CMPW)
13465 bool is64bit = Subtarget.isPPC64();
13466 bool isLittleEndian = Subtarget.isLittleEndian();
13467 unsigned ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
13478 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13480 F->insert(It, loopMBB);
13482 F->insert(It, loop2MBB);
13483 F->insert(It, exitMBB);
13489 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13492 Register PtrReg = RegInfo.createVirtualRegister(RC);
13493 Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
13495 isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
13496 Register Incr2Reg = RegInfo.createVirtualRegister(GPRC);
13497 Register MaskReg = RegInfo.createVirtualRegister(GPRC);
13498 Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
13499 Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
13500 Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
13501 Register Tmp3Reg = RegInfo.createVirtualRegister(GPRC);
13502 Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
13503 Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
13504 Register SrwDestReg = RegInfo.createVirtualRegister(GPRC);
13507 (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(GPRC);
13534 if (ptrA != ZeroReg) {
13535 Ptr1Reg = RegInfo.createVirtualRegister(RC);
13536 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
13544 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
13545 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
13548 .
addImm(is8bit ? 28 : 27);
13549 if (!isLittleEndian)
13550 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
13552 .
addImm(is8bit ? 24 : 16);
13554 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
13559 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
13569 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
13573 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
13578 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
13582 BuildMI(BB, dl,
TII->get(BinOpcode), TmpReg)
13585 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
13592 Register SReg = RegInfo.createVirtualRegister(GPRC);
13593 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13597 unsigned ValueReg = SReg;
13598 unsigned CmpReg = Incr2Reg;
13599 if (CmpOpcode == PPC::CMPW) {
13600 ValueReg = RegInfo.createVirtualRegister(GPRC);
13601 BuildMI(BB, dl,
TII->get(PPC::SRW), ValueReg)
13604 Register ValueSReg = RegInfo.createVirtualRegister(GPRC);
13605 BuildMI(BB, dl,
TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueSReg)
13607 ValueReg = ValueSReg;
13639 .
addImm(is8bit ? 24 : 16)
13660 Register DstReg =
MI.getOperand(0).getReg();
13662 assert(
TRI->isTypeLegalForClass(*RC, MVT::i32) &&
"Invalid destination!");
13667 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13668 "Invalid Pointer Size!");
13717 Register BufReg =
MI.getOperand(1).getReg();
13719 if (Subtarget.is64BitELFABI()) {
13732 BaseReg = Subtarget.isPPC64() ? PPC::X1 : PPC::R1;
13734 BaseReg = Subtarget.isPPC64() ? PPC::BP8 : PPC::BP;
13737 TII->get(Subtarget.isPPC64() ? PPC::STD : PPC::STW))
13760 TII->get(Subtarget.isPPC64() ? PPC::MFLR8 : PPC::MFLR), LabelReg);
13763 if (Subtarget.isPPC64()) {
13781 TII->get(PPC::PHI), DstReg)
13785 MI.eraseFromParent();
13799 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13800 "Invalid Pointer Size!");
13803 (PVT == MVT::i64) ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13806 unsigned FP = (PVT == MVT::i64) ? PPC::X31 : PPC::R31;
13807 unsigned SP = (PVT == MVT::i64) ? PPC::X1 : PPC::R1;
13821 Register BufReg =
MI.getOperand(0).getReg();
13826 if (PVT == MVT::i64) {
13838 if (PVT == MVT::i64) {
13850 if (PVT == MVT::i64) {
13862 if (PVT == MVT::i64) {
13874 if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) {
13884 TII->get(PVT == MVT::i64 ? PPC::MTCTR8 : PPC::MTCTR)).
addReg(Tmp);
13887 MI.eraseFromParent();
13903 "Unexpected stack alignment");
13907 unsigned StackProbeSize =
13910 StackProbeSize &= ~(StackAlign - 1);
13911 return StackProbeSize ? StackProbeSize : StackAlign;
13923 const bool isPPC64 = Subtarget.isPPC64();
13955 MF->
insert(MBBIter, TestMBB);
13956 MF->
insert(MBBIter, BlockMBB);
13957 MF->
insert(MBBIter, TailMBB);
13962 Register DstReg =
MI.getOperand(0).getReg();
13963 Register NegSizeReg =
MI.getOperand(1).getReg();
13975 isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_64 : PPC::PREPARE_PROBED_ALLOCA_32;
13981 ProbeOpc = isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_64
13982 : PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_32;
13984 .
addDef(ActualNegSizeReg)
13986 .
add(
MI.getOperand(2))
13987 .
add(
MI.getOperand(3));
13993 .
addReg(ActualNegSizeReg);
13996 int64_t NegProbeSize = -(int64_t)ProbeSize;
14002 .
addImm(NegProbeSize >> 16);
14006 .
addImm(NegProbeSize & 0xFFFF);
14015 .
addReg(ActualNegSizeReg)
14024 .
addReg(ActualNegSizeReg);
14034 BuildMI(TestMBB,
DL,
TII->get(isPPC64 ? PPC::CMPD : PPC::CMPW), CmpResult)
14061 TII->get(isPPC64 ? PPC::DYNAREAOFFSET8 : PPC::DYNAREAOFFSET),
14062 MaxCallFrameSizeReg)
14063 .
add(
MI.getOperand(2))
14064 .
add(
MI.getOperand(3));
14065 BuildMI(TailMBB,
DL,
TII->get(isPPC64 ? PPC::ADD8 : PPC::ADD4), DstReg)
14067 .
addReg(MaxCallFrameSizeReg);
14073 MBB->addSuccessor(TestMBB);
14076 MI.eraseFromParent();
14078 ++NumDynamicAllocaProbed;
14086static bool IsSelect(
unsigned Opcode,
bool CheckOnlyCC =
false) {
14089 case PPC::SELECT_CC_I4:
14090 case PPC::SELECT_CC_I8:
14091 case PPC::SELECT_CC_F4:
14092 case PPC::SELECT_CC_F8:
14093 case PPC::SELECT_CC_F16:
14094 case PPC::SELECT_CC_VRRC:
14095 case PPC::SELECT_CC_VSFRC:
14096 case PPC::SELECT_CC_VSSRC:
14097 case PPC::SELECT_CC_VSRC:
14098 case PPC::SELECT_CC_SPE4:
14099 case PPC::SELECT_CC_SPE:
14102 case PPC::SELECT_I4:
14103 case PPC::SELECT_I8:
14104 case PPC::SELECT_F4:
14105 case PPC::SELECT_F8:
14106 case PPC::SELECT_F16:
14107 case PPC::SELECT_SPE:
14108 case PPC::SELECT_SPE4:
14109 case PPC::SELECT_VRRC:
14110 case PPC::SELECT_VSFRC:
14111 case PPC::SELECT_VSSRC:
14112 case PPC::SELECT_VSRC:
14113 return !CheckOnlyCC;
14129 assert(
IsSelect(
MI.getOpcode()) &&
"Instruction must be a SELECT variant");
14132 if (Subtarget.hasISEL() &&
14133 (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
14134 MI.getOpcode() == PPC::SELECT_CC_I8 ||
14135 MI.getOpcode() == PPC::SELECT_I4 ||
MI.getOpcode() == PPC::SELECT_I8)) {
14137 if (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
14138 MI.getOpcode() == PPC::SELECT_CC_I8)
14139 Cond.push_back(
MI.getOperand(4));
14142 Cond.push_back(
MI.getOperand(1));
14145 TII->insertSelect(*BB,
MI, dl,
MI.getOperand(0).getReg(),
Cond,
14146 MI.getOperand(2).getReg(),
MI.getOperand(3).getReg());
14147 MI.eraseFromParent();
14160 F->insert(It, copy0MBB);
14161 F->insert(It, sinkMBB);
14169 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
14185 .
addImm(
MI.getOperand(4).getImm())
14186 .
addReg(
MI.getOperand(1).getReg())
14190 .
addReg(
MI.getOperand(1).getReg())
14200 .
addReg(
MI.getOperand(3).getReg())
14202 .
addReg(
MI.getOperand(2).getReg())
14204 MI.eraseFromParent();
14219 loop1MBB =
F->CreateMachineBasicBlock(LLVM_BB);
14220 loop2MBB =
F->CreateMachineBasicBlock(LLVM_BB);
14221 exitMBB =
F->CreateMachineBasicBlock(LLVM_BB);
14222 F->insert(It, loop1MBB);
14223 F->insert(It, loop2MBB);
14224 F->insert(It, exitMBB);
14259 bool is64bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
14261 unsigned LoadMnemonic = PPC::LDARX;
14262 unsigned StoreMnemonic = PPC::STDCX;
14263 switch (
MI.getOpcode()) {
14266 case PPC::ATOMIC_CMP_SWAP_I8:
14267 LoadMnemonic = PPC::LBARX;
14268 StoreMnemonic = PPC::STBCX;
14269 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14271 case PPC::ATOMIC_CMP_SWAP_I16:
14272 LoadMnemonic = PPC::LHARX;
14273 StoreMnemonic = PPC::STHCX;
14274 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14276 case PPC::ATOMIC_CMP_SWAP_I32:
14277 LoadMnemonic = PPC::LWARX;
14278 StoreMnemonic = PPC::STWCX;
14280 case PPC::ATOMIC_CMP_SWAP_I64:
14281 LoadMnemonic = PPC::LDARX;
14282 StoreMnemonic = PPC::STDCX;
14290 Register oldval =
MI.getOperand(3).getReg();
14291 Register newval =
MI.getOperand(4).getReg();
14305 BuildMI(BB, dl,
TII->get(is64bit ? PPC::CMPD : PPC::CMPW), CrReg)
14373 bool is64bit = Subtarget.isPPC64();
14375 bool is8bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8;
14380 Register oldval =
MI.getOperand(3).getReg();
14381 Register newval =
MI.getOperand(4).getReg();
14389 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
14394 return RegInfo.createVirtualRegister(RC);
14398 Register Shift1Reg = createVReg(GPRC);
14399 Register ShiftReg = isLittleEndian ? Shift1Reg : createVReg(GPRC);
14400 Register NewVal2Reg = createVReg(GPRC);
14401 Register NewVal3Reg = createVReg(GPRC);
14402 Register OldVal2Reg = createVReg(GPRC);
14403 Register OldVal3Reg = createVReg(GPRC);
14404 Register MaskReg = createVReg(GPRC);
14405 Register Mask2Reg = createVReg(GPRC);
14406 Register Mask3Reg = createVReg(GPRC);
14407 Register Tmp2Reg = createVReg(GPRC);
14408 Register Tmp4Reg = createVReg(GPRC);
14409 Register TmpDestReg = createVReg(GPRC);
14410 Register TmpReg = createVReg(GPRC);
14411 Register ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
14412 Register CrReg = createVReg(&PPC::CRRCRegClass);
14416 if (ptrA != ZeroReg) {
14417 Ptr1Reg = createVReg(RC);
14418 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
14425 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
14426 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
14429 .
addImm(is8bit ? 28 : 27);
14430 if (!isLittleEndian)
14431 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
14433 .
addImm(is8bit ? 24 : 16);
14435 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
14440 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
14447 BuildMI(BB, dl,
TII->get(PPC::SLW), NewVal2Reg)
14450 BuildMI(BB, dl,
TII->get(PPC::SLW), OldVal2Reg)
14457 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
14461 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
14464 BuildMI(BB, dl,
TII->get(PPC::AND), NewVal3Reg)
14467 BuildMI(BB, dl,
TII->get(PPC::AND), OldVal3Reg)
14477 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
14498 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
14543 switch (
MI.getOpcode()) {
14544 case TargetOpcode::STACKMAP:
14546 case TargetOpcode::PATCHPOINT:
14552 if (Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls())
14556 case PPC::EH_SjLj_SetJmp32:
14557 case PPC::EH_SjLj_SetJmp64:
14560 case PPC::EH_SjLj_LongJmp32:
14561 case PPC::EH_SjLj_LongJmp64:
14564 case PPC::ReadTB: {
14580 F->insert(It, readMBB);
14581 F->insert(It, sinkMBB);
14592 Register ReadAgainReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
14600 Register CmpReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14602 BuildMI(BB, dl,
TII->get(PPC::CMPW), CmpReg)
14614 case PPC::ATOMIC_LOAD_ADD_NOWP:
14617 case PPC::ATOMIC_LOAD_ADD:
14620 case PPC::ATOMIC_LOAD_ADD_I64:
14623 case PPC::ATOMIC_LOAD_AND_NOWP:
14626 case PPC::ATOMIC_LOAD_AND:
14629 case PPC::ATOMIC_LOAD_AND_I64:
14632 case PPC::ATOMIC_LOAD_OR_NOWP:
14635 case PPC::ATOMIC_LOAD_OR:
14638 case PPC::ATOMIC_LOAD_OR_I64:
14641 case PPC::ATOMIC_LOAD_XOR_NOWP:
14644 case PPC::ATOMIC_LOAD_XOR:
14647 case PPC::ATOMIC_LOAD_XOR_I64:
14650 case PPC::ATOMIC_LOAD_NAND_NOWP:
14653 case PPC::ATOMIC_LOAD_NAND:
14656 case PPC::ATOMIC_LOAD_NAND_I64:
14659 case PPC::ATOMIC_LOAD_SUB_NOWP:
14662 case PPC::ATOMIC_LOAD_SUB:
14665 case PPC::ATOMIC_LOAD_SUB_I64:
14668 case PPC::ATOMIC_LOAD_MIN_NOWP:
14671 case PPC::ATOMIC_LOAD_MIN:
14674 case PPC::ATOMIC_LOAD_MIN_I64:
14677 case PPC::ATOMIC_LOAD_MAX_NOWP:
14680 case PPC::ATOMIC_LOAD_MAX:
14683 case PPC::ATOMIC_LOAD_MAX_I64:
14686 case PPC::ATOMIC_LOAD_UMIN_NOWP:
14689 case PPC::ATOMIC_LOAD_UMIN:
14692 case PPC::ATOMIC_LOAD_UMIN_I64:
14695 case PPC::ATOMIC_LOAD_UMAX_NOWP:
14698 case PPC::ATOMIC_LOAD_UMAX:
14701 case PPC::ATOMIC_LOAD_UMAX_I64:
14704 case PPC::ATOMIC_SWAP_NOWP:
14707 case PPC::ATOMIC_SWAP:
14708 case PPC::ATOMIC_SWAP_I64:
14711 case PPC::ATOMIC_CMP_SWAP_I32:
14712 case PPC::ATOMIC_CMP_SWAP_I64:
14713 case PPC::ATOMIC_CMP_SWAP_I8:
14714 case PPC::ATOMIC_CMP_SWAP_I16: {
14716 bool useHardware =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
14717 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64 ||
14718 (Subtarget.hasPartwordAtomics() &&
14719 (
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 ||
14720 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16));
14728 case PPC::FADDrtz: {
14738 Register MFFSReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14753 auto MIB =
BuildMI(*BB,
MI, dl,
TII->get(PPC::FADD), Dest)
14763 case PPC::ANDI_rec_1_EQ_BIT:
14764 case PPC::ANDI_rec_1_GT_BIT:
14765 case PPC::ANDI_rec_1_EQ_BIT8:
14766 case PPC::ANDI_rec_1_GT_BIT8: {
14767 unsigned Opcode = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
14768 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8)
14771 bool IsEQ = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
14772 MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8);
14775 Register Dest = RegInfo.createVirtualRegister(
14776 Opcode == PPC::ANDI_rec ? &PPC::GPRCRegClass : &PPC::G8RCRegClass);
14780 .
addReg(
MI.getOperand(1).getReg())
14783 MI.getOperand(0).getReg())
14784 .
addReg(IsEQ ? PPC::CR0EQ : PPC::CR0GT);
14787 case PPC::TCHECK_RET: {
14790 Register CRReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14793 MI.getOperand(0).getReg())
14797 case PPC::TBEGIN_RET: {
14799 unsigned Imm =
MI.getOperand(1).getImm();
14802 MI.getOperand(0).getReg())
14806 case PPC::SETRNDi: {
14808 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14812 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14814 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14825 unsigned Mode =
MI.getOperand(1).getImm();
14826 BuildMI(*BB,
MI, dl,
TII->get((Mode & 1) ? PPC::MTFSB1 : PPC::MTFSB0))
14830 BuildMI(*BB,
MI, dl,
TII->get((Mode & 2) ? PPC::MTFSB1 : PPC::MTFSB0))
14835 case PPC::SETRND: {
14843 auto copyRegFromG8RCOrF8RC = [&] (
unsigned DestReg,
unsigned SrcReg) {
14844 if (Subtarget.hasDirectMove()) {
14845 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::COPY), DestReg)
14849 unsigned StoreOp = PPC::STD, LoadOp = PPC::LFD;
14852 if (RC == &PPC::F8RCRegClass) {
14854 assert((RegInfo.getRegClass(DestReg) == &PPC::G8RCRegClass) &&
14855 "Unsupported RegClass.");
14857 StoreOp = PPC::STFD;
14861 assert((RegInfo.getRegClass(SrcReg) == &PPC::G8RCRegClass) &&
14862 (RegInfo.getRegClass(DestReg) == &PPC::F8RCRegClass) &&
14863 "Unsupported RegClass.");
14896 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14899 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14911 Register OldFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14913 copyRegFromG8RCOrF8RC(OldFPSCRTmpReg, OldFPSCRReg);
14915 Register ImDefReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14916 Register ExtSrcReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14921 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), ImDefReg);
14922 BuildMI(*BB,
MI, dl,
TII->get(PPC::INSERT_SUBREG), ExtSrcReg)
14927 Register NewFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14928 BuildMI(*BB,
MI, dl,
TII->get(PPC::RLDIMI), NewFPSCRTmpReg)
14934 Register NewFPSCRReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14935 copyRegFromG8RCOrF8RC(NewFPSCRReg, NewFPSCRTmpReg);
14946 case PPC::SETFLM: {
14950 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14952 BuildMI(*BB,
MI, Dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14954 BuildMI(*BB,
MI, Dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14957 Register NewFPSCRReg =
MI.getOperand(1).getReg();
14965 case PPC::PROBED_ALLOCA_32:
14966 case PPC::PROBED_ALLOCA_64:
14969 case PPC::SPLIT_QUADWORD: {
14976 .
addUse(Src, {}, PPC::sub_gp8_x1);
14979 .
addUse(Src, {}, PPC::sub_gp8_x0);
14982 case PPC::LQX_PSEUDO:
14983 case PPC::STQX_PSEUDO: {
14989 F->getRegInfo().createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass);
14995 MI.getOpcode() == PPC::LQX_PSEUDO ?
TII->get(PPC::LQ)
14996 :
TII->get(PPC::STQ))
15006 MI.eraseFromParent();
15019 int RefinementSteps = Subtarget.hasRecipPrec() ? 1 : 3;
15022 return RefinementSteps;
15029 EVT VT =
Op.getValueType();
15032 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX())))
15056PPCTargetLowering::getSqrtResultForDenormInput(
SDValue Op,
15059 EVT VT =
Op.getValueType();
15060 if (VT != MVT::f64 &&
15061 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX()))
15064 return DAG.
getNode(PPCISD::FSQRT, SDLoc(
Op), VT,
Op);
15068 int Enabled,
int &RefinementSteps,
15069 bool &UseOneConstNR,
15070 bool Reciprocal)
const {
15072 if ((VT == MVT::f32 && Subtarget.hasFRSQRTES()) ||
15073 (VT == MVT::f64 && Subtarget.hasFRSQRTE()) ||
15074 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
15075 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
15081 UseOneConstNR = !Subtarget.needsTwoConstNR();
15082 return DAG.
getNode(PPCISD::FRSQRTE, SDLoc(Operand), VT, Operand);
15089 int &RefinementSteps)
const {
15091 if ((VT == MVT::f32 && Subtarget.hasFRES()) ||
15092 (VT == MVT::f64 && Subtarget.hasFRE()) ||
15093 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
15094 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
15097 return DAG.
getNode(PPCISD::FRE, SDLoc(Operand), VT, Operand);
15113 switch (Subtarget.getCPUDirective()) {
15140 unsigned Bytes,
int Dist,
15154 if (FS != BFS || FS != (
int)Bytes)
return false;
15159 int64_t Offset1 = 0, Offset2 = 0;
15162 if (Base1 == Base2 && Offset1 == (Offset2 + Dist * Bytes))
15172 if (isGA1 && isGA2 && GV1 == GV2)
15173 return Offset1 == (Offset2 + Dist*Bytes);
15180 unsigned Bytes,
int Dist,
15183 EVT VT = LS->getMemoryVT();
15190 switch (
N->getConstantOperandVal(1)) {
15191 default:
return false;
15192 case Intrinsic::ppc_altivec_lvx:
15193 case Intrinsic::ppc_altivec_lvxl:
15194 case Intrinsic::ppc_vsx_lxvw4x:
15195 case Intrinsic::ppc_vsx_lxvw4x_be:
15198 case Intrinsic::ppc_vsx_lxvd2x:
15199 case Intrinsic::ppc_vsx_lxvd2x_be:
15202 case Intrinsic::ppc_altivec_lvebx:
15205 case Intrinsic::ppc_altivec_lvehx:
15208 case Intrinsic::ppc_altivec_lvewx:
15218 switch (
N->getConstantOperandVal(1)) {
15219 default:
return false;
15220 case Intrinsic::ppc_altivec_stvx:
15221 case Intrinsic::ppc_altivec_stvxl:
15222 case Intrinsic::ppc_vsx_stxvw4x:
15225 case Intrinsic::ppc_vsx_stxvd2x:
15228 case Intrinsic::ppc_vsx_stxvw4x_be:
15231 case Intrinsic::ppc_vsx_stxvd2x_be:
15234 case Intrinsic::ppc_altivec_stvebx:
15237 case Intrinsic::ppc_altivec_stvehx:
15240 case Intrinsic::ppc_altivec_stvewx:
15257 SDValue Chain = LD->getChain();
15258 EVT VT = LD->getMemoryVT();
15267 while (!Queue.empty()) {
15268 SDNode *ChainNext = Queue.pop_back_val();
15269 if (!Visited.
insert(ChainNext).second)
15276 if (!Visited.
count(ChainLD->getChain().getNode()))
15277 Queue.push_back(ChainLD->getChain().getNode());
15279 for (
const SDUse &O : ChainNext->
ops())
15280 if (!Visited.
count(O.getNode()))
15281 Queue.push_back(O.getNode());
15283 LoadRoots.
insert(ChainNext);
15294 for (
SDNode *
I : LoadRoots) {
15295 Queue.push_back(
I);
15297 while (!Queue.empty()) {
15298 SDNode *LoadRoot = Queue.pop_back_val();
15299 if (!Visited.
insert(LoadRoot).second)
15311 Queue.push_back(U);
15344 auto Final = Shifted;
15355 DAGCombinerInfo &DCI)
const {
15358 SelectionDAG &DAG = DCI.DAG;
15363 if (!DCI.isAfterLegalizeDAG())
15368 for (
const SDNode *U :
N->users())
15373 auto OpSize =
N->getOperand(0).getValueSizeInBits();
15377 if (OpSize <
Size) {
15395 DAGCombinerInfo &DCI)
const {
15396 SelectionDAG &DAG = DCI.DAG;
15399 assert(Subtarget.useCRBits() &&
"Expecting to be tracking CR bits");
15410 N->getValueType(0) != MVT::i1)
15413 if (
N->getOperand(0).getValueType() != MVT::i32 &&
15414 N->getOperand(0).getValueType() != MVT::i64)
15424 unsigned OpBits =
N->getOperand(0).getValueSizeInBits();
15435 return (
N->getOpcode() ==
ISD::SETCC ? ConvertSETCCToSubtract(
N, DCI)
15458 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15459 N->getOperand(0).getOpcode() !=
ISD::OR &&
15460 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15470 N->getOperand(1).getOpcode() !=
ISD::AND &&
15471 N->getOperand(1).getOpcode() !=
ISD::OR &&
15472 N->getOperand(1).getOpcode() !=
ISD::XOR &&
15483 SmallPtrSet<SDNode *, 16> Visited;
15485 for (
unsigned i = 0; i < 2; ++i) {
15489 N->getOperand(i).getOperand(0).getValueType() == MVT::i1) ||
15501 while (!BinOps.
empty()) {
15509 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15543 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15547 for (
const SDNode *User : Inputs[i].
getNode()->
users()) {
15548 if (User !=
N && !Visited.
count(User))
15557 if (
User->getOperand(0) == Inputs[i])
15560 if (
User->getOperand(0) == Inputs[i] ||
15561 User->getOperand(1) == Inputs[i])
15567 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15568 for (
const SDNode *User : PromOps[i].
getNode()->
users()) {
15569 if (User !=
N && !Visited.
count(User))
15578 if (
User->getOperand(0) == PromOps[i])
15581 if (
User->getOperand(0) == PromOps[i] ||
15582 User->getOperand(1) == PromOps[i])
15589 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15598 std::list<HandleSDNode> PromOpHandles;
15599 for (
auto &PromOp : PromOps)
15600 PromOpHandles.emplace_back(PromOp);
15607 while (!PromOpHandles.empty()) {
15608 SDValue PromOp = PromOpHandles.back().getValue();
15609 PromOpHandles.pop_back();
15618 PromOpHandles.emplace_front(PromOp);
15632 default:
C = 0;
break;
15645 PromOpHandles.emplace_front(PromOp);
15652 for (
unsigned i = 0; i < 2; ++i)
15662 return N->getOperand(0);
15670 DAGCombinerInfo &DCI)
const {
15671 SelectionDAG &DAG = DCI.DAG;
15688 if (
N->getValueType(0) != MVT::i32 &&
15689 N->getValueType(0) != MVT::i64)
15692 if (!((
N->getOperand(0).getValueType() == MVT::i1 && Subtarget.useCRBits()) ||
15693 (
N->getOperand(0).getValueType() == MVT::i32 && Subtarget.isPPC64())))
15696 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15697 N->getOperand(0).getOpcode() !=
ISD::OR &&
15698 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15705 SmallPtrSet<SDNode *, 16> Visited;
15709 while (!BinOps.
empty()) {
15717 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15743 DenseMap<SDNode *, EVT> SelectTruncOp[2];
15748 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15753 if (User !=
N && !Visited.
count(User))
15759 if (
User->getOperand(0) == Inputs[i])
15760 SelectTruncOp[0].
insert(std::make_pair(User,
15761 User->getOperand(0).getValueType()));
15763 if (
User->getOperand(0) == Inputs[i])
15764 SelectTruncOp[0].
insert(std::make_pair(User,
15765 User->getOperand(0).getValueType()));
15766 if (
User->getOperand(1) == Inputs[i])
15767 SelectTruncOp[1].
insert(std::make_pair(User,
15768 User->getOperand(1).getValueType()));
15773 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15775 if (User !=
N && !Visited.
count(User))
15781 if (
User->getOperand(0) == PromOps[i])
15782 SelectTruncOp[0].
insert(std::make_pair(User,
15783 User->getOperand(0).getValueType()));
15785 if (
User->getOperand(0) == PromOps[i])
15786 SelectTruncOp[0].
insert(std::make_pair(User,
15787 User->getOperand(0).getValueType()));
15788 if (
User->getOperand(1) == PromOps[i])
15789 SelectTruncOp[1].
insert(std::make_pair(User,
15790 User->getOperand(1).getValueType()));
15795 unsigned PromBits =
N->getOperand(0).getValueSizeInBits();
15796 bool ReallyNeedsExt =
false;
15800 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15805 Inputs[i].getOperand(0).getValueSizeInBits();
15806 assert(PromBits < OpBits &&
"Truncation not to a smaller bit count?");
15811 OpBits-PromBits))) ||
15814 (OpBits-(PromBits-1)))) {
15815 ReallyNeedsExt =
true;
15823 std::list<HandleSDNode> PromOpHandles;
15824 for (
auto &PromOp : PromOps)
15825 PromOpHandles.emplace_back(PromOp);
15829 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15836 SDValue InSrc = Inputs[i].getOperand(0);
15854 while (!PromOpHandles.empty()) {
15856 PromOpHandles.pop_back();
15860 default:
C = 0;
break;
15873 PromOpHandles.emplace_front(PromOp);
15883 (SelectTruncOp[1].count(PromOp.
getNode()) &&
15885 PromOpHandles.emplace_front(PromOp);
15893 for (
unsigned i = 0; i < 2; ++i) {
15911 auto SI0 = SelectTruncOp[0].
find(PromOp.
getNode());
15912 if (SI0 != SelectTruncOp[0].
end())
15914 auto SI1 = SelectTruncOp[1].
find(PromOp.
getNode());
15915 if (SI1 != SelectTruncOp[1].
end())
15924 if (!ReallyNeedsExt)
15925 return N->getOperand(0);
15932 N->getValueSizeInBits(0), PromBits),
15933 dl,
N->getValueType(0)));
15936 "Invalid extension type");
15939 DAG.
getConstant(
N->getValueSizeInBits(0) - PromBits, dl, ShiftAmountTy);
15949 auto isValidForConvert = [IsPPC64](
SDValue &Operand) {
15958 const APInt &Val =
C->getAPIntValue();
15964 if (IsPPC64 && Val.
ult(1ULL << 16))
15978 if (LoadNode->isVolatile())
15999 return (isValidForConvert(
LHS) && isValidForConvert(
RHS));
16009 "CC mus be ISD::SETNE or ISD::SETEQ");
16011 auto getV16i8Load = [&](
const SDValue &Operand) {
16029 LoadNode->getBasePtr(), NewMMO);
16070 SDValue LHSVec = getV16i8Load(
N->getOperand(0));
16071 SDValue RHSVec = getV16i8Load(
N->getOperand(1));
16074 DAG.
getConstant(Intrinsic::ppc_altivec_vcmpequb_p,
DL, MVT::i32);
16077 IntrID, CRSel, LHSVec, RHSVec);
16080 return DAG.
getSetCC(
DL,
N->getValueType(0), PredResult,
16098 auto IsAndWithOne = [](
SDValue &V) {
16109 auto IsCompareWithZero = [](
SDValue &V) {
16116 return (IsAndWithOne(
LHS) && IsCompareWithZero(
RHS)) ||
16117 (IsAndWithOne(
RHS) && IsCompareWithZero(
LHS));
16134 auto MakeXor1 = [&](
SDValue V) {
16135 EVT VT = V.getValueType();
16142 return MakeXor1(
LHS);
16145 return MakeXor1(
RHS);
16162 DAGCombinerInfo &DCI)
const {
16163 if (Subtarget.isISA3_1())
16166 EVT VT =
N->getValueType(0);
16167 if (VT != MVT::i32 && (VT != MVT::i64 || !Subtarget.isPPC64()))
16183 SelectionDAG &DAG = DCI.DAG;
16185 EVT XVT =
X.getValueType();
16189 MVT OpVT = Subtarget.isPPC64() ? MVT::i64 : MVT::i32;
16202 Addc, Addc, Carry);
16205 if (OpVT == MVT::i64 && VT == MVT::i32)
16212 DAGCombinerInfo &DCI)
const {
16214 "Should be called with a SETCC node");
16236 SelectionDAG &DAG = DCI.DAG;
16237 EVT VT =
N->getValueType(0);
16238 EVT OpVT =
LHS.getValueType();
16256 if (Subtarget.hasAltivec() &&
16261 return DAGCombineTruncBoolExt(
N, DCI);
16268 Op.getValueType() == MVT::f64;
16280combineElementTruncationToVectorTruncation(
SDNode *
N,
16281 DAGCombinerInfo &DCI)
const {
16283 "Should be called with a BUILD_VECTOR node");
16285 SelectionDAG &DAG = DCI.DAG;
16288 SDValue FirstInput =
N->getOperand(0);
16290 "The input operand must be an fp-to-int conversion.");
16295 if (FirstConversion == PPCISD::FCTIDZ ||
16296 FirstConversion == PPCISD::FCTIDUZ ||
16297 FirstConversion == PPCISD::FCTIWZ ||
16298 FirstConversion == PPCISD::FCTIWUZ) {
16299 bool IsSplat =
true;
16300 bool Is32Bit = FirstConversion == PPCISD::FCTIWZ ||
16301 FirstConversion == PPCISD::FCTIWUZ;
16304 EVT TargetVT =
N->getValueType(0);
16305 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
16306 SDValue NextOp =
N->getOperand(i);
16307 if (NextOp.
getOpcode() != PPCISD::MFVSR)
16310 if (NextConversion != FirstConversion)
16318 if (
N->getOperand(i) != FirstInput)
16329 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
16330 SDValue In =
N->getOperand(i).getOperand(0);
16340 Ops.push_back(Trunc);
16343 Ops.push_back(
In.isUndef() ? DAG.
getUNDEF(SrcVT) :
In.getOperand(0));
16347 if (FirstConversion == PPCISD::FCTIDZ ||
16348 FirstConversion == PPCISD::FCTIWZ)
16353 EVT NewVT = TargetVT == MVT::v2i64 ? MVT::v2f64 : MVT::v4f32;
16355 return DAG.
getNode(Opcode, dl, TargetVT, BV);
16373 static const APInt BasePattern =
APInt(128, 0x8000000000000000ULL) << 64;
16377 if (FullVal == BasePattern)
16378 return std::make_tuple(Uim,
uint8_t{0});
16381 if (FullVal ==
APInt(128, 1))
16382 return std::make_tuple(Uim,
uint8_t{127});
16384 return std::nullopt;
16404 "Expected a BuildVectorSDNode in combineBVLoadsSpecialValue");
16408 EVT VT =
Op.getValueType();
16409 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
16423 for (
const SDValue &Operand :
Op.getNode()->op_values()) {
16433 for (
unsigned Index = 0;
Index < NumElems; ++
Index) {
16437 uint64_t ElemValue =
C->getZExtValue();
16441 ElemValue &= ((1ULL << ElemBits) - 1);
16445 (IsLittleEndian) ? (Index * ElemBits) : (128 - (
Index + 1) * ElemBits);
16448 APInt ElemAPInt(128, ElemValue);
16449 ElemAPInt <<= BitPos;
16452 FullVal |= ElemAPInt;
16459 const auto &[Uim, ShiftAmount] = *UIMOpt;
16463 if (ShiftAmount == 0) {
16468 <<
"combineBVLoadsSpecialValue: Instruction Emitted ";
16469 LxvkqInstr.
dump());
16473 assert(ShiftAmount == 127 &&
"Unexpected lxvkq shift amount value");
16485 DAG.
getMachineNode(PPC::VSRQ, Dl, VT, ShiftAmountVec, ShiftAmountVec),
16488 <<
"\n combineBVLoadsSpecialValue: Instruction Emitted ";
16504 "Should be called with a BUILD_VECTOR node");
16509 if (!
N->getValueType(0).getVectorElementType().isByteSized())
16512 bool InputsAreConsecutiveLoads =
true;
16513 bool InputsAreReverseConsecutive =
true;
16514 unsigned ElemSize =
N->getValueType(0).getScalarType().getStoreSize();
16515 SDValue FirstInput =
N->getOperand(0);
16516 bool IsRoundOfExtLoad =
false;
16526 N->getNumOperands() == 1)
16529 if (!IsRoundOfExtLoad)
16534 for (
int i = 1, e =
N->getNumOperands(); i < e; ++i) {
16536 if (IsRoundOfExtLoad &&
N->getOperand(i).getOpcode() !=
ISD::FP_ROUND)
16539 SDValue NextInput = IsRoundOfExtLoad ?
N->getOperand(i).getOperand(0) :
16545 IsRoundOfExtLoad ?
N->getOperand(i-1).getOperand(0) :
N->getOperand(i-1);
16556 InputsAreConsecutiveLoads =
false;
16558 InputsAreReverseConsecutive =
false;
16561 if (!InputsAreConsecutiveLoads && !InputsAreReverseConsecutive)
16566 assert(!(InputsAreConsecutiveLoads && InputsAreReverseConsecutive) &&
16567 "The loads cannot be both consecutive and reverse consecutive.");
16571 if (InputsAreConsecutiveLoads) {
16572 assert(FirstLoad &&
"Input needs to be a LoadSDNode.");
16576 ReturnSDVal = WideLoad;
16577 }
else if (InputsAreReverseConsecutive) {
16579 assert(LastLoad &&
"Input needs to be a LoadSDNode.");
16584 for (
int i =
N->getNumOperands() - 1; i >= 0; i--)
16592 for (
auto *LD : InputLoads)
16594 return ReturnSDVal;
16605 unsigned NumElems =
Input.getValueType().getVectorNumElements();
16611 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16613 ShuffleMask[CorrectElems & 0xF] = Elems & 0xF;
16615 ShuffleMask[(CorrectElems & 0xF0) >> 4] = (Elems & 0xF0) >> 4;
16616 CorrectElems = CorrectElems >> 8;
16617 Elems = Elems >> 8;
16624 EVT VT =
N->getValueType(0);
16628 Input.getValueType().getVectorElementType(),
16662 auto isSExtOfVecExtract = [&](
SDValue Op) ->
bool {
16688 Elems = Elems << 8;
16697 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16698 if (!isSExtOfVecExtract(
N->getOperand(i))) {
16705 int TgtElemArrayIdx;
16706 int InputSize =
Input.getValueType().getScalarSizeInBits();
16707 int OutputSize =
N->getValueType(0).getScalarSizeInBits();
16708 if (InputSize + OutputSize == 40)
16709 TgtElemArrayIdx = 0;
16710 else if (InputSize + OutputSize == 72)
16711 TgtElemArrayIdx = 1;
16712 else if (InputSize + OutputSize == 48)
16713 TgtElemArrayIdx = 2;
16714 else if (InputSize + OutputSize == 80)
16715 TgtElemArrayIdx = 3;
16716 else if (InputSize + OutputSize == 96)
16717 TgtElemArrayIdx = 4;
16721 uint64_t CorrectElems = TargetElems[TgtElemArrayIdx];
16723 ? CorrectElems & 0x0F0F0F0F0F0F0F0F
16724 : CorrectElems & 0xF0F0F0F0F0F0F0F0;
16725 if (Elems != CorrectElems) {
16741 if (
N->getValueType(0) != MVT::v1i128)
16744 SDValue Operand =
N->getOperand(0);
16751 EVT MemoryType = LD->getMemoryVT();
16755 bool ValidLDType = MemoryType == MVT::i8 || MemoryType == MVT::i16 ||
16756 MemoryType == MVT::i32 || MemoryType == MVT::i64;
16759 if (!ValidLDType ||
16765 LD->getChain(), LD->getBasePtr(),
16769 DAG.
getVTList(MVT::v1i128, MVT::Other),
16770 LoadOps, MemoryType, LD->getMemOperand());
16774 DAGCombinerInfo &DCI)
const {
16776 "Should be called with a BUILD_VECTOR node");
16778 SelectionDAG &DAG = DCI.DAG;
16781 if (!Subtarget.hasVSX())
16788 if (FirstInput.
getOpcode() == PPCISD::MFVSR) {
16789 SDValue Reduced = combineElementTruncationToVectorTruncation(
N, DCI);
16804 if (Subtarget.hasP9Altivec() && !DCI.isBeforeLegalize()) {
16813 if (Subtarget.isISA3_1()) {
16819 if (
N->getValueType(0) != MVT::v2f64)
16830 if (FirstInput.
getOpcode() !=
N->getOperand(1).getOpcode())
16841 if (!Ext1Op || !Ext2Op)
16850 if (FirstElem == 0 && SecondElem == 1)
16851 SubvecIdx = Subtarget.isLittleEndian() ? 1 : 0;
16852 else if (FirstElem == 2 && SecondElem == 3)
16853 SubvecIdx = Subtarget.isLittleEndian() ? 0 : 1;
16859 PPCISD::SINT_VEC_TO_FP : PPCISD::UINT_VEC_TO_FP;
16860 return DAG.
getNode(NodeType, dl, MVT::v2f64,
16865 DAGCombinerInfo &DCI)
const {
16868 "Need an int -> FP conversion node here");
16873 SelectionDAG &DAG = DCI.DAG;
16879 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
16881 if (!
Op.getOperand(0).getValueType().isSimple())
16883 if (
Op.getOperand(0).getValueType().getSimpleVT() <= MVT(MVT::i1) ||
16884 Op.getOperand(0).getValueType().getSimpleVT() > MVT(MVT::i64))
16887 SDValue FirstOperand(
Op.getOperand(0));
16888 bool SubWordLoad = FirstOperand.getOpcode() ==
ISD::LOAD &&
16889 (FirstOperand.getValueType() == MVT::i8 ||
16890 FirstOperand.getValueType() == MVT::i16);
16891 if (Subtarget.hasP9Vector() && Subtarget.hasP9Altivec() && SubWordLoad) {
16893 bool DstDouble =
Op.getValueType() == MVT::f64;
16894 unsigned ConvOp =
Signed ?
16895 (DstDouble ? PPCISD::FCFID : PPCISD::FCFIDS) :
16896 (DstDouble ? PPCISD::FCFIDU : PPCISD::FCFIDUS);
16901 SDValue Ops[] = { LDN->getChain(), LDN->getBasePtr(), WidthConst };
16904 Ops, MVT::i8, LDN->getMemOperand());
16909 SDValue ExtOps[] = { Ld, WidthConst };
16911 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ext);
16913 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ld);
16921 if (
Op.getOperand(0).getValueType() == MVT::i32)
16925 "UINT_TO_FP is supported only with FPCVT");
16929 unsigned FCFOp = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16934 MVT FCFTy = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16941 Subtarget.hasFPCVT()) ||
16943 SDValue Src =
Op.getOperand(0).getOperand(0);
16944 if (Src.getValueType() == MVT::f32) {
16946 DCI.AddToWorklist(Src.getNode());
16947 }
else if (Src.getValueType() != MVT::f64) {
16959 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
16962 DCI.AddToWorklist(
FP.getNode());
16986 switch (
N->getOpcode()) {
16991 Chain = LD->getChain();
16992 Base = LD->getBasePtr();
16993 MMO = LD->getMemOperand();
17012 MVT VecTy =
N->getValueType(0).getSimpleVT();
17020 Chain =
Load.getValue(1);
17022 PPCISD::XXSWAPD, dl, DAG.
getVTList(MVT::v2f64, MVT::Other), Chain,
Load);
17026 if (VecTy != MVT::v2f64) {
17053 switch (
N->getOpcode()) {
17058 Chain = ST->getChain();
17059 Base = ST->getBasePtr();
17060 MMO = ST->getMemOperand();
17080 SDValue Src =
N->getOperand(SrcOpnd);
17081 MVT VecTy = Src.getValueType().getSimpleVT();
17084 if (VecTy != MVT::v2f64) {
17090 DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Src);
17096 StoreOps, VecTy, MMO);
17103 DAGCombinerInfo &DCI)
const {
17106 unsigned Opcode =
N->getOperand(1).getOpcode();
17108 bool Strict =
N->getOperand(1)->isStrictFPOpcode();
17112 &&
"Not a FP_TO_INT Instruction!");
17115 EVT Op1VT =
N->getOperand(1).getValueType();
17118 if (!Subtarget.hasVSX() || !Subtarget.hasFPCVT() || !
isTypeLegal(ResVT))
17122 bool ValidTypeForStoreFltAsInt =
17123 (Op1VT == MVT::i32 || (Op1VT == MVT::i64 && Subtarget.isPPC64()) ||
17124 (Subtarget.hasP9Vector() && (Op1VT == MVT::i16 || Op1VT == MVT::i8)));
17127 if (ResVT == MVT::ppcf128 || (ResVT == MVT::f128 && !Subtarget.hasP9Vector()))
17130 if ((Op1VT != MVT::i64 && !Subtarget.hasP8Vector()) ||
17138 SDValue Ops[] = {
N->getOperand(0), Val,
N->getOperand(2),
17153 bool PrevElemFromFirstVec = Mask[0] < NumElts;
17154 for (
int i = 1, e = Mask.size(); i < e; i++) {
17155 if (PrevElemFromFirstVec && Mask[i] < NumElts)
17157 if (!PrevElemFromFirstVec && Mask[i] >= NumElts)
17159 PrevElemFromFirstVec = !PrevElemFromFirstVec;
17170 for (
int i = 0, e =
Op.getNumOperands(); i < e; i++) {
17171 FirstOp =
Op.getOperand(i);
17177 for (
int i = 1, e =
Op.getNumOperands(); i < e; i++)
17178 if (
Op.getOperand(i) != FirstOp && !
Op.getOperand(i).isUndef())
17188 Op =
Op.getOperand(0);
17204 int RHSFirstElt,
int RHSLastElt,
int HalfVec,
unsigned LHSNumValidElts,
17205 unsigned RHSNumValidElts,
const PPCSubtarget &Subtarget) {
17207 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - LHSNumValidElts;
17209 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - RHSNumValidElts;
17210 for (
int I = 0,
E = ShuffV.
size();
I <
E; ++
I) {
17211 int Idx = ShuffV[
I];
17212 if (Idx >= LHSFirstElt && Idx <= LHSLastElt)
17213 ShuffV[
I] += LHSEltFixup;
17214 else if (Idx >= RHSFirstElt && Idx <= RHSLastElt)
17215 ShuffV[
I] += RHSEltFixup;
17226 SDLoc dl(OrigSToV);
17229 "Expecting a SCALAR_TO_VECTOR here");
17242 "Cannot produce a permuted scalar_to_vector for one element vector");
17244 unsigned ResultInElt = NumElts / 2;
17250 return DAG.
getNode(PPCISD::SCALAR_TO_VECTOR_PERMUTED, dl, VT,
17255 int HalfVec,
int LHSLastElementDefined,
17256 int RHSLastElementDefined) {
17257 for (
int Index : ShuffV) {
17261 if ((LHSLastElementDefined >= 0) && (Index < HalfVec) &&
17262 (Index > LHSLastElementDefined))
17265 if ((RHSLastElementDefined >= 0) &&
17266 (Index > HalfVec + RHSLastElementDefined))
17273 int ScalarSize,
uint64_t ShuffleEltWidth,
unsigned &NumValidElts,
17274 int FirstElt,
int &LastElt,
SDValue VecShuffOperand,
SDValue SToVNode,
17290 LastElt = (
uint64_t)ScalarSize > ShuffleEltWidth
17291 ? ScalarSize / ShuffleEltWidth - 1 + FirstElt
17294 if (SToVPermuted.
getValueType() != VecShuffOperandType)
17295 SToVPermuted = DAG.
getBitcast(VecShuffOperandType, SToVPermuted);
17296 return SToVPermuted;
17316 int NumElts =
LHS.getValueType().getVectorNumElements();
17319 bool IsLittleEndian = Subtarget.isLittleEndian();
17326 if (!Subtarget.hasDirectMove())
17346 SmallVector<int, 16> ShuffV(Mask);
17349 if (SToVLHS || SToVRHS) {
17352 int ShuffleNumElts = ShuffV.
size();
17353 int HalfVec = ShuffleNumElts / 2;
17359 unsigned LHSNumValidElts = HalfVec;
17360 unsigned RHSNumValidElts = HalfVec;
17365 int LHSFirstElt = 0;
17366 int RHSFirstElt = ShuffleNumElts;
17367 int LHSLastElt = -1;
17368 int RHSLastElt = -1;
17376 int LHSScalarSize = 0;
17377 int RHSScalarSize = 0;
17380 if (!IsLittleEndian && LHSScalarSize >= 64)
17385 if (!IsLittleEndian && RHSScalarSize >= 64)
17388 if (LHSScalarSize != 0)
17390 LHSScalarSize, ShuffleEltWidth, LHSNumValidElts, LHSFirstElt,
17391 LHSLastElt,
LHS, SToVLHS, DAG, Subtarget);
17392 if (RHSScalarSize != 0)
17394 RHSScalarSize, ShuffleEltWidth, RHSNumValidElts, RHSFirstElt,
17395 RHSLastElt,
RHS, SToVRHS, DAG, Subtarget);
17406 ShuffV, LHSFirstElt, LHSLastElt, RHSFirstElt, RHSLastElt, HalfVec,
17407 LHSNumValidElts, RHSNumValidElts, Subtarget);
17433 if (IsLittleEndian) {
17436 if (Mask[0] < NumElts)
17437 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17441 ShuffV[i] = (ShuffV[i - 1] >= 0 ? ShuffV[i - 1] : 0) + NumElts;
17446 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17450 ShuffV[i] = (ShuffV[i + 1] >= 0 ? ShuffV[i + 1] : 0) + NumElts;
17455 if (Mask[0] < NumElts)
17456 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17460 ShuffV[i] = ShuffV[i + 1] >= 0 ? ShuffV[i + 1] - NumElts : 0;
17465 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17469 ShuffV[i] = ShuffV[i - 1] >= 0 ? ShuffV[i - 1] - NumElts : 0;
17479 if (IsLittleEndian)
17488 DAGCombinerInfo &DCI)
const {
17490 "Not a reverse memop pattern!");
17492 auto IsElementReverse = [](
const ShuffleVectorSDNode *SVN) ->
bool {
17495 auto I =
Mask.rbegin();
17496 auto E =
Mask.rend();
17498 for (;
I !=
E; ++
I) {
17506 SelectionDAG &DAG = DCI.DAG;
17509 if (!
isTypeLegal(VT) || !Subtarget.isLittleEndian() || !Subtarget.hasVSX())
17515 if (!Subtarget.hasP9Vector())
17518 if(!IsElementReverse(SVN))
17525 for (SDUse &Use : LSBase->
uses())
17526 if (
Use.getResNo() == 0 &&
17533 PPCISD::LOAD_VEC_BE, dl, DAG.
getVTList(VT, MVT::Other), LoadOps,
17548 PPCISD::STORE_VEC_BE, dl, DAG.
getVTList(MVT::Other), StoreOps,
17557 if (IntrinsicID == Intrinsic::ppc_stdcx)
17559 else if (IntrinsicID == Intrinsic::ppc_stwcx)
17561 else if (IntrinsicID == Intrinsic::ppc_sthcx)
17563 else if (IntrinsicID == Intrinsic::ppc_stbcx)
17572 if (
N->getOpcode() == PPCISD::ADDC &&
N->hasAnyUseOfValue(1)) {
17576 if (
LHS->getOpcode() == PPCISD::ADDE &&
17587 if (
N->getOpcode() == PPCISD::SUBE) {
17593 if (
LHS ==
RHS &&
LHS.getOpcode() == PPCISD::ADDC) {
17596 if (AddcLHS.
getOpcode() == PPCISD::ADDE &&
17618 SDValue CmpLHS =
N->getOperand(0);
17619 SDValue CmpRHS =
N->getOperand(1);
17620 SDValue TrueVal =
N->getOperand(2);
17621 SDValue FalseVal =
N->getOperand(3);
17635 if (FalseVal.getOpcode() !=
ISD::SRL || !FalseVal.hasOneUse())
17638 SDValue ShiftVal = FalseVal.getOperand(0);
17639 SDValue ShiftAmt = FalseVal.getOperand(1);
17643 if (!ShiftConst || !ShiftConst->getAPIntValue().isMinSignedValue())
17670 if (CtlzArg != CmpLHS)
17678 DAG.
getNode(PPCISD::SRL,
DL, FalseVal.getValueType(), ShiftVal, ShiftAmt);
17725 auto isZeroOrOne = [=](
SDValue &V) {
17727 V.getConstantOperandVal(0) == Intrinsic::ppc_test_data_class)
17732 if (!isZeroOrOne(NonNullConstant))
17742 EVT VType =
N->getValueType(0);
17746 return NewNonNullConstant;
17765 EVT XorVT =
N->getValueType(0);
17766 if ((XorVT != MVT::i32 && XorVT != MVT::i64))
17774 if (!XorConst || !XorConst->
isOne()) {
17776 if (!XorConst || !XorConst->
isOne())
17783 if (!
LHS.hasOneUse())
17791 SelectNode =
LHS.getOperand(0);
17805 if (MachineOpc != PPC::SELECT_CC_I4 && MachineOpc != PPC::SELECT_CC_I8)
17815 if (!ConstOp1 || !ConstOp2)
17819 if (!((ConstOp1->
isOne() && ConstOp2->
isZero()) ||
17828 MachineOpc = (XorVT == MVT::i32) ? PPC::SELECT_CC_I4 : PPC::SELECT_CC_I8;
17830 bool ConstOp1IsOne = ConstOp1->
isOne();
17833 {SelectNode.getOperand(0),
17834 DAG.getConstant(ConstOp1IsOne ? 0 : 1, DL, XorVT),
17835 DAG.getConstant(ConstOp1IsOne ? 1 : 0, DL, XorVT),
17836 SelectNode.getOperand(3)}),
17844 switch (
N->getOpcode()) {
17847 return combineADD(
N, DCI);
17879 return combineSHL(
N, DCI);
17881 return combineSRA(
N, DCI);
17883 return combineSRL(
N, DCI);
17885 return combineMUL(
N, DCI);
17887 case PPCISD::FNMSUB:
17888 return combineFMALike(
N, DCI);
17891 return N->getOperand(0);
17895 return N->getOperand(0);
17901 return N->getOperand(0);
17905 if (
SDValue SECC = combineSignExtendSetCC(
N, DCI))
17913 return DAGCombineExtBoolTrunc(
N, DCI);
17915 return combineTRUNCATE(
N, DCI);
17917 if (
SDValue CSCC = combineSetCC(
N, DCI))
17923 return DAGCombineTruncBoolExt(
N, DCI);
17926 return combineFPToIntToFP(
N, DCI);
17935 EVT Op1VT =
N->getOperand(1).getValueType();
17936 unsigned Opcode =
N->getOperand(1).getOpcode();
17940 SDValue Val = combineStoreFPToInt(
N, DCI);
17954 N->getOperand(1).getNode()->hasOneUse() &&
17955 (Op1VT == MVT::i32 || Op1VT == MVT::i16 ||
17956 (Subtarget.hasLDBRX() && Subtarget.isPPC64() && Op1VT == MVT::i64))) {
17964 SDValue BSwapOp =
N->getOperand(1).getOperand(0);
17971 if (Op1VT.
bitsGT(mVT)) {
17976 if (Op1VT == MVT::i64)
17981 N->getOperand(0), BSwapOp,
N->getOperand(2), DAG.
getValueType(mVT)
18001 ST->getBasePtr(), ST->getOffset(), MemVT,
18002 ST->getMemOperand(), ST->getAddressingMode(),
18006 return ST->isUnindexed()
18015 if (Subtarget.needsSwapsForVSXMemOps() &&
18016 (StoreVT == MVT::v2f64 || StoreVT == MVT::v2i64 ||
18017 StoreVT == MVT::v4f32 || StoreVT == MVT::v4i32))
18024 EVT VT = LD->getValueType(0);
18030 if (Subtarget.needsSwapsForVSXMemOps() &&
18031 (LoadVT == MVT::v2f64 || LoadVT == MVT::v2i64 ||
18032 LoadVT == MVT::v4f32 || LoadVT == MVT::v4i32))
18043 auto ReplaceTwoFloatLoad = [&]() {
18044 if (VT != MVT::i64)
18059 if (!LD->hasNUsesOfValue(2, 0))
18062 auto UI = LD->user_begin();
18063 while (UI.getUse().getResNo() != 0) ++UI;
18065 while (UI.getUse().getResNo() != 0) ++UI;
18066 SDNode *RightShift = *UI;
18074 if (RightShift->getOpcode() !=
ISD::SRL ||
18076 RightShift->getConstantOperandVal(1) != 32 ||
18077 !RightShift->hasOneUse())
18080 SDNode *Trunc2 = *RightShift->user_begin();
18090 Bitcast->getValueType(0) != MVT::f32)
18096 if (Subtarget.isLittleEndian())
18102 SDValue BasePtr = LD->getBasePtr();
18103 if (LD->isIndexed()) {
18105 "Non-pre-inc AM on PPC?");
18113 SDValue FloatLoad = DAG.
getLoad(MVT::f32, dl, LD->getChain(), BasePtr,
18114 LD->getPointerInfo(), LD->getAlign(),
18115 MMOFlags, LD->getAAInfo());
18121 LD->getPointerInfo().getWithOffset(4),
18124 if (LD->isIndexed()) {
18138 if (ReplaceTwoFloatLoad())
18141 EVT MemVT = LD->getMemoryVT();
18144 if (LD->isUnindexed() && VT.
isVector() &&
18147 !Subtarget.hasP8Vector() &&
18148 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
18149 VT == MVT::v4f32))) &&
18150 LD->getAlign() < ABIAlignment) {
18152 SDValue Chain = LD->getChain();
18153 SDValue Ptr = LD->getBasePtr();
18154 bool isLittleEndian = Subtarget.isLittleEndian();
18181 MVT PermCntlTy, PermTy, LDTy;
18182 Intr = isLittleEndian ? Intrinsic::ppc_altivec_lvsr
18183 : Intrinsic::ppc_altivec_lvsl;
18184 IntrLD = Intrinsic::ppc_altivec_lvx;
18185 IntrPerm = Intrinsic::ppc_altivec_vperm;
18186 PermCntlTy = MVT::v16i8;
18187 PermTy = MVT::v4i32;
18206 SDValue BaseLoadOps[] = { Chain, LDXIntID, Ptr };
18210 BaseLoadOps, LDTy, BaseMMO);
18219 int IncValue = IncOffset;
18236 SDValue ExtraLoadOps[] = { Chain, LDXIntID, Ptr };
18240 ExtraLoadOps, LDTy, ExtraMMO);
18251 if (isLittleEndian)
18253 ExtraLoad, BaseLoad, PermCntl, DAG, dl);
18256 BaseLoad, ExtraLoad, PermCntl, DAG, dl);
18259 Perm = Subtarget.hasAltivec()
18274 bool isLittleEndian = Subtarget.isLittleEndian();
18275 unsigned IID =
N->getConstantOperandVal(0);
18276 Intrinsic::ID Intr = (isLittleEndian ? Intrinsic::ppc_altivec_lvsr
18277 : Intrinsic::ppc_altivec_lvsl);
18278 if (IID == Intr &&
N->getOperand(1)->getOpcode() ==
ISD::ADD) {
18285 .zext(
Add.getScalarValueSizeInBits()))) {
18286 SDNode *BasePtr =
Add->getOperand(0).getNode();
18287 for (
SDNode *U : BasePtr->users()) {
18289 U->getConstantOperandVal(0) == IID) {
18300 SDNode *BasePtr =
Add->getOperand(0).getNode();
18301 for (
SDNode *U : BasePtr->users()) {
18304 (
Add->getConstantOperandVal(1) - U->getConstantOperandVal(1)) %
18310 V->getConstantOperandVal(0) == IID) {
18322 (IID == Intrinsic::ppc_altivec_vmaxsw ||
18323 IID == Intrinsic::ppc_altivec_vmaxsh ||
18324 IID == Intrinsic::ppc_altivec_vmaxsb)) {
18327 if ((
V1.getSimpleValueType() == MVT::v4i32 ||
18328 V1.getSimpleValueType() == MVT::v8i16 ||
18329 V1.getSimpleValueType() == MVT::v16i8) &&
18334 V1.getOperand(1) == V2) {
18355 switch (
N->getConstantOperandVal(1)) {
18358 case Intrinsic::ppc_altivec_vsum4sbs:
18359 case Intrinsic::ppc_altivec_vsum4shs:
18360 case Intrinsic::ppc_altivec_vsum4ubs: {
18367 APInt APSplatBits, APSplatUndef;
18368 unsigned SplatBitSize;
18371 APSplatBits, APSplatUndef, SplatBitSize, HasAnyUndefs, 0,
18372 !Subtarget.isLittleEndian());
18374 if (BVNIsConstantSplat && APSplatBits == 0)
18379 case Intrinsic::ppc_vsx_lxvw4x:
18380 case Intrinsic::ppc_vsx_lxvd2x:
18383 if (Subtarget.needsSwapsForVSXMemOps())
18391 if (Subtarget.needsSwapsForVSXMemOps()) {
18392 switch (
N->getConstantOperandVal(1)) {
18395 case Intrinsic::ppc_vsx_stxvw4x:
18396 case Intrinsic::ppc_vsx_stxvd2x:
18405 bool Is64BitBswapOn64BitTgt =
18406 Subtarget.isPPC64() &&
N->getValueType(0) == MVT::i64;
18408 N->getOperand(0).hasOneUse();
18409 if (IsSingleUseNormalLd &&
18410 (
N->getValueType(0) == MVT::i32 ||
N->getValueType(0) == MVT::i16 ||
18411 (Subtarget.hasLDBRX() && Is64BitBswapOn64BitTgt))) {
18422 DAG.
getVTList(
N->getValueType(0) == MVT::i64 ?
18423 MVT::i64 : MVT::i32, MVT::Other),
18424 Ops, LD->getMemoryVT(), LD->getMemOperand());
18428 if (
N->getValueType(0) == MVT::i16)
18445 !IsSingleUseNormalLd)
18450 if (!LD->isSimple())
18452 SDValue BasePtr = LD->getBasePtr();
18454 LD->getPointerInfo(), LD->getAlign());
18459 LD->getMemOperand(), 4, 4);
18463 if (Subtarget.isLittleEndian())
18469 Hi.getOperand(0).getValue(1),
Lo.getOperand(0).getValue(1));
18478 if (!
N->getOperand(0).hasOneUse() &&
18479 !
N->getOperand(1).hasOneUse() &&
18480 !
N->getOperand(2).hasOneUse()) {
18483 SDNode *VCMPrecNode =
nullptr;
18485 SDNode *LHSN =
N->getOperand(0).getNode();
18487 if (
User->getOpcode() == PPCISD::VCMP_rec &&
18491 VCMPrecNode =
User;
18503 SDNode *FlagUser =
nullptr;
18505 FlagUser ==
nullptr; ++UI) {
18506 assert(UI != VCMPrecNode->
use_end() &&
"Didn't find user!");
18519 return SDValue(VCMPrecNode, 0);
18530 SDValue LHS =
N->getOperand(2), RHS =
N->getOperand(3);
18541 auto RHSAPInt = RHS->getAsAPIntVal();
18542 if (!RHSAPInt.isIntN(64))
18545 unsigned Val = RHSAPInt.getZExtValue();
18546 auto isImpossibleCompare = [&]() {
18549 if (Val != 0 && Val != 1) {
18551 return N->getOperand(0);
18554 N->getOperand(0),
N->getOperand(4));
18559 unsigned StoreWidth = 0;
18562 if (
SDValue Impossible = isImpossibleCompare())
18574 SDValue Ops[] = {LHS.getOperand(0), LHS.getOperand(2), LHS.getOperand(3),
18578 PPCISD::STORE_COND, dl,
18580 MemNode->getMemoryVT(), MemNode->getMemOperand());
18584 if (
N->getOperand(0) == LHS.getValue(1))
18595 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other, InChain,
18597 DAG.
getRegister(PPC::CR0, MVT::i32),
N->getOperand(4),
18603 assert(isDot &&
"Can't compare against a vector result!");
18605 if (
SDValue Impossible = isImpossibleCompare())
18608 bool BranchOnWhenPredTrue = (CC ==
ISD::SETEQ) ^ (Val == 0);
18615 EVT VTs[] = { LHS.getOperand(2).getValueType(), MVT::Glue };
18620 switch (LHS.getConstantOperandVal(1)) {
18636 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other,
N->getOperand(0),
18639 N->getOperand(4), CompNode.
getValue(1));
18644 return DAGCombineBuildVector(
N, DCI);
18651 return DAGCombineBitcast(
N, DCI);
18662 EVT VT =
N->getValueType(0);
18663 if (VT == MVT::i64 && !Subtarget.isPPC64())
18665 if ((VT != MVT::i32 && VT != MVT::i64) ||
18673 unsigned Lg2 = (IsNegPow2 ? -Divisor : Divisor).
countr_zero();
18693 const APInt &DemandedElts,
18695 unsigned Depth)
const {
18697 switch (
Op.getOpcode()) {
18699 case PPCISD::LBRX: {
18702 Known.Zero = 0xFFFF0000;
18705 case PPCISD::ADDE: {
18706 if (
Op.getResNo() == 0) {
18711 Known.Zero = ~1ULL;
18716 switch (
Op.getConstantOperandVal(0)) {
18718 case Intrinsic::ppc_altivec_vcmpbfp_p:
18719 case Intrinsic::ppc_altivec_vcmpeqfp_p:
18720 case Intrinsic::ppc_altivec_vcmpequb_p:
18721 case Intrinsic::ppc_altivec_vcmpequh_p:
18722 case Intrinsic::ppc_altivec_vcmpequw_p:
18723 case Intrinsic::ppc_altivec_vcmpequd_p:
18724 case Intrinsic::ppc_altivec_vcmpequq_p:
18725 case Intrinsic::ppc_altivec_vcmpgefp_p:
18726 case Intrinsic::ppc_altivec_vcmpgtfp_p:
18727 case Intrinsic::ppc_altivec_vcmpgtsb_p:
18728 case Intrinsic::ppc_altivec_vcmpgtsh_p:
18729 case Intrinsic::ppc_altivec_vcmpgtsw_p:
18730 case Intrinsic::ppc_altivec_vcmpgtsd_p:
18731 case Intrinsic::ppc_altivec_vcmpgtsq_p:
18732 case Intrinsic::ppc_altivec_vcmpgtub_p:
18733 case Intrinsic::ppc_altivec_vcmpgtuh_p:
18734 case Intrinsic::ppc_altivec_vcmpgtuw_p:
18735 case Intrinsic::ppc_altivec_vcmpgtud_p:
18736 case Intrinsic::ppc_altivec_vcmpgtuq_p:
18743 switch (
Op.getConstantOperandVal(1)) {
18746 case Intrinsic::ppc_load2r:
18748 Known.Zero = 0xFFFF0000;
18757 switch (Subtarget.getCPUDirective()) {
18779 if (
ML->getLoopDepth() > 1 &&
ML->getSubLoops().empty())
18788 for (
auto I =
ML->block_begin(), IE =
ML->block_end();
I != IE; ++
I)
18790 LoopSize +=
TII->getInstSizeInBytes(J);
18795 if (LoopSize > 16 && LoopSize <= 32)
18809 if (Constraint.
size() == 1) {
18810 switch (Constraint[0]) {
18828 }
else if (Constraint ==
"wc") {
18830 }
else if (Constraint ==
"wa" || Constraint ==
"wd" ||
18831 Constraint ==
"wf" || Constraint ==
"ws" ||
18832 Constraint ==
"wi" || Constraint ==
"ww") {
18845 Value *CallOperandVal =
info.CallOperandVal;
18848 if (!CallOperandVal)
18855 else if ((
StringRef(constraint) ==
"wa" ||
18867 switch (*constraint) {
18897std::pair<unsigned, const TargetRegisterClass *>
18901 if (Constraint.
size() == 1) {
18903 switch (Constraint[0]) {
18905 if (VT == MVT::i64 && Subtarget.isPPC64())
18906 return std::make_pair(0U, &PPC::G8RC_NOX0RegClass);
18907 return std::make_pair(0U, &PPC::GPRC_NOR0RegClass);
18909 if (VT == MVT::i64 && Subtarget.isPPC64())
18910 return std::make_pair(0U, &PPC::G8RCRegClass);
18911 return std::make_pair(0U, &PPC::GPRCRegClass);
18917 if (Subtarget.hasSPE()) {
18918 if (VT == MVT::f32 || VT == MVT::i32)
18919 return std::make_pair(0U, &PPC::GPRCRegClass);
18920 if (VT == MVT::f64 || VT == MVT::i64)
18921 return std::make_pair(0U, &PPC::SPERCRegClass);
18923 if (VT == MVT::f32 || VT == MVT::i32)
18924 return std::make_pair(0U, &PPC::F4RCRegClass);
18925 if (VT == MVT::f64 || VT == MVT::i64)
18926 return std::make_pair(0U, &PPC::F8RCRegClass);
18930 if (Subtarget.hasAltivec() && VT.
isVector())
18931 return std::make_pair(0U, &PPC::VRRCRegClass);
18932 else if (Subtarget.hasVSX())
18934 return std::make_pair(0U, &PPC::VFRCRegClass);
18937 return std::make_pair(0U, &PPC::CRRCRegClass);
18939 }
else if (Constraint ==
"wc" && Subtarget.useCRBits()) {
18941 return std::make_pair(0U, &PPC::CRBITRCRegClass);
18942 }
else if ((Constraint ==
"wa" || Constraint ==
"wd" ||
18943 Constraint ==
"wf" || Constraint ==
"wi") &&
18944 Subtarget.hasVSX()) {
18948 return std::make_pair(0U, &PPC::VSRCRegClass);
18949 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18950 return std::make_pair(0U, &PPC::VSSRCRegClass);
18951 return std::make_pair(0U, &PPC::VSFRCRegClass);
18952 }
else if ((Constraint ==
"ws" || Constraint ==
"ww") && Subtarget.hasVSX()) {
18953 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18954 return std::make_pair(0U, &PPC::VSSRCRegClass);
18956 return std::make_pair(0U, &PPC::VSFRCRegClass);
18957 }
else if (Constraint ==
"lr") {
18958 if (VT == MVT::i64)
18959 return std::make_pair(0U, &PPC::LR8RCRegClass);
18961 return std::make_pair(0U, &PPC::LRRCRegClass);
18966 if (Constraint[0] ==
'{' && Constraint[Constraint.
size() - 1] ==
'}') {
18970 if (Constraint.
size() > 3 && Constraint[1] ==
'v' && Constraint[2] ==
's') {
18971 int VSNum = atoi(Constraint.
data() + 3);
18972 assert(VSNum >= 0 && VSNum <= 63 &&
18973 "Attempted to access a vsr out of range");
18975 return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass);
18976 return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass);
18981 if (Constraint.
size() > 3 && Constraint[1] ==
'f') {
18982 int RegNum = atoi(Constraint.
data() + 2);
18983 if (RegNum > 31 || RegNum < 0)
18985 if (VT == MVT::f32 || VT == MVT::i32)
18986 return Subtarget.hasSPE()
18987 ? std::make_pair(PPC::R0 + RegNum, &PPC::GPRCRegClass)
18988 : std::make_pair(PPC::F0 + RegNum, &PPC::F4RCRegClass);
18989 if (VT == MVT::f64 || VT == MVT::i64)
18990 return Subtarget.hasSPE()
18991 ? std::make_pair(PPC::S0 + RegNum, &PPC::SPERCRegClass)
18992 : std::make_pair(PPC::F0 + RegNum, &PPC::F8RCRegClass);
18996 std::pair<unsigned, const TargetRegisterClass *> R =
19005 if (R.first && VT == MVT::i64 && Subtarget.isPPC64() &&
19006 PPC::GPRCRegClass.contains(R.first))
19007 return std::make_pair(
TRI->getMatchingSuperReg(R.first,
19008 PPC::sub_32, &PPC::G8RCRegClass),
19009 &PPC::G8RCRegClass);
19012 if (!R.second &&
StringRef(
"{cc}").equals_insensitive(Constraint)) {
19013 R.first = PPC::CR0;
19014 R.second = &PPC::CRRCRegClass;
19018 if (Subtarget.isAIXABI() && !TM.getAIXExtendedAltivecABI()) {
19019 if (((R.first >= PPC::V20 && R.first <= PPC::V31) ||
19020 (R.first >= PPC::VF20 && R.first <= PPC::VF31)) &&
19021 (R.second == &PPC::VSRCRegClass || R.second == &PPC::VSFRCRegClass))
19022 errs() <<
"warning: vector registers 20 to 32 are reserved in the "
19023 "default AIX AltiVec ABI and cannot be used\n";
19033 std::vector<SDValue> &
Ops,
19038 if (Constraint.
size() > 1)
19041 char Letter = Constraint[0];
19056 EVT TCVT = MVT::i64;
19097 if (Result.getNode()) {
19098 Ops.push_back(Result);
19109 if (
I.getNumOperands() <= 1)
19113 auto IntrinsicID =
Ops[1].getNode()->getAsZExtVal();
19114 if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw &&
19115 IntrinsicID != Intrinsic::ppc_trapd && IntrinsicID != Intrinsic::ppc_trap)
19118 if (
MDNode *MDN =
I.getMetadata(LLVMContext::MD_annotation))
19134 if (Ty->isVectorTy() && AM.
BaseOffs != 0 && !Subtarget.hasP9Vector())
19146 switch (AM.
Scale) {
19174 unsigned Depth =
Op.getConstantOperandVal(0);
19198 SDValue RetAddrFI = getReturnAddrFrameIndex(DAG);
19206 unsigned Depth =
Op.getConstantOperandVal(0);
19213 bool isPPC64 = PtrVT == MVT::i64;
19219 FrameReg = isPPC64 ? PPC::X1 : PPC::R1;
19221 FrameReg = isPPC64 ? PPC::FP8 : PPC::FP;
19227 FrameAddr, MachinePointerInfo());
19231#define GET_REGISTER_MATCHER
19232#include "PPCGenAsmMatcher.inc"
19236 bool IsPPC64 = Subtarget.isPPC64();
19248 if ((IsPPC64 && Reg == PPC::R2) || Reg == PPC::R0)
19254 Reg = Reg.id() - PPC::R0 + PPC::X0;
19261 if (Subtarget.is32BitELFABI())
19266 if (Subtarget.isAIXABI())
19280 return Subtarget.isGVIndirectSymbol(
G->getGlobal());
19296 case Intrinsic::ppc_atomicrmw_xchg_i128:
19297 case Intrinsic::ppc_atomicrmw_add_i128:
19298 case Intrinsic::ppc_atomicrmw_sub_i128:
19299 case Intrinsic::ppc_atomicrmw_nand_i128:
19300 case Intrinsic::ppc_atomicrmw_and_i128:
19301 case Intrinsic::ppc_atomicrmw_or_i128:
19302 case Intrinsic::ppc_atomicrmw_xor_i128:
19303 case Intrinsic::ppc_cmpxchg_i128:
19305 Info.memVT = MVT::i128;
19306 Info.ptrVal =
I.getArgOperand(0);
19308 Info.align =
Align(16);
19313 case Intrinsic::ppc_atomic_load_i128:
19315 Info.memVT = MVT::i128;
19316 Info.ptrVal =
I.getArgOperand(0);
19318 Info.align =
Align(16);
19322 case Intrinsic::ppc_atomic_store_i128:
19324 Info.memVT = MVT::i128;
19325 Info.ptrVal =
I.getArgOperand(2);
19327 Info.align =
Align(16);
19331 case Intrinsic::ppc_altivec_lvx:
19332 case Intrinsic::ppc_altivec_lvxl:
19333 case Intrinsic::ppc_altivec_lvebx:
19334 case Intrinsic::ppc_altivec_lvehx:
19335 case Intrinsic::ppc_altivec_lvewx:
19336 case Intrinsic::ppc_vsx_lxvd2x:
19337 case Intrinsic::ppc_vsx_lxvw4x:
19338 case Intrinsic::ppc_vsx_lxvd2x_be:
19339 case Intrinsic::ppc_vsx_lxvw4x_be:
19340 case Intrinsic::ppc_vsx_lxvl:
19341 case Intrinsic::ppc_vsx_lxvll: {
19344 case Intrinsic::ppc_altivec_lvebx:
19347 case Intrinsic::ppc_altivec_lvehx:
19350 case Intrinsic::ppc_altivec_lvewx:
19353 case Intrinsic::ppc_vsx_lxvd2x:
19354 case Intrinsic::ppc_vsx_lxvd2x_be:
19364 Info.ptrVal =
I.getArgOperand(0);
19367 Info.align =
Align(1);
19372 case Intrinsic::ppc_altivec_stvx:
19373 case Intrinsic::ppc_altivec_stvxl:
19374 case Intrinsic::ppc_altivec_stvebx:
19375 case Intrinsic::ppc_altivec_stvehx:
19376 case Intrinsic::ppc_altivec_stvewx:
19377 case Intrinsic::ppc_vsx_stxvd2x:
19378 case Intrinsic::ppc_vsx_stxvw4x:
19379 case Intrinsic::ppc_vsx_stxvd2x_be:
19380 case Intrinsic::ppc_vsx_stxvw4x_be:
19381 case Intrinsic::ppc_vsx_stxvl:
19382 case Intrinsic::ppc_vsx_stxvll: {
19385 case Intrinsic::ppc_altivec_stvebx:
19388 case Intrinsic::ppc_altivec_stvehx:
19391 case Intrinsic::ppc_altivec_stvewx:
19394 case Intrinsic::ppc_vsx_stxvd2x:
19395 case Intrinsic::ppc_vsx_stxvd2x_be:
19405 Info.ptrVal =
I.getArgOperand(1);
19408 Info.align =
Align(1);
19413 case Intrinsic::ppc_stdcx:
19414 case Intrinsic::ppc_stwcx:
19415 case Intrinsic::ppc_sthcx:
19416 case Intrinsic::ppc_stbcx: {
19418 auto Alignment =
Align(8);
19420 case Intrinsic::ppc_stdcx:
19423 case Intrinsic::ppc_stwcx:
19425 Alignment =
Align(4);
19427 case Intrinsic::ppc_sthcx:
19429 Alignment =
Align(2);
19431 case Intrinsic::ppc_stbcx:
19433 Alignment =
Align(1);
19438 Info.ptrVal =
I.getArgOperand(0);
19440 Info.align = Alignment;
19454 const AttributeList &FuncAttributes)
const {
19458 if (Subtarget.hasAltivec() &&
Op.size() >= 16) {
19459 if (
Op.isMemset() && Subtarget.hasVSX()) {
19464 if (TailSize > 2 && TailSize <= 4) {
19469 if (
Op.isAligned(
Align(16)) || Subtarget.hasP8Vector())
19474 if (Subtarget.isPPC64()) {
19485 assert(Ty->isIntegerTy());
19487 unsigned BitSize = Ty->getPrimitiveSizeInBits();
19488 return !(BitSize == 0 || BitSize > 64);
19496 return NumBits1 == 64 && NumBits2 == 32;
19504 return NumBits1 == 64 && NumBits2 == 32;
19511 EVT MemVT = LD->getMemoryVT();
19512 if ((MemVT == MVT::i1 || MemVT == MVT::i8 || MemVT == MVT::i16 ||
19513 (Subtarget.isPPC64() && MemVT == MVT::i32)) &&
19529 "invalid fpext types");
19531 if (DestVT == MVT::f128)
19546 unsigned *
Fast)
const {
19560 !Subtarget.allowsUnalignedFPAccess())
19564 if (Subtarget.hasVSX()) {
19565 if (VT != MVT::v2f64 && VT != MVT::v2i64 &&
19566 VT != MVT::v4f32 && VT != MVT::v4i32)
19573 if (VT == MVT::ppcf128)
19588 if (!ConstNode->getAPIntValue().isSignedIntN(64))
19596 int64_t Imm = ConstNode->getSExtValue();
19617 if (Subtarget.hasSPE() || Subtarget.useSoftFloat())
19619 switch (Ty->getScalarType()->getTypeID()) {
19624 return Subtarget.hasP9Vector();
19632 if (!
I->hasOneUse())
19636 assert(
User &&
"A single use instruction with no uses.");
19638 switch (
I->getOpcode()) {
19639 case Instruction::FMul: {
19641 if (
User->getOpcode() != Instruction::FSub &&
19642 User->getOpcode() != Instruction::FAdd)
19649 bool AllowContract =
I->getFastMathFlags().allowContract() &&
19650 User->getFastMathFlags().allowContract();
19656 case Instruction::Load: {
19669 if (
User->getOpcode() != Instruction::Store)
19689 static const MCPhysReg ScratchRegs[] = {
19690 PPC::X12, PPC::LR8, PPC::CTR8, 0
19693 return ScratchRegs;
19697 const Constant *PersonalityFn)
const {
19698 return Subtarget.isPPC64() ? PPC::X3 : PPC::R3;
19702 const Constant *PersonalityFn)
const {
19703 return Subtarget.isPPC64() ? PPC::X4 : PPC::R4;
19708 EVT VT ,
unsigned DefinedValues)
const {
19709 if (VT == MVT::v2i64)
19710 return Subtarget.hasDirectMove();
19712 if (Subtarget.hasVSX())
19739 return PPCISD::FNMSUB;
19740 case PPCISD::FNMSUB:
19746 bool LegalOps,
bool OptForSize,
19748 unsigned Depth)
const {
19752 unsigned Opc =
Op.getOpcode();
19753 EVT VT =
Op.getValueType();
19757 case PPCISD::FNMSUB:
19777 if (Flags.hasNoSignedZeros()) {
19781 N0Cost,
Depth + 1);
19785 N1Cost,
Depth + 1);
19787 if (NegN0 && N0Cost <= N1Cost) {
19788 Cost = std::min(N0Cost, N2Cost);
19790 }
else if (NegN1) {
19791 Cost = std::min(N1Cost, N2Cost);
19811 if (M.getStackProtectorGuard() ==
"tls" || Subtarget.isTargetLinux())
19817 bool ForCodeSize)
const {
19818 if (!VT.
isSimple() || !Subtarget.hasVSX())
19828 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
19833 APSInt IntResult(16,
false);
19838 if (IsExact && IntResult <= 15 && IntResult >= -16)
19840 return Imm.isZero();
19843 return Imm.isPosZero();
19855 unsigned Opcode =
N->getOpcode();
19875 if (Mask->getZExtValue() == OpSizeInBits - 1)
19882 DAGCombinerInfo &DCI)
const {
19883 EVT VT =
N->getValueType(0);
19886 unsigned Opc =
N->getOpcode();
19888 "Unexpected opcode.");
19895 if (EltTy != MVT::i64 && EltTy != MVT::i32)
19899 uint64_t SplatBits = 0;
19900 bool AddSplatCase =
false;
19904 AddSplatCase =
true;
19908 if (!AddSplatCase) {
19912 unsigned SplatBitSize;
19914 APInt APSplatBits, APSplatUndef;
19916 bool BVNIsConstantSplat =
19918 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
19919 if (!BVNIsConstantSplat || SplatBitSize != EltBits)
19930 if (SplatBits == (EltBits - 1)) {
19934 NewOpc = PPCISD::SHL;
19937 NewOpc = PPCISD::SRL;
19940 NewOpc = PPCISD::SRA;
19944 return DCI.DAG.getNode(NewOpc,
DL, VT, N0, SplatOnes);
19952 if (EltTy != MVT::i64 || SplatBits != 1)
19955 return DCI.DAG.getNode(
ISD::ADD, SDLoc(
N), VT, N0, N0);
19958SDValue PPCTargetLowering::combineSHL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19962 if (
N->getValueType(0).isVector())
19963 return combineVectorShift(
N, DCI);
19967 if (!Subtarget.isISA3_0() || !Subtarget.isPPC64() ||
19970 N->getValueType(0) != MVT::i64)
19985 ShiftBy = DCI.DAG.getConstant(CN1->
getZExtValue(),
DL, MVT::i32);
19991SDValue PPCTargetLowering::combineSRA(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19995 if (
N->getValueType(0).isVector())
19996 return combineVectorShift(
N, DCI);
20001SDValue PPCTargetLowering::combineSRL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20005 if (
N->getValueType(0).isVector())
20006 return combineVectorShift(
N, DCI);
20017 if (!Subtarget.isPPC64())
20023 auto isZextOfCompareWithConstant = [](
SDValue Op) {
20025 Op.getValueType() != MVT::i64)
20029 if (Cmp.getOpcode() !=
ISD::SETCC || !Cmp.hasOneUse() ||
20030 Cmp.getOperand(0).getValueType() != MVT::i64)
20034 int64_t NegConstant = 0 -
Constant->getSExtValue();
20043 bool LHSHasPattern = isZextOfCompareWithConstant(
LHS);
20044 bool RHSHasPattern = isZextOfCompareWithConstant(
RHS);
20047 if (LHSHasPattern && !RHSHasPattern)
20049 else if (!LHSHasPattern && !RHSHasPattern)
20053 EVT CarryType = Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
20056 SDValue Z = Cmp.getOperand(0);
20058 int64_t NegConstant = 0 -
Constant->getSExtValue();
20071 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
20089 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
20119 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
20122 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
20130 if (!GSDN || !ConstNode)
20158 EVT VT =
N->getValueType(0);
20159 if (!Subtarget.hasVSX())
20163 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
20175 unsigned NumOfEles =
RHS.getNumOperands();
20176 for (
unsigned i = 0; i < NumOfEles; ++i) {
20178 if (!CN || CN->getSExtValue() != 1)
20193SDValue PPCTargetLowering::combineADD(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20215 DAGCombinerInfo &DCI)
const {
20217 if (Subtarget.useCRBits()) {
20219 if (
SDValue CRTruncValue = DAGCombineTruncBoolExt(
N, DCI))
20220 return CRTruncValue;
20227 if (Op0.
getValueType() != MVT::i128 ||
N->getValueType(0) != MVT::i64)
20230 int EltToExtract = DCI.DAG.getDataLayout().isBigEndian() ? 1 : 0;
20240 EltToExtract = EltToExtract ? 0 : 1;
20250 return DCI.DAG.getNode(
20252 DCI.DAG.getTargetConstant(EltToExtract, dl, MVT::i32));
20257SDValue PPCTargetLowering::combineMUL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20258 SelectionDAG &DAG = DCI.DAG;
20261 if (!ConstOpOrElement)
20269 auto IsProfitable = [
this](
bool IsNeg,
bool IsAddOne, EVT VT) ->
bool {
20270 switch (this->Subtarget.getCPUDirective()) {
20293 return IsAddOne && IsNeg ? VT.
isVector() :
true;
20297 EVT VT =
N->getValueType(0);
20302 APInt MulAmtAbs = MulAmt.
abs();
20304 if ((MulAmtAbs - 1).isPowerOf2()) {
20308 if (!IsProfitable(IsNeg,
true, VT))
20321 }
else if ((MulAmtAbs + 1).isPowerOf2()) {
20325 if (!IsProfitable(IsNeg,
false, VT))
20346 DAGCombinerInfo &DCI)
const {
20350 SDNodeFlags
Flags =
N->getFlags();
20351 EVT VT =
N->getValueType(0);
20352 SelectionDAG &DAG = DCI.DAG;
20353 unsigned Opc =
N->getOpcode();
20355 bool LegalOps = !DCI.isBeforeLegalizeOps();
20363 if (!
Flags.hasNoSignedZeros())
20379bool PPCTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
20381 if (!Subtarget.is64BitELFABI())
20391 if (!TM.Options.GuaranteedTailCallOpt &&
DisableSCO)
20396 if (!Callee ||
Callee->isVarArg())
20409bool PPCTargetLowering::
20410isMaskAndCmp0FoldingBeneficial(
const Instruction &AndI)
const {
20415 if (CI->getBitWidth() > 64)
20417 int64_t ConstVal = CI->getZExtValue();
20419 (
isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF));
20428PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(
unsigned Flags)
const {
20434 if ((Flags & FlagSet) == FlagSet)
20437 if ((Flags & FlagSet) == FlagSet)
20440 if ((Flags & FlagSet) == FlagSet)
20443 if ((Flags & FlagSet) == FlagSet)
20464 if ((FrameIndexAlign % 4) != 0)
20465 FlagSet &=
~PPC::MOF_RPlusSImm16Mult4;
20466 if ((FrameIndexAlign % 16) != 0)
20467 FlagSet &=
~PPC::MOF_RPlusSImm16Mult16;
20471 if ((FrameIndexAlign % 4) == 0)
20473 if ((FrameIndexAlign % 16) == 0)
20486 auto SetAlignFlagsForImm = [&](
uint64_t Imm) {
20487 if ((Imm & 0x3) == 0)
20489 if ((Imm & 0xf) == 0)
20495 const APInt &ConstImm = CN->getAPIntValue();
20514 const APInt &ConstImm = CN->getAPIntValue();
20524 }
else if (
RHS.getOpcode() == PPCISD::Lo && !
RHS.getConstantOperandVal(1))
20535 return (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR ||
20544unsigned PPCTargetLowering::computeMOFlags(
const SDNode *Parent,
SDValue N,
20549 if (!Subtarget.hasP9Vector())
20554 if (Subtarget.hasPrefixInstrs())
20557 if (Subtarget.hasSPE())
20566 unsigned ParentOp = Parent->
getOpcode();
20570 if ((
ID == Intrinsic::ppc_vsx_lxvp) || (
ID == Intrinsic::ppc_vsx_stxvp)) {
20571 SDValue IntrinOp = (
ID == Intrinsic::ppc_vsx_lxvp)
20583 if (LSB->isIndexed())
20589 assert(MN &&
"Parent should be a MemSDNode!");
20594 "Not expecting scalar integers larger than 16 bytes!");
20597 else if (
Size == 32)
20604 else if (
Size == 256) {
20605 assert(Subtarget.pairedVectorMemops() &&
20606 "256-bit vectors are only available when paired vector memops is "
20614 else if (MemVT == MVT::f128 || MemVT.
isVector())
20645 FlagSet &= ~PPC::MOF_NoExt;
20650 bool IsNonP1034BitConst =
20654 IsNonP1034BitConst)
20667 int16_t ForceXFormImm = 0;
20670 Disp =
N.getOperand(0);
20671 Base =
N.getOperand(1);
20682 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
20683 Disp =
N.getOperand(0);
20684 Base =
N.getOperand(1);
20689 Disp = DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20698 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
20704 if (PartVT == MVT::f64 &&
20705 (ValVT == MVT::i32 || ValVT == MVT::i16 || ValVT == MVT::i8)) {
20714SDValue PPCTargetLowering::lowerToLibCall(
const char *LibCallName,
SDValue Op,
20718 EVT RetVT =
Op.getValueType();
20725 EVT ArgVT =
N.getValueType();
20729 Entry.IsZExt = !Entry.IsSExt;
20730 Args.push_back(Entry);
20738 (RetTy ==
F.getReturnType() ||
F.getReturnType()->isVoidTy());
20751SDValue PPCTargetLowering::lowerLibCallBasedOnType(
20752 const char *LibCallFloatName,
const char *LibCallDoubleName,
SDValue Op,
20754 if (
Op.getValueType() == MVT::f32)
20755 return lowerToLibCall(LibCallFloatName,
Op, DAG);
20757 if (
Op.getValueType() == MVT::f64)
20758 return lowerToLibCall(LibCallDoubleName,
Op, DAG);
20763bool PPCTargetLowering::isLowringToMASSFiniteSafe(
SDValue Op)
const {
20764 SDNodeFlags
Flags =
Op.getNode()->getFlags();
20765 return isLowringToMASSSafe(
Op) &&
Flags.hasNoSignedZeros() &&
20769bool PPCTargetLowering::isLowringToMASSSafe(
SDValue Op)
const {
20770 return Op.getNode()->getFlags().hasApproximateFuncs();
20773bool PPCTargetLowering::isScalarMASSConversionEnabled()
const {
20777SDValue PPCTargetLowering::lowerLibCallBase(
const char *LibCallDoubleName,
20778 const char *LibCallFloatName,
20779 const char *LibCallDoubleNameFinite,
20780 const char *LibCallFloatNameFinite,
20783 if (!isScalarMASSConversionEnabled() || !isLowringToMASSSafe(
Op))
20786 if (!isLowringToMASSFiniteSafe(
Op))
20787 return lowerLibCallBasedOnType(LibCallFloatName, LibCallDoubleName,
Op,
20790 return lowerLibCallBasedOnType(LibCallFloatNameFinite,
20791 LibCallDoubleNameFinite,
Op, DAG);
20795 return lowerLibCallBase(
"__xl_pow",
"__xl_powf",
"__xl_pow_finite",
20796 "__xl_powf_finite",
Op, DAG);
20800 return lowerLibCallBase(
"__xl_sin",
"__xl_sinf",
"__xl_sin_finite",
20801 "__xl_sinf_finite",
Op, DAG);
20805 return lowerLibCallBase(
"__xl_cos",
"__xl_cosf",
"__xl_cos_finite",
20806 "__xl_cosf_finite",
Op, DAG);
20810 return lowerLibCallBase(
"__xl_log",
"__xl_logf",
"__xl_log_finite",
20811 "__xl_logf_finite",
Op, DAG);
20815 return lowerLibCallBase(
"__xl_log10",
"__xl_log10f",
"__xl_log10_finite",
20816 "__xl_log10f_finite",
Op, DAG);
20820 return lowerLibCallBase(
"__xl_exp",
"__xl_expf",
"__xl_exp_finite",
20821 "__xl_expf_finite",
Op, DAG);
20846 unsigned Flags = computeMOFlags(Parent,
N, DAG);
20857 assert(Subtarget.isUsingPCRelativeCalls() &&
20858 "Must be using PC-Relative calls when a valid PC-Relative node is "
20888 Disp =
N.getOperand(1).getOperand(0);
20893 Base =
N.getOperand(0);
20901 EVT CNType = CN->getValueType(0);
20902 uint64_t CNImm = CN->getZExtValue();
20913 if ((CNType == MVT::i32 ||
isInt<32>(CNImm)) &&
20915 int32_t Addr = (int32_t)CNImm;
20920 uint32_t LIS = CNType == MVT::i32 ? PPC::LIS : PPC::LIS8;
20936 unsigned Opcode =
N.getOpcode();
20944 Base =
N.getOperand(0);
20963 Base = FI ?
N :
N.getOperand(1);
20964 Disp = FI ? DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20975 bool IsVarArg)
const {
20985 return Subtarget.isPPC64() && Subtarget.hasQuadwordAtomics();
21022 return Intrinsic::ppc_atomicrmw_xchg_i128;
21024 return Intrinsic::ppc_atomicrmw_add_i128;
21026 return Intrinsic::ppc_atomicrmw_sub_i128;
21028 return Intrinsic::ppc_atomicrmw_and_i128;
21030 return Intrinsic::ppc_atomicrmw_or_i128;
21032 return Intrinsic::ppc_atomicrmw_xor_i128;
21034 return Intrinsic::ppc_atomicrmw_nand_i128;
21042 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21046 Value *IncrLo = Builder.CreateTrunc(Incr, Int64Ty,
"incr_lo");
21048 Builder.CreateTrunc(Builder.CreateLShr(Incr, 64), Int64Ty,
"incr_hi");
21049 Value *LoHi = Builder.CreateIntrinsic(
21051 {AlignedAddr, IncrLo, IncrHi});
21052 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21053 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21054 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
21055 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
21056 return Builder.CreateOr(
21057 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
21064 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21070 Value *CmpLo = Builder.CreateTrunc(CmpVal, Int64Ty,
"cmp_lo");
21072 Builder.CreateTrunc(Builder.CreateLShr(CmpVal, 64), Int64Ty,
"cmp_hi");
21073 Value *NewLo = Builder.CreateTrunc(NewVal, Int64Ty,
"new_lo");
21075 Builder.CreateTrunc(Builder.CreateLShr(NewVal, 64), Int64Ty,
"new_hi");
21078 Builder.CreateCall(IntCmpXchg, {AlignedAddr, CmpLo, CmpHi, NewLo, NewHi});
21080 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21081 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21082 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
21083 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
21084 return Builder.CreateOr(
21085 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
21089 return Subtarget.useCRBits();
21094bool PPCTargetLowering::isShuffleMaskLegal(
ArrayRef<int> Mask,
EVT VT)
const {
21105 DAGCombinerInfo &DCI)
const {
21110 EVT ResVT =
N->getValueType(0);
21112 EVT SrcVT = Src.getValueType();
21117 if (ResVT != MVT::i16 && ResVT != MVT::i8)
21120 GenerateVBPERM(DAG, dl, Src, SrcVT, TruncResVT, IsLittleEndian);
21133 bool IsV16i8 = (ResVT == MVT::v16i1 && SrcVT == MVT::v16i8);
21134 bool IsV8i16 = (ResVT == MVT::v8i1 && SrcVT == MVT::v8i16);
21135 bool IsV8i8 = (ResVT == MVT::v8i1 && SrcVT == MVT::v8i8);
21137 if (!IsV16i8 && !IsV8i16 && !IsV8i8)
21145 SmallVector<int, 16> BitIndices(16, 128);
21149 BitIndices[Idx] = EltSize * (NumElts - Idx) - 1;
21150 if (IsV8i8 && IsLE)
21151 BitIndices[Idx] += 64;
21154 std::reverse(BitIndices.begin(), BitIndices.end());
21156 for (
auto Idx : BitIndices)
21161 DAG.
getConstant(Intrinsic::ppc_altivec_vbpermq, dl, MVT::i32),
21169 bool BVNIsConstantSplat,
21170 unsigned SplatBitSize)
const {
21172 if (!BVNIsConstantSplat || !Subtarget.hasVSX() || !Subtarget.hasP8Vector() ||
21173 Subtarget.hasP10Vector())
21176 EVT VT =
Op->getValueType(0);
21177 if (!((SplatBitSize == 64 && VT == MVT::v2f64) ||
21178 (SplatBitSize == 32 && VT == MVT::v4f32)))
21185 APFloat APFloatVal = CN->getValueAPF();
21187 APSInt IntResult(16,
false);
21190 if (!(IsExact && IntResult <= 15 && IntResult >= -16 && !APFloatVal.
isZero()))
21193 int64_t
IntVal = IntResult.getSExtValue();
21198 if (SplatBitSize == 64)
21201 DAG.
getConstant(Intrinsic::ppc_vsx_xvcvsxwdp, dl, MVT::i32), IntSplat);
21203 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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
This file defines the DenseMap class.
const HexagonInstrInfo * TII
static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl)
CreateCopyOfByValArgument - Make a copy of an aggregate at address specified by "Src" to address "Dst...
Module.h This file contains the declarations for the Module class.
This defines the Use class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static bool isConstantOrUndef(const SDValue Op)
MachineInstr unsigned OpIdx
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
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.
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
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.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
bool isJumpTableRelative() const override
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
LowerOperation - Provide custom lowering hooks for some operations.
PPC::AddrMode SelectOptimalAddrMode(const SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG, MaybeAlign Align) const
SelectOptimalAddrMode - Based on a node N and it's Parent (a MemSDNode), compute the address flags of...
bool SelectAddressPCRel(SDValue N, SDValue &Base) const
SelectAddressPCRel - Represent the specified address as pc relative to be represented as [pc+imm].
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the ISD::SETCC ValueType
bool SelectAddressEVXRegReg(SDValue N, SDValue &Base, SDValue &Index, SelectionDAG &DAG) const
SelectAddressEVXRegReg - Given the specified addressed, check to see if it can be more efficiently re...
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
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(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Wrapper class representing virtual and physical registers.
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...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
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 getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
const DataLayout & getDataLayout() const
SDValue getTargetFrameIndex(int FI, EVT VT)
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const
Return true if loads are next to each other and can be merged.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI SDValue getMDNode(const MDNode *MD)
Return an MDNodeSDNode which holds an MDNode.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
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 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.