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()) {
823 if (Subtarget.hasAltivec()) {
824 for (
MVT VT : { MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
841 if (VT.getSizeInBits() <= 128 && VT.getScalarSizeInBits() <= 64) {
854 if (Subtarget.hasVSX()) {
863 if (Subtarget.hasP8Altivec() && (VT.SimpleTy != MVT::v1i128)) {
873 if (Subtarget.hasP9Altivec() && (VT.SimpleTy != MVT::v1i128))
947 if (!Subtarget.hasP8Vector()) {
989 if (Subtarget.hasAltivec())
990 for (
auto VT : {MVT::v4i32, MVT::v8i16, MVT::v16i8})
993 if (Subtarget.hasP8Altivec())
1004 if (Subtarget.hasVSX()) {
1010 if (Subtarget.hasP8Altivec())
1015 if (Subtarget.isISA3_1()) {
1061 if (Subtarget.hasVSX()) {
1064 if (Subtarget.hasP8Vector()) {
1068 if (Subtarget.hasDirectMove() && isPPC64) {
1117 if (Subtarget.hasP8Vector())
1126 if (Subtarget.hasP8Altivec()) {
1153 if (Subtarget.isISA3_1())
1256 if (Subtarget.hasP8Altivec()) {
1261 if (Subtarget.hasP9Vector()) {
1265 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,
11966 uint64_t RHSC =
Op.getConstantOperandVal(1);
11969 EVT VT =
LHS.getValueType();
11971 assert((VT == MVT::f32 || VT == MVT::f64 ||
11972 ((VT == MVT::f128 || VT == MVT::ppcf128) && Subtarget.hasVSX() &&
11973 Subtarget.useCRBits())) &&
11974 "invalid customize type for IS_FPCLASS.");
11976 if (VT == MVT::ppcf128) {
11984 if (Subtarget.hasP9Vector() && Subtarget.useCRBits()) {
11993 if ((Category & ~
fcNan) && (Category != ~
fcNan)) {
12001 if (Subtarget.hasVSX()) {
12004 if (VT == MVT::f32) {
12006 }
else if (VT != MVT::f64) {
12009 CmpOp = PPC::XSCMPUDP;
12014 if (VT == MVT::f64) {
12015 CmpOp = PPC::FCMPUD;
12016 }
else if (VT == MVT::f32) {
12017 CmpOp = PPC::FCMPUS;
12031 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Cmp,
12036 return DAG.
getNOT(Dl, NanCheck, MVT::i1);
12054 bool Future = Subtarget.isISAFuture();
12057 "Mask predication not supported");
12060 unsigned IID = Future ? Intrinsic::ppc_vsx_lxvrl : Intrinsic::ppc_vsx_lxvl;
12061 unsigned EltBits =
Op->getValueType(0).getScalarType().getSizeInBits();
12065 SDVTList Tys = DAG.
getVTList(
Op->getValueType(0), MVT::Other);
12068 VPLD->getMemoryVT(), VPLD->getMemOperand());
12075 "Mask predication not supported");
12080 Op->getOperand(1).getValueType().getScalarType().getSizeInBits();
12081 bool Future = Subtarget.isISAFuture();
12082 unsigned IID = Future ? Intrinsic::ppc_vsx_stxvrl : Intrinsic::ppc_vsx_stxvl;
12085 VPST->getChain(), DAG.
getConstant(IID, dl, MVT::i32),
12088 SDVTList Tys = DAG.
getVTList(MVT::Other);
12091 VPST->getMemoryVT(), VPST->getMemOperand());
12102 "Unexpected partial reduction");
12125 unsigned EltSize =
Op.getValueType().getScalarSizeInBits();
12127 int64_t
IntVal =
Op.getConstantOperandVal(0);
12128 if (IntVal >= -16 && IntVal <= 15)
12134 if (Subtarget.hasLFIWAX() && Subtarget.hasVSX() &&
12139 MachineMemOperand *MMO =
12141 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
12144 PPCISD::LD_SPLAT, dl, DAG.
getVTList(MVT::v4i32, MVT::Other),
Ops,
12148 return Bits.getValue(0);
12164 !Subtarget.isLittleEndian() && ValVT.
isInteger() &&
12169 64 -
Op.getValueType().getScalarSizeInBits(), dl, ShiftAmountTy);
12177 MachinePointerInfo());
12184 return DAG.
getLoad(
Op.getValueType(), dl,
Store, FIdx, MachinePointerInfo());
12190 "Should only be called for ISD::INSERT_VECTOR_ELT");
12194 EVT VT =
Op.getValueType();
12199 if (VT == MVT::v2f64 &&
C)
12202 if (Subtarget.hasP9Vector()) {
12211 if ((VT == MVT::v4f32) && (V2.
getValueType() == MVT::f32) &&
12217 BitcastLoad,
Op.getOperand(2));
12218 return DAG.
getBitcast(MVT::v4f32, InsVecElt);
12222 if (Subtarget.isISA3_1()) {
12223 if ((VT == MVT::v2i64 || VT == MVT::v2f64) && !Subtarget.isPPC64())
12227 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
12228 VT == MVT::v2i64 || VT == MVT::v4f32 || VT == MVT::v2f64)
12238 if (VT == MVT::v8i16 || VT == MVT::v16i8) {
12241 unsigned InsertAtElement =
C->getZExtValue();
12242 unsigned InsertAtByte = InsertAtElement * BytesInEachElement;
12243 if (Subtarget.isLittleEndian()) {
12244 InsertAtByte = (16 - BytesInEachElement) - InsertAtByte;
12246 return DAG.
getNode(PPCISD::VECINSERT, dl, VT,
V1, Mtvsrz,
12258 EVT VT =
Op.getValueType();
12259 bool IsV1024i1 = VT == MVT::v1024i1;
12260 bool IsV2048i1 = VT == MVT::v2048i1;
12264 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12266 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12267 "Dense Math support required.");
12268 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12277 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12278 MachineMemOperand *NewMMO =
12286 DAG.
getVTList(MVT::v256i1, MVT::Other),
12287 LoadOps, MVT::v256i1, NewMMO);
12292 if (Subtarget.isLittleEndian()) {
12293 std::reverse(Loads.
begin(), Loads.
end());
12294 std::reverse(LoadChains.
begin(), LoadChains.
end());
12306 SDValue Dmr1Value = DMFInsert1024(MoreLoads, dl, DAG);
12312 const SDValue DmrPOps[] = {DmrPRC,
Value, Dmr0Sub, Dmr1Value, Dmr1Sub};
12315 DAG.
getMachineNode(PPC::REG_SEQUENCE, dl, MVT::v2048i1, DmrPOps), 0);
12324 DAG.
getNode(PPCISD::INST512, dl, MVT::v512i1, Pairs[0], Pairs[1]);
12327 DAG.
getNode(PPCISD::INST512HI, dl, MVT::v512i1, Pairs[2], Pairs[3]);
12332 {RC, Lo, LoSub, Hi, HiSub}),
12342 EVT VT =
Op.getValueType();
12344 if (VT == MVT::v1024i1 || VT == MVT::v2048i1)
12345 return LowerDMFVectorLoad(
Op, DAG);
12347 if (VT != MVT::v256i1 && VT != MVT::v512i1)
12351 assert((VT != MVT::v512i1 || Subtarget.hasMMA()) &&
12352 "Type unsupported without MMA");
12353 assert((VT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12354 "Type unsupported without paired vector support");
12358 if (VT == MVT::v256i1 && Subtarget.isISAFuture())
12367 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12369 DAG.
getLoad(MVT::v16i8, dl, LoadChain, BasePtr,
12378 if (Subtarget.isLittleEndian()) {
12379 std::reverse(Loads.
begin(), Loads.
end());
12380 std::reverse(LoadChains.
begin(), LoadChains.
end());
12384 DAG.
getNode(VT == MVT::v512i1 ? PPCISD::ACC_BUILD : PPCISD::PAIR_BUILD,
12400 bool IsV1024i1 = VT == MVT::v1024i1;
12401 bool IsV2048i1 = VT == MVT::v2048i1;
12405 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12407 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12408 "Dense Math support required.");
12409 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12411 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12414 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12419 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12423 MachineSDNode *ExtNode =
12427 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes,
Hi);
12433 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12439 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12445 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12450 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12455 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12460 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12464 MachineSDNode *ExtNode =
12465 DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr0Lo);
12469 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr0Hi);
12472 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr1Lo);
12476 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr1Hi);
12481 if (Subtarget.isLittleEndian())
12484 SDVTList Tys = DAG.
getVTList(MVT::Other);
12486 StoreChain, DAG.
getConstant(Intrinsic::ppc_vsx_stxvp, dl, MVT::i32),
12490 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12491 MachineMemOperand *NewMMO =
12500 MVT::v256i1, NewMMO);
12516 EVT StoreVT =
Value.getValueType();
12518 if (StoreVT == MVT::v1024i1 || StoreVT == MVT::v2048i1)
12519 return LowerDMFVectorStore(
Op, DAG);
12521 if (StoreVT != MVT::v256i1 && StoreVT != MVT::v512i1)
12525 assert((StoreVT != MVT::v512i1 || Subtarget.hasMMA()) &&
12526 "Type unsupported without MMA");
12527 assert((StoreVT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12528 "Type unsupported without paired vector support");
12532 if (StoreVT == MVT::v256i1 && Subtarget.isISAFuture() &&
12540 unsigned NumVecs = 2;
12541 if (StoreVT == MVT::v512i1) {
12542 if (Subtarget.isISAFuture()) {
12543 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12545 PPC::DMXXEXTFDMR512, dl, ReturnTypes,
Op.getOperand(1));
12548 Value2 =
SDValue(ExtNode, 1);
12553 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12554 unsigned VecNum = Subtarget.isLittleEndian() ? NumVecs - 1 - Idx : Idx;
12556 if (Subtarget.isISAFuture()) {
12557 VecNum = Subtarget.isLittleEndian() ? 1 - (Idx % 2) : (Idx % 2);
12558 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
12559 Idx > 1 ? Value2 :
Value,
12562 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
Value,
12566 DAG.
getStore(StoreChain, dl, Elt, BasePtr,
12580 if (
Op.getValueType() == MVT::v4i32) {
12597 LHS,
RHS, DAG, dl, MVT::v4i32);
12600 LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32);
12605 }
else if (
Op.getValueType() == MVT::v16i8) {
12607 bool isLittleEndian = Subtarget.isLittleEndian();
12611 LHS,
RHS, DAG, dl, MVT::v8i16);
12616 LHS,
RHS, DAG, dl, MVT::v8i16);
12624 for (
unsigned i = 0; i != 8; ++i) {
12625 if (isLittleEndian) {
12627 Ops[i*2+1] = 2*i+16;
12630 Ops[i*2+1] = 2*i+1+16;
12633 if (isLittleEndian)
12643 bool IsStrict =
Op->isStrictFPOpcode();
12644 if (
Op.getOperand(IsStrict ? 1 : 0).getValueType() == MVT::f128 &&
12645 !Subtarget.hasP9Vector())
12655 "Should only be called for ISD::FP_EXTEND");
12659 if (
Op.getValueType() != MVT::v2f64 ||
12660 Op.getOperand(0).getValueType() != MVT::v2f32)
12672 "Node should have 2 operands with second one being a constant!");
12684 int DWord = Idx >> 1;
12687 if (Subtarget.isLittleEndian())
12690 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64,
12704 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12706 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12707 LD->getMemoryVT(),
LD->getMemOperand());
12712 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewOp,
12717 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12719 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12720 LD->getMemoryVT(),
LD->getMemOperand());
12721 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewLd,
12732 if (STI.useCRBits())
12749 PPCISD::ADDE,
DL, DAG.
getVTList(SumType, MVT::i32), Zero, Zero, Flag);
12750 if (STI.useCRBits())
12758 SDNode *
N =
Op.getNode();
12759 EVT VT =
N->getValueType(0);
12760 EVT CarryType =
N->getValueType(1);
12761 unsigned Opc =
N->getOpcode();
12763 Opc = IsAdd ? PPCISD::ADDC : PPCISD::SUBC;
12765 N->getOperand(0),
N->getOperand(1));
12777 SDNode *
N =
Op.getNode();
12778 unsigned Opc =
N->getOpcode();
12779 EVT VT =
N->getValueType(0);
12780 EVT CarryType =
N->getValueType(1);
12781 SDValue CarryOp =
N->getOperand(2);
12783 Opc = IsAdd ? PPCISD::ADDE : PPCISD::SUBE;
12789 Op.getOperand(0),
Op.getOperand(1), CarryOp);
12803 EVT VT =
Op.getNode()->getValueType(0);
12829 EVT VT =
Op.getNode()->getValueType(0);
12861 EVT OpVT =
LHS.getValueType();
12862 EVT VT =
Op.getValueType();
12877 unsigned Opcode = PPCISD::SUBC;
12887 Opcode = PPCISD::ADDC;
12894 if (Subtarget.isPPC64() && OpVT != MVT::i64) {
12901 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12921 EVT OpVT =
A.getValueType();
12922 EVT ResVT =
Op.getValueType();
12927 if (Subtarget.isPPC64() && OpVT != MVT::i64) {
12937 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12955 switch (
Op.getOpcode()) {
12976 return LowerSSUBO(
Op, DAG);
12978 return LowerSADDO(
Op, DAG);
12990 return LowerGET_DYNAMIC_AREA_OFFSET(
Op, DAG);
13011 return LowerSET_ROUNDING(
Op, DAG);
13018 case ISD::FSHL:
return LowerFunnelShift(
Op, DAG);
13019 case ISD::FSHR:
return LowerFunnelShift(
Op, DAG);
13031 return LowerFP_ROUND(
Op, DAG);
13045 return LowerINTRINSIC_VOID(
Op, DAG);
13047 return LowerBSWAP(
Op, DAG);
13049 return LowerATOMIC_CMP_SWAP(
Op, DAG);
13051 return LowerATOMIC_LOAD_STORE(
Op, DAG);
13053 return LowerIS_FPCLASS(
Op, DAG);
13056 return LowerADDSUBO(
Op, DAG);
13059 return LowerADDSUBO_CARRY(
Op, DAG);
13061 return LowerUCMP(
Op, DAG);
13063 return LowerABDU(
Op, DAG);
13069 if (
Op->getFlags().hasNoFPExcept())
13073 return LowerVP_LOAD(
Op, DAG);
13074 case ISD::VP_STORE:
13075 return LowerVP_STORE(
Op, DAG);
13077 return LowerPartialReduce(
Op, DAG);
13085 switch (
N->getOpcode()) {
13087 llvm_unreachable(
"Do not know how to custom type legalize this operation!");
13104 if (
N->getConstantOperandVal(1) != Intrinsic::loop_decrement)
13107 assert(
N->getValueType(0) == MVT::i1 &&
13108 "Unexpected result type for CTR decrement intrinsic");
13110 N->getValueType(0));
13120 switch (
N->getConstantOperandVal(0)) {
13121 case Intrinsic::ppc_pack_longdouble:
13123 N->getOperand(2),
N->getOperand(1)));
13125 case Intrinsic::ppc_maxfe:
13126 case Intrinsic::ppc_minfe:
13127 case Intrinsic::ppc_fnmsub:
13128 case Intrinsic::ppc_convert_f128_to_ppcf128:
13135 if (!Subtarget.isSVR4ABI() || Subtarget.isPPC64())
13138 EVT VT =
N->getValueType(0);
13140 if (VT == MVT::i64) {
13153 if (
N->getOperand(
N->isStrictFPOpcode() ? 1 : 0).getValueType() ==
13157 Results.push_back(LoweredValue);
13158 if (
N->isStrictFPOpcode())
13163 if (!
N->getValueType(0).isVector())
13196 return Builder.CreateIntrinsicWithoutFolding(Id, {});
13202 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
13204 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
13205 "Only 8/16/32/64-bit atomic loads supported");
13211 IntID = Intrinsic::ppc_lbarx;
13212 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13215 IntID = Intrinsic::ppc_lharx;
13216 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13219 IntID = Intrinsic::ppc_lwarx;
13222 IntID = Intrinsic::ppc_ldarx;
13226 Builder.CreateIntrinsic(IntID, Addr,
nullptr,
"larx");
13228 return Builder.CreateTruncOrBitCast(
Call, ValueTy);
13239 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
13240 "Only 8/16/32/64-bit atomic loads supported");
13246 IntID = Intrinsic::ppc_stbcx;
13247 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13250 IntID = Intrinsic::ppc_sthcx;
13251 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13254 IntID = Intrinsic::ppc_stwcx;
13257 IntID = Intrinsic::ppc_stdcx;
13261 if (SZ == 8 || SZ == 16)
13262 Val = Builder.CreateZExt(Val, Builder.getInt32Ty());
13264 Value *
Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
13266 return Builder.CreateXor(
Call, Builder.getInt32(1));
13289 return Builder.CreateIntrinsicWithoutFolding(Intrinsic::ppc_cfence,
13299 unsigned BinOpcode,
13300 unsigned CmpOpcode,
13301 unsigned CmpPred)
const {
13306 unsigned AtomicSize =
MI.getOperand(3).getImm();
13308 auto LoadMnemonic = PPC::LDARX;
13309 auto StoreMnemonic = PPC::STDCX;
13310 switch (AtomicSize) {
13314 LoadMnemonic = PPC::LBARX;
13315 StoreMnemonic = PPC::STBCX;
13316 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13319 LoadMnemonic = PPC::LHARX;
13320 StoreMnemonic = PPC::STHCX;
13321 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13324 LoadMnemonic = PPC::LWARX;
13325 StoreMnemonic = PPC::STWCX;
13328 LoadMnemonic = PPC::LDARX;
13329 StoreMnemonic = PPC::STDCX;
13337 if (CmpOpcode == PPC::CMPW && (AtomicSize == 1 || AtomicSize == 2))
13348 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13350 F->insert(It, loopMBB);
13352 F->insert(It, loop2MBB);
13353 F->insert(It, exitMBB);
13359 Register TmpReg = (!BinOpcode) ? incr :
13360 RegInfo.createVirtualRegister( AtomicSize == 8 ? &PPC::G8RCRegClass
13361 : &PPC::GPRCRegClass);
13386 BuildMI(BB, dl,
TII->get(LoadMnemonic), dest)
13391 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13393 if (CmpOpcode == PPC::CMPW && AtomicSize < 4) {
13394 Register ExtReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13395 BuildMI(BB, dl,
TII->get(AtomicSize == 1 ? PPC::EXTSB : PPC::EXTSH),
13425 switch(
MI.getOpcode()) {
13429 return TII->isSignExtended(
MI.getOperand(1).getReg(),
13430 &
MI.getMF()->getRegInfo());
13454 case PPC::EXTSB8_32_64:
13455 case PPC::EXTSB8_rec:
13456 case PPC::EXTSB_rec:
13459 case PPC::EXTSH8_32_64:
13460 case PPC::EXTSH8_rec:
13461 case PPC::EXTSH_rec:
13463 case PPC::EXTSWSLI:
13464 case PPC::EXTSWSLI_32_64:
13465 case PPC::EXTSWSLI_32_64_rec:
13466 case PPC::EXTSWSLI_rec:
13467 case PPC::EXTSW_32:
13468 case PPC::EXTSW_32_64:
13469 case PPC::EXTSW_32_64_rec:
13470 case PPC::EXTSW_rec:
13473 case PPC::SRAWI_rec:
13474 case PPC::SRAW_rec:
13484 unsigned OpIdx,
bool IsByte,
13489 bool IsSignExtended =
13492 if (!IsSignExtended) {
13493 Register ValueReg =
RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13495 TII->get(IsByte ? PPC::EXTSB : PPC::EXTSH), ValueReg)
13497 MI.getOperand(
OpIdx).setReg(ValueReg);
13503 unsigned CmpOpcode,
unsigned CmpPred)
const {
13507 assert(!Subtarget.hasPartwordAtomics() &&
13508 "Assumes that part-word atomics are not available");
13516 const bool is8bit =
MI.getOperand(3).getImm() == 1;
13517 if (CmpOpcode == PPC::CMPW)
13525 bool is64bit = Subtarget.isPPC64();
13526 bool isLittleEndian = Subtarget.isLittleEndian();
13527 unsigned ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
13538 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13540 F->insert(It, loopMBB);
13542 F->insert(It, loop2MBB);
13543 F->insert(It, exitMBB);
13549 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13552 Register PtrReg = RegInfo.createVirtualRegister(RC);
13553 Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
13555 isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
13556 Register Incr2Reg = RegInfo.createVirtualRegister(GPRC);
13557 Register MaskReg = RegInfo.createVirtualRegister(GPRC);
13558 Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
13559 Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
13560 Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
13561 Register Tmp3Reg = RegInfo.createVirtualRegister(GPRC);
13562 Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
13563 Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
13564 Register SrwDestReg = RegInfo.createVirtualRegister(GPRC);
13567 (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(GPRC);
13594 if (ptrA != ZeroReg) {
13595 Ptr1Reg = RegInfo.createVirtualRegister(RC);
13596 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
13604 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
13605 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
13608 .
addImm(is8bit ? 28 : 27);
13609 if (!isLittleEndian)
13610 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
13612 .
addImm(is8bit ? 24 : 16);
13614 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
13619 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
13629 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
13633 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
13638 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
13642 BuildMI(BB, dl,
TII->get(BinOpcode), TmpReg)
13645 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
13652 Register SReg = RegInfo.createVirtualRegister(GPRC);
13653 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13657 unsigned ValueReg = SReg;
13658 unsigned CmpReg = Incr2Reg;
13659 if (CmpOpcode == PPC::CMPW) {
13660 ValueReg = RegInfo.createVirtualRegister(GPRC);
13661 BuildMI(BB, dl,
TII->get(PPC::SRW), ValueReg)
13664 Register ValueSReg = RegInfo.createVirtualRegister(GPRC);
13665 BuildMI(BB, dl,
TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueSReg)
13667 ValueReg = ValueSReg;
13699 .
addImm(is8bit ? 24 : 16)
13720 Register DstReg =
MI.getOperand(0).getReg();
13722 assert(
TRI->isTypeLegalForClass(*RC, MVT::i32) &&
"Invalid destination!");
13727 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13728 "Invalid Pointer Size!");
13777 Register BufReg =
MI.getOperand(1).getReg();
13779 if (Subtarget.is64BitELFABI()) {
13792 BaseReg = Subtarget.isPPC64() ? PPC::X1 : PPC::R1;
13794 BaseReg = Subtarget.isPPC64() ? PPC::BP8 : PPC::BP;
13797 TII->get(Subtarget.isPPC64() ? PPC::STD : PPC::STW))
13820 TII->get(Subtarget.isPPC64() ? PPC::MFLR8 : PPC::MFLR), LabelReg);
13823 if (Subtarget.isPPC64()) {
13841 TII->get(PPC::PHI), DstReg)
13845 MI.eraseFromParent();
13859 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13860 "Invalid Pointer Size!");
13863 (PVT == MVT::i64) ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13866 unsigned FP = (PVT == MVT::i64) ? PPC::X31 : PPC::R31;
13867 unsigned SP = (PVT == MVT::i64) ? PPC::X1 : PPC::R1;
13881 Register BufReg =
MI.getOperand(0).getReg();
13886 if (PVT == MVT::i64) {
13898 if (PVT == MVT::i64) {
13910 if (PVT == MVT::i64) {
13922 if (PVT == MVT::i64) {
13934 if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) {
13944 TII->get(PVT == MVT::i64 ? PPC::MTCTR8 : PPC::MTCTR)).
addReg(Tmp);
13947 MI.eraseFromParent();
13963 "Unexpected stack alignment");
13967 unsigned StackProbeSize =
13970 StackProbeSize &= ~(StackAlign - 1);
13971 return StackProbeSize ? StackProbeSize : StackAlign;
13983 const bool isPPC64 = Subtarget.isPPC64();
14015 MF->
insert(MBBIter, TestMBB);
14016 MF->
insert(MBBIter, BlockMBB);
14017 MF->
insert(MBBIter, TailMBB);
14022 Register DstReg =
MI.getOperand(0).getReg();
14023 Register NegSizeReg =
MI.getOperand(1).getReg();
14035 isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_64 : PPC::PREPARE_PROBED_ALLOCA_32;
14041 ProbeOpc = isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_64
14042 : PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_32;
14044 .
addDef(ActualNegSizeReg)
14046 .
add(
MI.getOperand(2))
14047 .
add(
MI.getOperand(3));
14053 .
addReg(ActualNegSizeReg);
14056 int64_t NegProbeSize = -(int64_t)ProbeSize;
14062 .
addImm(NegProbeSize >> 16);
14066 .
addImm(NegProbeSize & 0xFFFF);
14075 .
addReg(ActualNegSizeReg)
14084 .
addReg(ActualNegSizeReg);
14094 BuildMI(TestMBB,
DL,
TII->get(isPPC64 ? PPC::CMPD : PPC::CMPW), CmpResult)
14121 TII->get(isPPC64 ? PPC::DYNAREAOFFSET8 : PPC::DYNAREAOFFSET),
14122 MaxCallFrameSizeReg)
14123 .
add(
MI.getOperand(2))
14124 .
add(
MI.getOperand(3));
14125 BuildMI(TailMBB,
DL,
TII->get(isPPC64 ? PPC::ADD8 : PPC::ADD4), DstReg)
14127 .
addReg(MaxCallFrameSizeReg);
14133 MBB->addSuccessor(TestMBB);
14136 MI.eraseFromParent();
14138 ++NumDynamicAllocaProbed;
14146static bool IsSelect(
unsigned Opcode,
bool CheckOnlyCC =
false) {
14149 case PPC::SELECT_CC_I4:
14150 case PPC::SELECT_CC_I8:
14151 case PPC::SELECT_CC_F4:
14152 case PPC::SELECT_CC_F8:
14153 case PPC::SELECT_CC_F16:
14154 case PPC::SELECT_CC_VRRC:
14155 case PPC::SELECT_CC_VSFRC:
14156 case PPC::SELECT_CC_VSSRC:
14157 case PPC::SELECT_CC_VSRC:
14158 case PPC::SELECT_CC_SPE4:
14159 case PPC::SELECT_CC_SPE:
14162 case PPC::SELECT_I4:
14163 case PPC::SELECT_I8:
14164 case PPC::SELECT_F4:
14165 case PPC::SELECT_F8:
14166 case PPC::SELECT_F16:
14167 case PPC::SELECT_SPE:
14168 case PPC::SELECT_SPE4:
14169 case PPC::SELECT_VRRC:
14170 case PPC::SELECT_VSFRC:
14171 case PPC::SELECT_VSSRC:
14172 case PPC::SELECT_VSRC:
14173 return !CheckOnlyCC;
14189 assert(
IsSelect(
MI.getOpcode()) &&
"Instruction must be a SELECT variant");
14192 if (Subtarget.hasISEL() &&
14193 (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
14194 MI.getOpcode() == PPC::SELECT_CC_I8 ||
14195 MI.getOpcode() == PPC::SELECT_I4 ||
MI.getOpcode() == PPC::SELECT_I8)) {
14197 if (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
14198 MI.getOpcode() == PPC::SELECT_CC_I8)
14199 Cond.push_back(
MI.getOperand(4));
14202 Cond.push_back(
MI.getOperand(1));
14205 TII->insertSelect(*BB,
MI, dl,
MI.getOperand(0).getReg(),
Cond,
14206 MI.getOperand(2).getReg(),
MI.getOperand(3).getReg());
14207 MI.eraseFromParent();
14220 F->insert(It, copy0MBB);
14221 F->insert(It, sinkMBB);
14229 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
14245 .
addImm(
MI.getOperand(4).getImm())
14246 .
addReg(
MI.getOperand(1).getReg())
14250 .
addReg(
MI.getOperand(1).getReg())
14260 .
addReg(
MI.getOperand(3).getReg())
14262 .
addReg(
MI.getOperand(2).getReg())
14264 MI.eraseFromParent();
14279 loop1MBB =
F->CreateMachineBasicBlock(LLVM_BB);
14280 loop2MBB =
F->CreateMachineBasicBlock(LLVM_BB);
14281 exitMBB =
F->CreateMachineBasicBlock(LLVM_BB);
14282 F->insert(It, loop1MBB);
14283 F->insert(It, loop2MBB);
14284 F->insert(It, exitMBB);
14319 bool is64bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
14321 unsigned LoadMnemonic = PPC::LDARX;
14322 unsigned StoreMnemonic = PPC::STDCX;
14323 switch (
MI.getOpcode()) {
14326 case PPC::ATOMIC_CMP_SWAP_I8:
14327 LoadMnemonic = PPC::LBARX;
14328 StoreMnemonic = PPC::STBCX;
14329 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14331 case PPC::ATOMIC_CMP_SWAP_I16:
14332 LoadMnemonic = PPC::LHARX;
14333 StoreMnemonic = PPC::STHCX;
14334 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14336 case PPC::ATOMIC_CMP_SWAP_I32:
14337 LoadMnemonic = PPC::LWARX;
14338 StoreMnemonic = PPC::STWCX;
14340 case PPC::ATOMIC_CMP_SWAP_I64:
14341 LoadMnemonic = PPC::LDARX;
14342 StoreMnemonic = PPC::STDCX;
14350 Register oldval =
MI.getOperand(3).getReg();
14351 Register newval =
MI.getOperand(4).getReg();
14365 BuildMI(BB, dl,
TII->get(is64bit ? PPC::CMPD : PPC::CMPW), CrReg)
14433 bool is64bit = Subtarget.isPPC64();
14435 bool is8bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8;
14440 Register oldval =
MI.getOperand(3).getReg();
14441 Register newval =
MI.getOperand(4).getReg();
14449 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
14454 return RegInfo.createVirtualRegister(RC);
14458 Register Shift1Reg = createVReg(GPRC);
14459 Register ShiftReg = isLittleEndian ? Shift1Reg : createVReg(GPRC);
14460 Register NewVal2Reg = createVReg(GPRC);
14461 Register NewVal3Reg = createVReg(GPRC);
14462 Register OldVal2Reg = createVReg(GPRC);
14463 Register OldVal3Reg = createVReg(GPRC);
14464 Register MaskReg = createVReg(GPRC);
14465 Register Mask2Reg = createVReg(GPRC);
14466 Register Mask3Reg = createVReg(GPRC);
14467 Register Tmp2Reg = createVReg(GPRC);
14468 Register Tmp4Reg = createVReg(GPRC);
14469 Register TmpDestReg = createVReg(GPRC);
14470 Register TmpReg = createVReg(GPRC);
14471 Register ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
14472 Register CrReg = createVReg(&PPC::CRRCRegClass);
14476 if (ptrA != ZeroReg) {
14477 Ptr1Reg = createVReg(RC);
14478 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
14485 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
14486 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
14489 .
addImm(is8bit ? 28 : 27);
14490 if (!isLittleEndian)
14491 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
14493 .
addImm(is8bit ? 24 : 16);
14495 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
14500 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
14507 BuildMI(BB, dl,
TII->get(PPC::SLW), NewVal2Reg)
14510 BuildMI(BB, dl,
TII->get(PPC::SLW), OldVal2Reg)
14517 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
14521 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
14524 BuildMI(BB, dl,
TII->get(PPC::AND), NewVal3Reg)
14527 BuildMI(BB, dl,
TII->get(PPC::AND), OldVal3Reg)
14537 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
14558 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
14603 switch (
MI.getOpcode()) {
14604 case TargetOpcode::STACKMAP:
14606 case TargetOpcode::PATCHPOINT:
14612 if (Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls())
14616 case PPC::EH_SjLj_SetJmp32:
14617 case PPC::EH_SjLj_SetJmp64:
14620 case PPC::EH_SjLj_LongJmp32:
14621 case PPC::EH_SjLj_LongJmp64:
14624 case PPC::ReadTB: {
14640 F->insert(It, readMBB);
14641 F->insert(It, sinkMBB);
14652 Register ReadAgainReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
14660 Register CmpReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14662 BuildMI(BB, dl,
TII->get(PPC::CMPW), CmpReg)
14674 case PPC::ATOMIC_LOAD_ADD_NOWP:
14677 case PPC::ATOMIC_LOAD_ADD:
14680 case PPC::ATOMIC_LOAD_ADD_I64:
14683 case PPC::ATOMIC_LOAD_AND_NOWP:
14686 case PPC::ATOMIC_LOAD_AND:
14689 case PPC::ATOMIC_LOAD_AND_I64:
14692 case PPC::ATOMIC_LOAD_OR_NOWP:
14695 case PPC::ATOMIC_LOAD_OR:
14698 case PPC::ATOMIC_LOAD_OR_I64:
14701 case PPC::ATOMIC_LOAD_XOR_NOWP:
14704 case PPC::ATOMIC_LOAD_XOR:
14707 case PPC::ATOMIC_LOAD_XOR_I64:
14710 case PPC::ATOMIC_LOAD_NAND_NOWP:
14713 case PPC::ATOMIC_LOAD_NAND:
14716 case PPC::ATOMIC_LOAD_NAND_I64:
14719 case PPC::ATOMIC_LOAD_SUB_NOWP:
14722 case PPC::ATOMIC_LOAD_SUB:
14725 case PPC::ATOMIC_LOAD_SUB_I64:
14728 case PPC::ATOMIC_LOAD_MIN_NOWP:
14731 case PPC::ATOMIC_LOAD_MIN:
14734 case PPC::ATOMIC_LOAD_MIN_I64:
14737 case PPC::ATOMIC_LOAD_MAX_NOWP:
14740 case PPC::ATOMIC_LOAD_MAX:
14743 case PPC::ATOMIC_LOAD_MAX_I64:
14746 case PPC::ATOMIC_LOAD_UMIN_NOWP:
14749 case PPC::ATOMIC_LOAD_UMIN:
14752 case PPC::ATOMIC_LOAD_UMIN_I64:
14755 case PPC::ATOMIC_LOAD_UMAX_NOWP:
14758 case PPC::ATOMIC_LOAD_UMAX:
14761 case PPC::ATOMIC_LOAD_UMAX_I64:
14764 case PPC::ATOMIC_SWAP_NOWP:
14767 case PPC::ATOMIC_SWAP:
14768 case PPC::ATOMIC_SWAP_I64:
14771 case PPC::ATOMIC_CMP_SWAP_I32:
14772 case PPC::ATOMIC_CMP_SWAP_I64:
14773 case PPC::ATOMIC_CMP_SWAP_I8:
14774 case PPC::ATOMIC_CMP_SWAP_I16: {
14776 bool useHardware =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
14777 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64 ||
14778 (Subtarget.hasPartwordAtomics() &&
14779 (
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 ||
14780 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16));
14788 case PPC::FADDrtz: {
14798 Register MFFSReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14813 auto MIB =
BuildMI(*BB,
MI, dl,
TII->get(PPC::FADD), Dest)
14823 case PPC::ANDI_rec_1_EQ_BIT:
14824 case PPC::ANDI_rec_1_GT_BIT:
14825 case PPC::ANDI_rec_1_EQ_BIT8:
14826 case PPC::ANDI_rec_1_GT_BIT8: {
14827 unsigned Opcode = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
14828 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8)
14831 bool IsEQ = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
14832 MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8);
14835 Register Dest = RegInfo.createVirtualRegister(
14836 Opcode == PPC::ANDI_rec ? &PPC::GPRCRegClass : &PPC::G8RCRegClass);
14840 .
addReg(
MI.getOperand(1).getReg())
14843 MI.getOperand(0).getReg())
14844 .
addReg(IsEQ ? PPC::CR0EQ : PPC::CR0GT);
14847 case PPC::TCHECK_RET: {
14850 Register CRReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14853 MI.getOperand(0).getReg())
14857 case PPC::TBEGIN_RET: {
14859 unsigned Imm =
MI.getOperand(1).getImm();
14862 MI.getOperand(0).getReg())
14866 case PPC::SETRNDi: {
14868 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14872 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14874 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14885 unsigned Mode =
MI.getOperand(1).getImm();
14886 BuildMI(*BB,
MI, dl,
TII->get((Mode & 1) ? PPC::MTFSB1 : PPC::MTFSB0))
14890 BuildMI(*BB,
MI, dl,
TII->get((Mode & 2) ? PPC::MTFSB1 : PPC::MTFSB0))
14895 case PPC::SETRND: {
14903 auto copyRegFromG8RCOrF8RC = [&] (
unsigned DestReg,
unsigned SrcReg) {
14904 if (Subtarget.hasDirectMove()) {
14905 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::COPY), DestReg)
14909 unsigned StoreOp = PPC::STD, LoadOp = PPC::LFD;
14912 if (RC == &PPC::F8RCRegClass) {
14914 assert((RegInfo.getRegClass(DestReg) == &PPC::G8RCRegClass) &&
14915 "Unsupported RegClass.");
14917 StoreOp = PPC::STFD;
14921 assert((RegInfo.getRegClass(SrcReg) == &PPC::G8RCRegClass) &&
14922 (RegInfo.getRegClass(DestReg) == &PPC::F8RCRegClass) &&
14923 "Unsupported RegClass.");
14956 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14959 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14971 Register OldFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14973 copyRegFromG8RCOrF8RC(OldFPSCRTmpReg, OldFPSCRReg);
14975 Register ImDefReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14976 Register ExtSrcReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14981 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), ImDefReg);
14982 BuildMI(*BB,
MI, dl,
TII->get(PPC::INSERT_SUBREG), ExtSrcReg)
14987 Register NewFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14988 BuildMI(*BB,
MI, dl,
TII->get(PPC::RLDIMI), NewFPSCRTmpReg)
14994 Register NewFPSCRReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14995 copyRegFromG8RCOrF8RC(NewFPSCRReg, NewFPSCRTmpReg);
15006 case PPC::SETFLM: {
15010 Register OldFPSCRReg =
MI.getOperand(0).getReg();
15012 BuildMI(*BB,
MI, Dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
15014 BuildMI(*BB,
MI, Dl,
TII->get(PPC::MFFS), OldFPSCRReg);
15017 Register NewFPSCRReg =
MI.getOperand(1).getReg();
15025 case PPC::PROBED_ALLOCA_32:
15026 case PPC::PROBED_ALLOCA_64:
15029 case PPC::SPLIT_QUADWORD: {
15036 .
addUse(Src, {}, PPC::sub_gp8_x1);
15039 .
addUse(Src, {}, PPC::sub_gp8_x0);
15042 case PPC::LQX_PSEUDO:
15043 case PPC::STQX_PSEUDO: {
15049 F->getRegInfo().createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass);
15055 MI.getOpcode() == PPC::LQX_PSEUDO ?
TII->get(PPC::LQ)
15056 :
TII->get(PPC::STQ))
15066 MI.eraseFromParent();
15079 int RefinementSteps = Subtarget.hasRecipPrec() ? 1 : 3;
15082 return RefinementSteps;
15089 EVT VT =
Op.getValueType();
15092 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX())))
15116PPCTargetLowering::getSqrtResultForDenormInput(
SDValue Op,
15119 EVT VT =
Op.getValueType();
15120 if (VT != MVT::f64 &&
15121 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX()))
15124 return DAG.
getNode(PPCISD::FSQRT, SDLoc(
Op), VT,
Op);
15128 int Enabled,
int &RefinementSteps,
15129 bool &UseOneConstNR,
15130 bool Reciprocal)
const {
15132 if ((VT == MVT::f32 && Subtarget.hasFRSQRTES()) ||
15133 (VT == MVT::f64 && Subtarget.hasFRSQRTE()) ||
15134 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
15135 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
15141 UseOneConstNR = !Subtarget.needsTwoConstNR();
15142 return DAG.
getNode(PPCISD::FRSQRTE, SDLoc(Operand), VT, Operand);
15149 int &RefinementSteps)
const {
15151 if ((VT == MVT::f32 && Subtarget.hasFRES()) ||
15152 (VT == MVT::f64 && Subtarget.hasFRE()) ||
15153 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
15154 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
15157 return DAG.
getNode(PPCISD::FRE, SDLoc(Operand), VT, Operand);
15173 switch (Subtarget.getCPUDirective()) {
15200 unsigned Bytes,
int Dist,
15214 if (FS != BFS || FS != (
int)Bytes)
return false;
15219 int64_t Offset1 = 0, Offset2 = 0;
15222 if (Base1 == Base2 && Offset1 == (Offset2 + Dist * Bytes))
15232 if (isGA1 && isGA2 && GV1 == GV2)
15233 return Offset1 == (Offset2 + Dist*Bytes);
15240 unsigned Bytes,
int Dist,
15243 EVT VT = LS->getMemoryVT();
15250 switch (
N->getConstantOperandVal(1)) {
15251 default:
return false;
15252 case Intrinsic::ppc_altivec_lvx:
15253 case Intrinsic::ppc_altivec_lvxl:
15254 case Intrinsic::ppc_vsx_lxvw4x:
15255 case Intrinsic::ppc_vsx_lxvw4x_be:
15258 case Intrinsic::ppc_vsx_lxvd2x:
15259 case Intrinsic::ppc_vsx_lxvd2x_be:
15262 case Intrinsic::ppc_altivec_lvebx:
15265 case Intrinsic::ppc_altivec_lvehx:
15268 case Intrinsic::ppc_altivec_lvewx:
15278 switch (
N->getConstantOperandVal(1)) {
15279 default:
return false;
15280 case Intrinsic::ppc_altivec_stvx:
15281 case Intrinsic::ppc_altivec_stvxl:
15282 case Intrinsic::ppc_vsx_stxvw4x:
15285 case Intrinsic::ppc_vsx_stxvd2x:
15288 case Intrinsic::ppc_vsx_stxvw4x_be:
15291 case Intrinsic::ppc_vsx_stxvd2x_be:
15294 case Intrinsic::ppc_altivec_stvebx:
15297 case Intrinsic::ppc_altivec_stvehx:
15300 case Intrinsic::ppc_altivec_stvewx:
15317 SDValue Chain = LD->getChain();
15318 EVT VT = LD->getMemoryVT();
15327 while (!Queue.empty()) {
15328 SDNode *ChainNext = Queue.pop_back_val();
15329 if (!Visited.
insert(ChainNext).second)
15336 if (!Visited.
count(ChainLD->getChain().getNode()))
15337 Queue.push_back(ChainLD->getChain().getNode());
15339 for (
const SDUse &O : ChainNext->
ops())
15340 if (!Visited.
count(O.getNode()))
15341 Queue.push_back(O.getNode());
15343 LoadRoots.
insert(ChainNext);
15354 for (
SDNode *
I : LoadRoots) {
15355 Queue.push_back(
I);
15357 while (!Queue.empty()) {
15358 SDNode *LoadRoot = Queue.pop_back_val();
15359 if (!Visited.
insert(LoadRoot).second)
15371 Queue.push_back(U);
15404 auto Final = Shifted;
15415 DAGCombinerInfo &DCI)
const {
15418 SelectionDAG &DAG = DCI.DAG;
15423 if (!DCI.isAfterLegalizeDAG())
15428 for (
const SDNode *U :
N->users())
15433 auto OpSize =
N->getOperand(0).getValueSizeInBits();
15437 if (OpSize <
Size) {
15455 DAGCombinerInfo &DCI)
const {
15456 SelectionDAG &DAG = DCI.DAG;
15459 assert(Subtarget.useCRBits() &&
"Expecting to be tracking CR bits");
15470 N->getValueType(0) != MVT::i1)
15473 if (
N->getOperand(0).getValueType() != MVT::i32 &&
15474 N->getOperand(0).getValueType() != MVT::i64)
15484 unsigned OpBits =
N->getOperand(0).getValueSizeInBits();
15495 return (
N->getOpcode() ==
ISD::SETCC ? ConvertSETCCToSubtract(
N, DCI)
15518 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15519 N->getOperand(0).getOpcode() !=
ISD::OR &&
15520 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15530 N->getOperand(1).getOpcode() !=
ISD::AND &&
15531 N->getOperand(1).getOpcode() !=
ISD::OR &&
15532 N->getOperand(1).getOpcode() !=
ISD::XOR &&
15543 SmallPtrSet<SDNode *, 16> Visited;
15545 for (
unsigned i = 0; i < 2; ++i) {
15549 N->getOperand(i).getOperand(0).getValueType() == MVT::i1) ||
15561 while (!BinOps.
empty()) {
15569 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15603 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15607 for (
const SDNode *User : Inputs[i].
getNode()->
users()) {
15608 if (User !=
N && !Visited.
count(User))
15617 if (
User->getOperand(0) == Inputs[i])
15620 if (
User->getOperand(0) == Inputs[i] ||
15621 User->getOperand(1) == Inputs[i])
15627 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15628 for (
const SDNode *User : PromOps[i].
getNode()->
users()) {
15629 if (User !=
N && !Visited.
count(User))
15638 if (
User->getOperand(0) == PromOps[i])
15641 if (
User->getOperand(0) == PromOps[i] ||
15642 User->getOperand(1) == PromOps[i])
15649 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15658 std::list<HandleSDNode> PromOpHandles;
15659 for (
auto &PromOp : PromOps)
15660 PromOpHandles.emplace_back(PromOp);
15667 while (!PromOpHandles.empty()) {
15668 SDValue PromOp = PromOpHandles.back().getValue();
15669 PromOpHandles.pop_back();
15678 PromOpHandles.emplace_front(PromOp);
15692 default:
C = 0;
break;
15705 PromOpHandles.emplace_front(PromOp);
15712 for (
unsigned i = 0; i < 2; ++i)
15722 return N->getOperand(0);
15730 DAGCombinerInfo &DCI)
const {
15731 SelectionDAG &DAG = DCI.DAG;
15748 if (
N->getValueType(0) != MVT::i32 &&
15749 N->getValueType(0) != MVT::i64)
15752 if (!((
N->getOperand(0).getValueType() == MVT::i1 && Subtarget.useCRBits()) ||
15753 (
N->getOperand(0).getValueType() == MVT::i32 && Subtarget.isPPC64())))
15756 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15757 N->getOperand(0).getOpcode() !=
ISD::OR &&
15758 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15765 SmallPtrSet<SDNode *, 16> Visited;
15769 while (!BinOps.
empty()) {
15777 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15803 DenseMap<SDNode *, EVT> SelectTruncOp[2];
15808 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15813 if (User !=
N && !Visited.
count(User))
15819 if (
User->getOperand(0) == Inputs[i])
15820 SelectTruncOp[0].
insert(std::make_pair(User,
15821 User->getOperand(0).getValueType()));
15823 if (
User->getOperand(0) == Inputs[i])
15824 SelectTruncOp[0].
insert(std::make_pair(User,
15825 User->getOperand(0).getValueType()));
15826 if (
User->getOperand(1) == Inputs[i])
15827 SelectTruncOp[1].
insert(std::make_pair(User,
15828 User->getOperand(1).getValueType()));
15833 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15835 if (User !=
N && !Visited.
count(User))
15841 if (
User->getOperand(0) == PromOps[i])
15842 SelectTruncOp[0].
insert(std::make_pair(User,
15843 User->getOperand(0).getValueType()));
15845 if (
User->getOperand(0) == PromOps[i])
15846 SelectTruncOp[0].
insert(std::make_pair(User,
15847 User->getOperand(0).getValueType()));
15848 if (
User->getOperand(1) == PromOps[i])
15849 SelectTruncOp[1].
insert(std::make_pair(User,
15850 User->getOperand(1).getValueType()));
15855 unsigned PromBits =
N->getOperand(0).getValueSizeInBits();
15856 bool ReallyNeedsExt =
false;
15860 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15865 Inputs[i].getOperand(0).getValueSizeInBits();
15866 assert(PromBits < OpBits &&
"Truncation not to a smaller bit count?");
15871 OpBits-PromBits))) ||
15874 (OpBits-(PromBits-1)))) {
15875 ReallyNeedsExt =
true;
15883 std::list<HandleSDNode> PromOpHandles;
15884 for (
auto &PromOp : PromOps)
15885 PromOpHandles.emplace_back(PromOp);
15889 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15896 SDValue InSrc = Inputs[i].getOperand(0);
15914 while (!PromOpHandles.empty()) {
15916 PromOpHandles.pop_back();
15920 default:
C = 0;
break;
15933 PromOpHandles.emplace_front(PromOp);
15943 (SelectTruncOp[1].count(PromOp.
getNode()) &&
15945 PromOpHandles.emplace_front(PromOp);
15953 for (
unsigned i = 0; i < 2; ++i) {
15971 auto SI0 = SelectTruncOp[0].
find(PromOp.
getNode());
15972 if (SI0 != SelectTruncOp[0].
end())
15974 auto SI1 = SelectTruncOp[1].
find(PromOp.
getNode());
15975 if (SI1 != SelectTruncOp[1].
end())
15984 if (!ReallyNeedsExt)
15985 return N->getOperand(0);
15992 N->getValueSizeInBits(0), PromBits),
15993 dl,
N->getValueType(0)));
15996 "Invalid extension type");
15999 DAG.
getConstant(
N->getValueSizeInBits(0) - PromBits, dl, ShiftAmountTy);
16009 auto isValidForConvert = [IsPPC64](
SDValue &Operand) {
16018 const APInt &Val =
C->getAPIntValue();
16024 if (IsPPC64 && Val.
ult(1ULL << 16))
16038 if (LoadNode->isVolatile())
16059 return (isValidForConvert(
LHS) && isValidForConvert(
RHS));
16069 "CC mus be ISD::SETNE or ISD::SETEQ");
16071 auto getV16i8Load = [&](
const SDValue &Operand) {
16089 LoadNode->getBasePtr(), NewMMO);
16130 SDValue LHSVec = getV16i8Load(
N->getOperand(0));
16131 SDValue RHSVec = getV16i8Load(
N->getOperand(1));
16134 DAG.
getConstant(Intrinsic::ppc_altivec_vcmpequb_p,
DL, MVT::i32);
16137 IntrID, CRSel, LHSVec, RHSVec);
16140 return DAG.
getSetCC(
DL,
N->getValueType(0), PredResult,
16158 auto IsAndWithOne = [](
SDValue &V) {
16169 auto IsCompareWithZero = [](
SDValue &V) {
16176 return (IsAndWithOne(
LHS) && IsCompareWithZero(
RHS)) ||
16177 (IsAndWithOne(
RHS) && IsCompareWithZero(
LHS));
16194 auto MakeXor1 = [&](
SDValue V) {
16195 EVT VT = V.getValueType();
16202 return MakeXor1(
LHS);
16205 return MakeXor1(
RHS);
16222 DAGCombinerInfo &DCI)
const {
16223 if (Subtarget.isISA3_1())
16226 EVT VT =
N->getValueType(0);
16227 if (VT != MVT::i32 && (VT != MVT::i64 || !Subtarget.isPPC64()))
16243 SelectionDAG &DAG = DCI.DAG;
16245 EVT XVT =
X.getValueType();
16249 MVT OpVT = Subtarget.isPPC64() ? MVT::i64 : MVT::i32;
16262 Addc, Addc, Carry);
16265 if (OpVT == MVT::i64 && VT == MVT::i32)
16272 DAGCombinerInfo &DCI)
const {
16274 "Should be called with a SETCC node");
16296 SelectionDAG &DAG = DCI.DAG;
16297 EVT VT =
N->getValueType(0);
16298 EVT OpVT =
LHS.getValueType();
16316 if (Subtarget.hasAltivec() &&
16321 return DAGCombineTruncBoolExt(
N, DCI);
16328 Op.getValueType() == MVT::f64;
16340combineElementTruncationToVectorTruncation(
SDNode *
N,
16341 DAGCombinerInfo &DCI)
const {
16343 "Should be called with a BUILD_VECTOR node");
16345 SelectionDAG &DAG = DCI.DAG;
16348 SDValue FirstInput =
N->getOperand(0);
16350 "The input operand must be an fp-to-int conversion.");
16355 if (FirstConversion == PPCISD::FCTIDZ ||
16356 FirstConversion == PPCISD::FCTIDUZ ||
16357 FirstConversion == PPCISD::FCTIWZ ||
16358 FirstConversion == PPCISD::FCTIWUZ) {
16359 bool IsSplat =
true;
16360 bool Is32Bit = FirstConversion == PPCISD::FCTIWZ ||
16361 FirstConversion == PPCISD::FCTIWUZ;
16364 EVT TargetVT =
N->getValueType(0);
16365 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
16366 SDValue NextOp =
N->getOperand(i);
16367 if (NextOp.
getOpcode() != PPCISD::MFVSR)
16370 if (NextConversion != FirstConversion)
16378 if (
N->getOperand(i) != FirstInput)
16389 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
16390 SDValue In =
N->getOperand(i).getOperand(0);
16400 Ops.push_back(Trunc);
16403 Ops.push_back(
In.isUndef() ? DAG.
getUNDEF(SrcVT) :
In.getOperand(0));
16407 if (FirstConversion == PPCISD::FCTIDZ ||
16408 FirstConversion == PPCISD::FCTIWZ)
16413 EVT NewVT = TargetVT == MVT::v2i64 ? MVT::v2f64 : MVT::v4f32;
16415 return DAG.
getNode(Opcode, dl, TargetVT, BV);
16433 static const APInt BasePattern =
APInt(128, 0x8000000000000000ULL) << 64;
16437 if (FullVal == BasePattern)
16438 return std::make_tuple(Uim,
uint8_t{0});
16441 if (FullVal ==
APInt(128, 1))
16442 return std::make_tuple(Uim,
uint8_t{127});
16444 return std::nullopt;
16464 "Expected a BuildVectorSDNode in combineBVLoadsSpecialValue");
16468 EVT VT =
Op.getValueType();
16469 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
16483 for (
const SDValue &Operand :
Op.getNode()->op_values()) {
16493 for (
unsigned Index = 0;
Index < NumElems; ++
Index) {
16497 uint64_t ElemValue =
C->getZExtValue();
16501 ElemValue &= ((1ULL << ElemBits) - 1);
16505 (IsLittleEndian) ? (Index * ElemBits) : (128 - (
Index + 1) * ElemBits);
16508 APInt ElemAPInt(128, ElemValue);
16509 ElemAPInt <<= BitPos;
16512 FullVal |= ElemAPInt;
16519 const auto &[Uim, ShiftAmount] = *UIMOpt;
16523 if (ShiftAmount == 0) {
16528 <<
"combineBVLoadsSpecialValue: Instruction Emitted ";
16529 LxvkqInstr.
dump());
16533 assert(ShiftAmount == 127 &&
"Unexpected lxvkq shift amount value");
16545 DAG.
getMachineNode(PPC::VSRQ, Dl, VT, ShiftAmountVec, ShiftAmountVec),
16548 <<
"\n combineBVLoadsSpecialValue: Instruction Emitted ";
16564 "Should be called with a BUILD_VECTOR node");
16569 if (!
N->getValueType(0).getVectorElementType().isByteSized())
16572 bool InputsAreConsecutiveLoads =
true;
16573 bool InputsAreReverseConsecutive =
true;
16574 unsigned ElemSize =
N->getValueType(0).getScalarType().getStoreSize();
16575 SDValue FirstInput =
N->getOperand(0);
16576 bool IsRoundOfExtLoad =
false;
16586 N->getNumOperands() == 1)
16589 if (!IsRoundOfExtLoad)
16594 for (
int i = 1, e =
N->getNumOperands(); i < e; ++i) {
16596 if (IsRoundOfExtLoad &&
N->getOperand(i).getOpcode() !=
ISD::FP_ROUND)
16599 SDValue NextInput = IsRoundOfExtLoad ?
N->getOperand(i).getOperand(0) :
16605 IsRoundOfExtLoad ?
N->getOperand(i-1).getOperand(0) :
N->getOperand(i-1);
16616 InputsAreConsecutiveLoads =
false;
16618 InputsAreReverseConsecutive =
false;
16621 if (!InputsAreConsecutiveLoads && !InputsAreReverseConsecutive)
16626 assert(!(InputsAreConsecutiveLoads && InputsAreReverseConsecutive) &&
16627 "The loads cannot be both consecutive and reverse consecutive.");
16631 if (InputsAreConsecutiveLoads) {
16632 assert(FirstLoad &&
"Input needs to be a LoadSDNode.");
16636 ReturnSDVal = WideLoad;
16637 }
else if (InputsAreReverseConsecutive) {
16639 assert(LastLoad &&
"Input needs to be a LoadSDNode.");
16644 for (
int i =
N->getNumOperands() - 1; i >= 0; i--)
16652 for (
auto *LD : InputLoads)
16654 return ReturnSDVal;
16665 unsigned NumElems =
Input.getValueType().getVectorNumElements();
16671 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16673 ShuffleMask[CorrectElems & 0xF] = Elems & 0xF;
16675 ShuffleMask[(CorrectElems & 0xF0) >> 4] = (Elems & 0xF0) >> 4;
16676 CorrectElems = CorrectElems >> 8;
16677 Elems = Elems >> 8;
16684 EVT VT =
N->getValueType(0);
16688 Input.getValueType().getVectorElementType(),
16722 auto isSExtOfVecExtract = [&](
SDValue Op) ->
bool {
16748 Elems = Elems << 8;
16757 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16758 if (!isSExtOfVecExtract(
N->getOperand(i))) {
16765 int TgtElemArrayIdx;
16766 int InputSize =
Input.getValueType().getScalarSizeInBits();
16767 int OutputSize =
N->getValueType(0).getScalarSizeInBits();
16768 if (InputSize + OutputSize == 40)
16769 TgtElemArrayIdx = 0;
16770 else if (InputSize + OutputSize == 72)
16771 TgtElemArrayIdx = 1;
16772 else if (InputSize + OutputSize == 48)
16773 TgtElemArrayIdx = 2;
16774 else if (InputSize + OutputSize == 80)
16775 TgtElemArrayIdx = 3;
16776 else if (InputSize + OutputSize == 96)
16777 TgtElemArrayIdx = 4;
16781 uint64_t CorrectElems = TargetElems[TgtElemArrayIdx];
16783 ? CorrectElems & 0x0F0F0F0F0F0F0F0F
16784 : CorrectElems & 0xF0F0F0F0F0F0F0F0;
16785 if (Elems != CorrectElems) {
16801 if (
N->getValueType(0) != MVT::v1i128)
16804 SDValue Operand =
N->getOperand(0);
16811 EVT MemoryType = LD->getMemoryVT();
16815 bool ValidLDType = MemoryType == MVT::i8 || MemoryType == MVT::i16 ||
16816 MemoryType == MVT::i32 || MemoryType == MVT::i64;
16819 if (!ValidLDType ||
16825 LD->getChain(), LD->getBasePtr(),
16829 DAG.
getVTList(MVT::v1i128, MVT::Other),
16830 LoadOps, MemoryType, LD->getMemOperand());
16834 DAGCombinerInfo &DCI)
const {
16836 "Should be called with a BUILD_VECTOR node");
16838 SelectionDAG &DAG = DCI.DAG;
16841 if (!Subtarget.hasVSX())
16848 if (FirstInput.
getOpcode() == PPCISD::MFVSR) {
16849 SDValue Reduced = combineElementTruncationToVectorTruncation(
N, DCI);
16864 if (Subtarget.hasP9Altivec() && !DCI.isBeforeLegalize()) {
16873 if (Subtarget.isISA3_1()) {
16879 if (
N->getValueType(0) != MVT::v2f64)
16890 if (FirstInput.
getOpcode() !=
N->getOperand(1).getOpcode())
16901 if (!Ext1Op || !Ext2Op)
16910 if (FirstElem == 0 && SecondElem == 1)
16911 SubvecIdx = Subtarget.isLittleEndian() ? 1 : 0;
16912 else if (FirstElem == 2 && SecondElem == 3)
16913 SubvecIdx = Subtarget.isLittleEndian() ? 0 : 1;
16919 PPCISD::SINT_VEC_TO_FP : PPCISD::UINT_VEC_TO_FP;
16920 return DAG.
getNode(NodeType, dl, MVT::v2f64,
16925 DAGCombinerInfo &DCI)
const {
16928 "Need an int -> FP conversion node here");
16933 SelectionDAG &DAG = DCI.DAG;
16939 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
16941 if (!
Op.getOperand(0).getValueType().isSimple())
16943 if (
Op.getOperand(0).getValueType().getSimpleVT() <= MVT(MVT::i1) ||
16944 Op.getOperand(0).getValueType().getSimpleVT() > MVT(MVT::i64))
16947 SDValue FirstOperand(
Op.getOperand(0));
16948 bool SubWordLoad = FirstOperand.getOpcode() ==
ISD::LOAD &&
16949 (FirstOperand.getValueType() == MVT::i8 ||
16950 FirstOperand.getValueType() == MVT::i16);
16951 if (Subtarget.hasP9Vector() && Subtarget.hasP9Altivec() && SubWordLoad) {
16953 bool DstDouble =
Op.getValueType() == MVT::f64;
16954 unsigned ConvOp =
Signed ?
16955 (DstDouble ? PPCISD::FCFID : PPCISD::FCFIDS) :
16956 (DstDouble ? PPCISD::FCFIDU : PPCISD::FCFIDUS);
16961 SDValue Ops[] = { LDN->getChain(), LDN->getBasePtr(), WidthConst };
16964 Ops, MVT::i8, LDN->getMemOperand());
16969 SDValue ExtOps[] = { Ld, WidthConst };
16971 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ext);
16973 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ld);
16981 if (
Op.getOperand(0).getValueType() == MVT::i32)
16985 "UINT_TO_FP is supported only with FPCVT");
16989 unsigned FCFOp = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16994 MVT FCFTy = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
17001 Subtarget.hasFPCVT()) ||
17003 SDValue Src =
Op.getOperand(0).getOperand(0);
17004 if (Src.getValueType() == MVT::f32) {
17006 DCI.AddToWorklist(Src.getNode());
17007 }
else if (Src.getValueType() != MVT::f64) {
17019 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
17022 DCI.AddToWorklist(
FP.getNode());
17046 switch (
N->getOpcode()) {
17051 Chain = LD->getChain();
17052 Base = LD->getBasePtr();
17053 MMO = LD->getMemOperand();
17072 MVT VecTy =
N->getValueType(0).getSimpleVT();
17080 Chain =
Load.getValue(1);
17082 PPCISD::XXSWAPD, dl, DAG.
getVTList(MVT::v2f64, MVT::Other), Chain,
Load);
17086 if (VecTy != MVT::v2f64) {
17113 switch (
N->getOpcode()) {
17118 Chain = ST->getChain();
17119 Base = ST->getBasePtr();
17120 MMO = ST->getMemOperand();
17140 SDValue Src =
N->getOperand(SrcOpnd);
17141 MVT VecTy = Src.getValueType().getSimpleVT();
17144 if (VecTy != MVT::v2f64) {
17150 DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Src);
17156 StoreOps, VecTy, MMO);
17163 DAGCombinerInfo &DCI)
const {
17166 unsigned Opcode =
N->getOperand(1).getOpcode();
17168 bool Strict =
N->getOperand(1)->isStrictFPOpcode();
17172 &&
"Not a FP_TO_INT Instruction!");
17175 EVT Op1VT =
N->getOperand(1).getValueType();
17178 if (!Subtarget.hasVSX() || !Subtarget.hasFPCVT() || !
isTypeLegal(ResVT))
17182 bool ValidTypeForStoreFltAsInt =
17183 (Op1VT == MVT::i32 || (Op1VT == MVT::i64 && Subtarget.isPPC64()) ||
17184 (Subtarget.hasP9Vector() && (Op1VT == MVT::i16 || Op1VT == MVT::i8)));
17187 if (ResVT == MVT::ppcf128 || (ResVT == MVT::f128 && !Subtarget.hasP9Vector()))
17190 if ((Op1VT != MVT::i64 && !Subtarget.hasP8Vector()) ||
17198 SDValue Ops[] = {
N->getOperand(0), Val,
N->getOperand(2),
17213 bool PrevElemFromFirstVec = Mask[0] < NumElts;
17214 for (
int i = 1, e = Mask.size(); i < e; i++) {
17215 if (PrevElemFromFirstVec && Mask[i] < NumElts)
17217 if (!PrevElemFromFirstVec && Mask[i] >= NumElts)
17219 PrevElemFromFirstVec = !PrevElemFromFirstVec;
17230 for (
int i = 0, e =
Op.getNumOperands(); i < e; i++) {
17231 FirstOp =
Op.getOperand(i);
17237 for (
int i = 1, e =
Op.getNumOperands(); i < e; i++)
17238 if (
Op.getOperand(i) != FirstOp && !
Op.getOperand(i).isUndef())
17248 Op =
Op.getOperand(0);
17264 int RHSFirstElt,
int RHSLastElt,
int HalfVec,
unsigned LHSNumValidElts,
17265 unsigned RHSNumValidElts,
const PPCSubtarget &Subtarget) {
17267 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - LHSNumValidElts;
17269 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - RHSNumValidElts;
17270 for (
int I = 0,
E = ShuffV.
size();
I <
E; ++
I) {
17271 int Idx = ShuffV[
I];
17272 if (Idx >= LHSFirstElt && Idx <= LHSLastElt)
17273 ShuffV[
I] += LHSEltFixup;
17274 else if (Idx >= RHSFirstElt && Idx <= RHSLastElt)
17275 ShuffV[
I] += RHSEltFixup;
17286 SDLoc dl(OrigSToV);
17289 "Expecting a SCALAR_TO_VECTOR here");
17302 "Cannot produce a permuted scalar_to_vector for one element vector");
17304 unsigned ResultInElt = NumElts / 2;
17310 return DAG.
getNode(PPCISD::SCALAR_TO_VECTOR_PERMUTED, dl, VT,
17315 int HalfVec,
int LHSLastElementDefined,
17316 int RHSLastElementDefined) {
17317 for (
int Index : ShuffV) {
17321 if ((LHSLastElementDefined >= 0) && (Index < HalfVec) &&
17322 (Index > LHSLastElementDefined))
17325 if ((RHSLastElementDefined >= 0) &&
17326 (Index > HalfVec + RHSLastElementDefined))
17333 int ScalarSize,
uint64_t ShuffleEltWidth,
unsigned &NumValidElts,
17334 int FirstElt,
int &LastElt,
SDValue VecShuffOperand,
SDValue SToVNode,
17350 LastElt = (
uint64_t)ScalarSize > ShuffleEltWidth
17351 ? ScalarSize / ShuffleEltWidth - 1 + FirstElt
17354 if (SToVPermuted.
getValueType() != VecShuffOperandType)
17355 SToVPermuted = DAG.
getBitcast(VecShuffOperandType, SToVPermuted);
17356 return SToVPermuted;
17376 int NumElts =
LHS.getValueType().getVectorNumElements();
17379 bool IsLittleEndian = Subtarget.isLittleEndian();
17386 if (!Subtarget.hasDirectMove())
17406 SmallVector<int, 16> ShuffV(Mask);
17409 if (SToVLHS || SToVRHS) {
17412 int ShuffleNumElts = ShuffV.
size();
17413 int HalfVec = ShuffleNumElts / 2;
17419 unsigned LHSNumValidElts = HalfVec;
17420 unsigned RHSNumValidElts = HalfVec;
17425 int LHSFirstElt = 0;
17426 int RHSFirstElt = ShuffleNumElts;
17427 int LHSLastElt = -1;
17428 int RHSLastElt = -1;
17436 int LHSScalarSize = 0;
17437 int RHSScalarSize = 0;
17440 if (!IsLittleEndian && LHSScalarSize >= 64)
17445 if (!IsLittleEndian && RHSScalarSize >= 64)
17448 if (LHSScalarSize != 0)
17450 LHSScalarSize, ShuffleEltWidth, LHSNumValidElts, LHSFirstElt,
17451 LHSLastElt,
LHS, SToVLHS, DAG, Subtarget);
17452 if (RHSScalarSize != 0)
17454 RHSScalarSize, ShuffleEltWidth, RHSNumValidElts, RHSFirstElt,
17455 RHSLastElt,
RHS, SToVRHS, DAG, Subtarget);
17466 ShuffV, LHSFirstElt, LHSLastElt, RHSFirstElt, RHSLastElt, HalfVec,
17467 LHSNumValidElts, RHSNumValidElts, Subtarget);
17493 if (IsLittleEndian) {
17496 if (Mask[0] < NumElts)
17497 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17501 ShuffV[i] = (ShuffV[i - 1] >= 0 ? ShuffV[i - 1] : 0) + NumElts;
17506 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17510 ShuffV[i] = (ShuffV[i + 1] >= 0 ? ShuffV[i + 1] : 0) + NumElts;
17515 if (Mask[0] < NumElts)
17516 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17520 ShuffV[i] = ShuffV[i + 1] >= 0 ? ShuffV[i + 1] - NumElts : 0;
17525 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17529 ShuffV[i] = ShuffV[i - 1] >= 0 ? ShuffV[i - 1] - NumElts : 0;
17539 if (IsLittleEndian)
17548 DAGCombinerInfo &DCI)
const {
17550 "Not a reverse memop pattern!");
17552 auto IsElementReverse = [](
const ShuffleVectorSDNode *SVN) ->
bool {
17555 auto I =
Mask.rbegin();
17556 auto E =
Mask.rend();
17558 for (;
I !=
E; ++
I) {
17566 SelectionDAG &DAG = DCI.DAG;
17569 if (!
isTypeLegal(VT) || !Subtarget.isLittleEndian() || !Subtarget.hasVSX())
17575 if (!Subtarget.hasP9Vector())
17578 if(!IsElementReverse(SVN))
17585 for (SDUse &Use : LSBase->
uses())
17586 if (
Use.getResNo() == 0 &&
17593 PPCISD::LOAD_VEC_BE, dl, DAG.
getVTList(VT, MVT::Other), LoadOps,
17608 PPCISD::STORE_VEC_BE, dl, DAG.
getVTList(MVT::Other), StoreOps,
17617 if (IntrinsicID == Intrinsic::ppc_stdcx)
17619 else if (IntrinsicID == Intrinsic::ppc_stwcx)
17621 else if (IntrinsicID == Intrinsic::ppc_sthcx)
17623 else if (IntrinsicID == Intrinsic::ppc_stbcx)
17632 if (
N->getOpcode() == PPCISD::ADDC &&
N->hasAnyUseOfValue(1)) {
17636 if (
LHS->getOpcode() == PPCISD::ADDE &&
17647 if (
N->getOpcode() == PPCISD::SUBE) {
17653 if (
LHS ==
RHS &&
LHS.getOpcode() == PPCISD::ADDC) {
17656 if (AddcLHS.
getOpcode() == PPCISD::ADDE &&
17678 SDValue CmpLHS =
N->getOperand(0);
17679 SDValue CmpRHS =
N->getOperand(1);
17680 SDValue TrueVal =
N->getOperand(2);
17681 SDValue FalseVal =
N->getOperand(3);
17695 if (FalseVal.getOpcode() !=
ISD::SRL || !FalseVal.hasOneUse())
17698 SDValue ShiftVal = FalseVal.getOperand(0);
17699 SDValue ShiftAmt = FalseVal.getOperand(1);
17703 if (!ShiftConst || !ShiftConst->getAPIntValue().isMinSignedValue())
17730 if (CtlzArg != CmpLHS)
17738 DAG.
getNode(PPCISD::SRL,
DL, FalseVal.getValueType(), ShiftVal, ShiftAmt);
17785 auto isZeroOrOne = [=](
SDValue &V) {
17787 V.getConstantOperandVal(0) == Intrinsic::ppc_test_data_class)
17792 if (!isZeroOrOne(NonNullConstant))
17802 EVT VType =
N->getValueType(0);
17806 return NewNonNullConstant;
17825 EVT XorVT =
N->getValueType(0);
17826 if ((XorVT != MVT::i32 && XorVT != MVT::i64))
17834 if (!XorConst || !XorConst->
isOne()) {
17836 if (!XorConst || !XorConst->
isOne())
17843 if (!
LHS.hasOneUse())
17851 SelectNode =
LHS.getOperand(0);
17865 if (MachineOpc != PPC::SELECT_CC_I4 && MachineOpc != PPC::SELECT_CC_I8)
17875 if (!ConstOp1 || !ConstOp2)
17879 if (!((ConstOp1->
isOne() && ConstOp2->
isZero()) ||
17888 MachineOpc = (XorVT == MVT::i32) ? PPC::SELECT_CC_I4 : PPC::SELECT_CC_I8;
17890 bool ConstOp1IsOne = ConstOp1->
isOne();
17893 {SelectNode.getOperand(0),
17894 DAG.getConstant(ConstOp1IsOne ? 0 : 1, DL, XorVT),
17895 DAG.getConstant(ConstOp1IsOne ? 1 : 0, DL, XorVT),
17896 SelectNode.getOperand(3)}),
17904 switch (
N->getOpcode()) {
17907 return combineADD(
N, DCI);
17939 return combineSHL(
N, DCI);
17941 return combineSRA(
N, DCI);
17943 return combineSRL(
N, DCI);
17945 return combineMUL(
N, DCI);
17947 case PPCISD::FNMSUB:
17948 return combineFMALike(
N, DCI);
17951 return N->getOperand(0);
17955 return N->getOperand(0);
17961 return N->getOperand(0);
17965 if (
SDValue SECC = combineSignExtendSetCC(
N, DCI))
17973 return DAGCombineExtBoolTrunc(
N, DCI);
17975 return combineTRUNCATE(
N, DCI);
17977 if (
SDValue CSCC = combineSetCC(
N, DCI))
17983 return DAGCombineTruncBoolExt(
N, DCI);
17986 return combineFPToIntToFP(
N, DCI);
17995 EVT Op1VT =
N->getOperand(1).getValueType();
17996 unsigned Opcode =
N->getOperand(1).getOpcode();
18000 SDValue Val = combineStoreFPToInt(
N, DCI);
18014 N->getOperand(1).getNode()->hasOneUse() &&
18015 (Op1VT == MVT::i32 || Op1VT == MVT::i16 ||
18016 (Subtarget.hasLDBRX() && Subtarget.isPPC64() && Op1VT == MVT::i64))) {
18024 SDValue BSwapOp =
N->getOperand(1).getOperand(0);
18031 if (Op1VT.
bitsGT(mVT)) {
18036 if (Op1VT == MVT::i64)
18041 N->getOperand(0), BSwapOp,
N->getOperand(2), DAG.
getValueType(mVT)
18061 ST->getBasePtr(), ST->getOffset(), MemVT,
18062 ST->getMemOperand(), ST->getAddressingMode(),
18066 return ST->isUnindexed()
18075 if (Subtarget.needsSwapsForVSXMemOps() &&
18076 (StoreVT == MVT::v2f64 || StoreVT == MVT::v2i64 ||
18077 StoreVT == MVT::v4f32 || StoreVT == MVT::v4i32))
18084 EVT VT = LD->getValueType(0);
18090 if (Subtarget.needsSwapsForVSXMemOps() &&
18091 (LoadVT == MVT::v2f64 || LoadVT == MVT::v2i64 ||
18092 LoadVT == MVT::v4f32 || LoadVT == MVT::v4i32))
18103 auto ReplaceTwoFloatLoad = [&]() {
18104 if (VT != MVT::i64)
18119 if (!LD->hasNUsesOfValue(2, 0))
18122 auto UI = LD->user_begin();
18123 while (UI.getUse().getResNo() != 0) ++UI;
18125 while (UI.getUse().getResNo() != 0) ++UI;
18126 SDNode *RightShift = *UI;
18134 if (RightShift->getOpcode() !=
ISD::SRL ||
18136 RightShift->getConstantOperandVal(1) != 32 ||
18137 !RightShift->hasOneUse())
18140 SDNode *Trunc2 = *RightShift->user_begin();
18150 Bitcast->getValueType(0) != MVT::f32)
18156 if (Subtarget.isLittleEndian())
18162 SDValue BasePtr = LD->getBasePtr();
18163 if (LD->isIndexed()) {
18165 "Non-pre-inc AM on PPC?");
18173 SDValue FloatLoad = DAG.
getLoad(MVT::f32, dl, LD->getChain(), BasePtr,
18174 LD->getPointerInfo(), LD->getAlign(),
18175 MMOFlags, LD->getAAInfo());
18181 LD->getPointerInfo().getWithOffset(4),
18184 if (LD->isIndexed()) {
18198 if (ReplaceTwoFloatLoad())
18201 EVT MemVT = LD->getMemoryVT();
18204 if (LD->isUnindexed() && VT.
isVector() &&
18207 !Subtarget.hasP8Vector() &&
18208 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
18209 VT == MVT::v4f32))) &&
18210 LD->getAlign() < ABIAlignment) {
18212 SDValue Chain = LD->getChain();
18213 SDValue Ptr = LD->getBasePtr();
18214 bool isLittleEndian = Subtarget.isLittleEndian();
18241 MVT PermCntlTy, PermTy, LDTy;
18242 Intr = isLittleEndian ? Intrinsic::ppc_altivec_lvsr
18243 : Intrinsic::ppc_altivec_lvsl;
18244 IntrLD = Intrinsic::ppc_altivec_lvx;
18245 IntrPerm = Intrinsic::ppc_altivec_vperm;
18246 PermCntlTy = MVT::v16i8;
18247 PermTy = MVT::v4i32;
18266 SDValue BaseLoadOps[] = { Chain, LDXIntID, Ptr };
18270 BaseLoadOps, LDTy, BaseMMO);
18279 int IncValue = IncOffset;
18296 SDValue ExtraLoadOps[] = { Chain, LDXIntID, Ptr };
18300 ExtraLoadOps, LDTy, ExtraMMO);
18311 if (isLittleEndian)
18313 ExtraLoad, BaseLoad, PermCntl, DAG, dl);
18316 BaseLoad, ExtraLoad, PermCntl, DAG, dl);
18319 Perm = Subtarget.hasAltivec()
18334 bool isLittleEndian = Subtarget.isLittleEndian();
18335 unsigned IID =
N->getConstantOperandVal(0);
18336 Intrinsic::ID Intr = (isLittleEndian ? Intrinsic::ppc_altivec_lvsr
18337 : Intrinsic::ppc_altivec_lvsl);
18338 if (IID == Intr &&
N->getOperand(1)->getOpcode() ==
ISD::ADD) {
18345 .zext(
Add.getScalarValueSizeInBits()))) {
18346 SDNode *BasePtr =
Add->getOperand(0).getNode();
18347 for (
SDNode *U : BasePtr->users()) {
18349 U->getConstantOperandVal(0) == IID) {
18360 SDNode *BasePtr =
Add->getOperand(0).getNode();
18361 for (
SDNode *U : BasePtr->users()) {
18364 (
Add->getConstantOperandVal(1) - U->getConstantOperandVal(1)) %
18370 V->getConstantOperandVal(0) == IID) {
18382 (IID == Intrinsic::ppc_altivec_vmaxsw ||
18383 IID == Intrinsic::ppc_altivec_vmaxsh ||
18384 IID == Intrinsic::ppc_altivec_vmaxsb)) {
18387 if ((
V1.getSimpleValueType() == MVT::v4i32 ||
18388 V1.getSimpleValueType() == MVT::v8i16 ||
18389 V1.getSimpleValueType() == MVT::v16i8) &&
18394 V1.getOperand(1) == V2) {
18415 switch (
N->getConstantOperandVal(1)) {
18418 case Intrinsic::ppc_altivec_vsum4sbs:
18419 case Intrinsic::ppc_altivec_vsum4shs:
18420 case Intrinsic::ppc_altivec_vsum4ubs: {
18427 APInt APSplatBits, APSplatUndef;
18428 unsigned SplatBitSize;
18431 APSplatBits, APSplatUndef, SplatBitSize, HasAnyUndefs, 0,
18432 !Subtarget.isLittleEndian());
18434 if (BVNIsConstantSplat && APSplatBits == 0)
18439 case Intrinsic::ppc_vsx_lxvw4x:
18440 case Intrinsic::ppc_vsx_lxvd2x:
18443 if (Subtarget.needsSwapsForVSXMemOps())
18451 if (Subtarget.needsSwapsForVSXMemOps()) {
18452 switch (
N->getConstantOperandVal(1)) {
18455 case Intrinsic::ppc_vsx_stxvw4x:
18456 case Intrinsic::ppc_vsx_stxvd2x:
18465 bool Is64BitBswapOn64BitTgt =
18466 Subtarget.isPPC64() &&
N->getValueType(0) == MVT::i64;
18468 N->getOperand(0).hasOneUse();
18469 if (IsSingleUseNormalLd &&
18470 (
N->getValueType(0) == MVT::i32 ||
N->getValueType(0) == MVT::i16 ||
18471 (Subtarget.hasLDBRX() && Is64BitBswapOn64BitTgt))) {
18482 DAG.
getVTList(
N->getValueType(0) == MVT::i64 ?
18483 MVT::i64 : MVT::i32, MVT::Other),
18484 Ops, LD->getMemoryVT(), LD->getMemOperand());
18488 if (
N->getValueType(0) == MVT::i16)
18505 !IsSingleUseNormalLd)
18510 if (!LD->isSimple())
18512 SDValue BasePtr = LD->getBasePtr();
18514 LD->getPointerInfo(), LD->getAlign());
18519 LD->getMemOperand(), 4, 4);
18523 if (Subtarget.isLittleEndian())
18529 Hi.getOperand(0).getValue(1),
Lo.getOperand(0).getValue(1));
18538 if (!
N->getOperand(0).hasOneUse() &&
18539 !
N->getOperand(1).hasOneUse() &&
18540 !
N->getOperand(2).hasOneUse()) {
18543 SDNode *VCMPrecNode =
nullptr;
18545 SDNode *LHSN =
N->getOperand(0).getNode();
18547 if (
User->getOpcode() == PPCISD::VCMP_rec &&
18551 VCMPrecNode =
User;
18563 SDNode *FlagUser =
nullptr;
18565 FlagUser ==
nullptr; ++UI) {
18566 assert(UI != VCMPrecNode->
use_end() &&
"Didn't find user!");
18579 return SDValue(VCMPrecNode, 0);
18590 SDValue LHS =
N->getOperand(2), RHS =
N->getOperand(3);
18601 auto RHSAPInt = RHS->getAsAPIntVal();
18602 if (!RHSAPInt.isIntN(64))
18605 unsigned Val = RHSAPInt.getZExtValue();
18606 auto isImpossibleCompare = [&]() {
18609 if (Val != 0 && Val != 1) {
18611 return N->getOperand(0);
18614 N->getOperand(0),
N->getOperand(4));
18619 unsigned StoreWidth = 0;
18622 if (
SDValue Impossible = isImpossibleCompare())
18634 SDValue Ops[] = {LHS.getOperand(0), LHS.getOperand(2), LHS.getOperand(3),
18638 PPCISD::STORE_COND, dl,
18640 MemNode->getMemoryVT(), MemNode->getMemOperand());
18644 if (
N->getOperand(0) == LHS.getValue(1))
18655 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other, InChain,
18657 DAG.
getRegister(PPC::CR0, MVT::i32),
N->getOperand(4),
18663 assert(isDot &&
"Can't compare against a vector result!");
18665 if (
SDValue Impossible = isImpossibleCompare())
18668 bool BranchOnWhenPredTrue = (CC ==
ISD::SETEQ) ^ (Val == 0);
18675 EVT VTs[] = { LHS.getOperand(2).getValueType(), MVT::Glue };
18680 switch (LHS.getConstantOperandVal(1)) {
18696 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other,
N->getOperand(0),
18699 N->getOperand(4), CompNode.
getValue(1));
18704 return DAGCombineBuildVector(
N, DCI);
18711 return DAGCombineBitcast(
N, DCI);
18722 EVT VT =
N->getValueType(0);
18723 if (VT == MVT::i64 && !Subtarget.isPPC64())
18725 if ((VT != MVT::i32 && VT != MVT::i64) ||
18733 unsigned Lg2 = (IsNegPow2 ? -Divisor : Divisor).
countr_zero();
18753 const APInt &DemandedElts,
18755 unsigned Depth)
const {
18757 switch (
Op.getOpcode()) {
18759 case PPCISD::LBRX: {
18762 Known.Zero = 0xFFFF0000;
18765 case PPCISD::ADDE: {
18766 if (
Op.getResNo() == 0) {
18771 Known.Zero = ~1ULL;
18776 switch (
Op.getConstantOperandVal(0)) {
18778 case Intrinsic::ppc_altivec_vcmpbfp_p:
18779 case Intrinsic::ppc_altivec_vcmpeqfp_p:
18780 case Intrinsic::ppc_altivec_vcmpequb_p:
18781 case Intrinsic::ppc_altivec_vcmpequh_p:
18782 case Intrinsic::ppc_altivec_vcmpequw_p:
18783 case Intrinsic::ppc_altivec_vcmpequd_p:
18784 case Intrinsic::ppc_altivec_vcmpequq_p:
18785 case Intrinsic::ppc_altivec_vcmpgefp_p:
18786 case Intrinsic::ppc_altivec_vcmpgtfp_p:
18787 case Intrinsic::ppc_altivec_vcmpgtsb_p:
18788 case Intrinsic::ppc_altivec_vcmpgtsh_p:
18789 case Intrinsic::ppc_altivec_vcmpgtsw_p:
18790 case Intrinsic::ppc_altivec_vcmpgtsd_p:
18791 case Intrinsic::ppc_altivec_vcmpgtsq_p:
18792 case Intrinsic::ppc_altivec_vcmpgtub_p:
18793 case Intrinsic::ppc_altivec_vcmpgtuh_p:
18794 case Intrinsic::ppc_altivec_vcmpgtuw_p:
18795 case Intrinsic::ppc_altivec_vcmpgtud_p:
18796 case Intrinsic::ppc_altivec_vcmpgtuq_p:
18803 switch (
Op.getConstantOperandVal(1)) {
18806 case Intrinsic::ppc_load2r:
18808 Known.Zero = 0xFFFF0000;
18817 switch (Subtarget.getCPUDirective()) {
18839 if (
ML->getLoopDepth() > 1 &&
ML->getSubLoops().empty())
18848 for (
auto I =
ML->block_begin(), IE =
ML->block_end();
I != IE; ++
I)
18850 LoopSize +=
TII->getInstSizeInBytes(J);
18855 if (LoopSize > 16 && LoopSize <= 32)
18869 if (Constraint.
size() == 1) {
18870 switch (Constraint[0]) {
18888 }
else if (Constraint ==
"wc") {
18890 }
else if (Constraint ==
"wa" || Constraint ==
"wd" ||
18891 Constraint ==
"wf" || Constraint ==
"ws" ||
18892 Constraint ==
"wi" || Constraint ==
"ww") {
18905 Value *CallOperandVal =
info.CallOperandVal;
18908 if (!CallOperandVal)
18915 else if ((
StringRef(constraint) ==
"wa" ||
18927 switch (*constraint) {
18957std::pair<unsigned, const TargetRegisterClass *>
18961 if (Constraint.
size() == 1) {
18963 switch (Constraint[0]) {
18965 if (VT == MVT::i64 && Subtarget.isPPC64())
18966 return std::make_pair(0U, &PPC::G8RC_NOX0RegClass);
18967 return std::make_pair(0U, &PPC::GPRC_NOR0RegClass);
18969 if (VT == MVT::i64 && Subtarget.isPPC64())
18970 return std::make_pair(0U, &PPC::G8RCRegClass);
18971 return std::make_pair(0U, &PPC::GPRCRegClass);
18977 if (Subtarget.hasSPE()) {
18978 if (VT == MVT::f32 || VT == MVT::i32)
18979 return std::make_pair(0U, &PPC::GPRCRegClass);
18980 if (VT == MVT::f64 || VT == MVT::i64)
18981 return std::make_pair(0U, &PPC::SPERCRegClass);
18983 if (VT == MVT::f32 || VT == MVT::i32)
18984 return std::make_pair(0U, &PPC::F4RCRegClass);
18985 if (VT == MVT::f64 || VT == MVT::i64)
18986 return std::make_pair(0U, &PPC::F8RCRegClass);
18990 if (Subtarget.hasAltivec() && VT.
isVector())
18991 return std::make_pair(0U, &PPC::VRRCRegClass);
18992 else if (Subtarget.hasVSX())
18994 return std::make_pair(0U, &PPC::VFRCRegClass);
18997 return std::make_pair(0U, &PPC::CRRCRegClass);
18999 }
else if (Constraint ==
"wc" && Subtarget.useCRBits()) {
19001 return std::make_pair(0U, &PPC::CRBITRCRegClass);
19002 }
else if ((Constraint ==
"wa" || Constraint ==
"wd" ||
19003 Constraint ==
"wf" || Constraint ==
"wi") &&
19004 Subtarget.hasVSX()) {
19008 return std::make_pair(0U, &PPC::VSRCRegClass);
19009 if (VT == MVT::f32 && Subtarget.hasP8Vector())
19010 return std::make_pair(0U, &PPC::VSSRCRegClass);
19011 return std::make_pair(0U, &PPC::VSFRCRegClass);
19012 }
else if ((Constraint ==
"ws" || Constraint ==
"ww") && Subtarget.hasVSX()) {
19013 if (VT == MVT::f32 && Subtarget.hasP8Vector())
19014 return std::make_pair(0U, &PPC::VSSRCRegClass);
19016 return std::make_pair(0U, &PPC::VSFRCRegClass);
19017 }
else if (Constraint ==
"lr") {
19018 if (VT == MVT::i64)
19019 return std::make_pair(0U, &PPC::LR8RCRegClass);
19021 return std::make_pair(0U, &PPC::LRRCRegClass);
19026 if (Constraint[0] ==
'{' && Constraint[Constraint.
size() - 1] ==
'}') {
19030 if (Constraint.
size() > 3 && Constraint[1] ==
'v' && Constraint[2] ==
's') {
19031 int VSNum = atoi(Constraint.
data() + 3);
19032 assert(VSNum >= 0 && VSNum <= 63 &&
19033 "Attempted to access a vsr out of range");
19035 return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass);
19036 return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass);
19041 if (Constraint.
size() > 3 && Constraint[1] ==
'f') {
19042 int RegNum = atoi(Constraint.
data() + 2);
19043 if (RegNum > 31 || RegNum < 0)
19045 if (VT == MVT::f32 || VT == MVT::i32)
19046 return Subtarget.hasSPE()
19047 ? std::make_pair(PPC::R0 + RegNum, &PPC::GPRCRegClass)
19048 : std::make_pair(PPC::F0 + RegNum, &PPC::F4RCRegClass);
19049 if (VT == MVT::f64 || VT == MVT::i64)
19050 return Subtarget.hasSPE()
19051 ? std::make_pair(PPC::S0 + RegNum, &PPC::SPERCRegClass)
19052 : std::make_pair(PPC::F0 + RegNum, &PPC::F8RCRegClass);
19056 std::pair<unsigned, const TargetRegisterClass *> R =
19065 if (R.first && VT == MVT::i64 && Subtarget.isPPC64() &&
19066 PPC::GPRCRegClass.contains(R.first))
19067 return std::make_pair(
TRI->getMatchingSuperReg(R.first,
19068 PPC::sub_32, &PPC::G8RCRegClass),
19069 &PPC::G8RCRegClass);
19072 if (!R.second &&
StringRef(
"{cc}").equals_insensitive(Constraint)) {
19073 R.first = PPC::CR0;
19074 R.second = &PPC::CRRCRegClass;
19078 if (Subtarget.isAIXABI() && !TM.getAIXExtendedAltivecABI()) {
19079 if (((R.first >= PPC::V20 && R.first <= PPC::V31) ||
19080 (R.first >= PPC::VF20 && R.first <= PPC::VF31)) &&
19081 (R.second == &PPC::VSRCRegClass || R.second == &PPC::VSFRCRegClass))
19082 errs() <<
"warning: vector registers 20 to 32 are reserved in the "
19083 "default AIX AltiVec ABI and cannot be used\n";
19093 std::vector<SDValue> &
Ops,
19098 if (Constraint.
size() > 1)
19101 char Letter = Constraint[0];
19116 EVT TCVT = MVT::i64;
19157 if (Result.getNode()) {
19158 Ops.push_back(Result);
19169 if (
I.getNumOperands() <= 1)
19173 auto IntrinsicID =
Ops[1].getNode()->getAsZExtVal();
19174 if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw &&
19175 IntrinsicID != Intrinsic::ppc_trapd && IntrinsicID != Intrinsic::ppc_trap)
19178 if (
MDNode *MDN =
I.getMetadata(LLVMContext::MD_annotation))
19194 if (Ty->isVectorTy() && AM.
BaseOffs != 0 && !Subtarget.hasP9Vector())
19206 switch (AM.
Scale) {
19234 unsigned Depth =
Op.getConstantOperandVal(0);
19258 SDValue RetAddrFI = getReturnAddrFrameIndex(DAG);
19266 unsigned Depth =
Op.getConstantOperandVal(0);
19273 bool isPPC64 = PtrVT == MVT::i64;
19279 FrameReg = isPPC64 ? PPC::X1 : PPC::R1;
19281 FrameReg = isPPC64 ? PPC::FP8 : PPC::FP;
19287 FrameAddr, MachinePointerInfo());
19291#define GET_REGISTER_MATCHER
19292#include "PPCGenAsmMatcher.inc"
19296 bool IsPPC64 = Subtarget.isPPC64();
19308 if ((IsPPC64 && Reg == PPC::R2) || Reg == PPC::R0)
19314 Reg = Reg.id() - PPC::R0 + PPC::X0;
19321 if (Subtarget.is32BitELFABI())
19326 if (Subtarget.isAIXABI())
19340 return Subtarget.isGVIndirectSymbol(
G->getGlobal());
19356 case Intrinsic::ppc_atomicrmw_xchg_i128:
19357 case Intrinsic::ppc_atomicrmw_add_i128:
19358 case Intrinsic::ppc_atomicrmw_sub_i128:
19359 case Intrinsic::ppc_atomicrmw_nand_i128:
19360 case Intrinsic::ppc_atomicrmw_and_i128:
19361 case Intrinsic::ppc_atomicrmw_or_i128:
19362 case Intrinsic::ppc_atomicrmw_xor_i128:
19363 case Intrinsic::ppc_cmpxchg_i128:
19365 Info.memVT = MVT::i128;
19366 Info.ptrVal =
I.getArgOperand(0);
19368 Info.align =
Align(16);
19373 case Intrinsic::ppc_atomic_load_i128:
19375 Info.memVT = MVT::i128;
19376 Info.ptrVal =
I.getArgOperand(0);
19378 Info.align =
Align(16);
19382 case Intrinsic::ppc_atomic_store_i128:
19384 Info.memVT = MVT::i128;
19385 Info.ptrVal =
I.getArgOperand(2);
19387 Info.align =
Align(16);
19391 case Intrinsic::ppc_altivec_lvx:
19392 case Intrinsic::ppc_altivec_lvxl:
19393 case Intrinsic::ppc_altivec_lvebx:
19394 case Intrinsic::ppc_altivec_lvehx:
19395 case Intrinsic::ppc_altivec_lvewx:
19396 case Intrinsic::ppc_vsx_lxvd2x:
19397 case Intrinsic::ppc_vsx_lxvw4x:
19398 case Intrinsic::ppc_vsx_lxvd2x_be:
19399 case Intrinsic::ppc_vsx_lxvw4x_be:
19400 case Intrinsic::ppc_vsx_lxvl:
19401 case Intrinsic::ppc_vsx_lxvll: {
19404 case Intrinsic::ppc_altivec_lvebx:
19407 case Intrinsic::ppc_altivec_lvehx:
19410 case Intrinsic::ppc_altivec_lvewx:
19413 case Intrinsic::ppc_vsx_lxvd2x:
19414 case Intrinsic::ppc_vsx_lxvd2x_be:
19424 Info.ptrVal =
I.getArgOperand(0);
19427 Info.align =
Align(1);
19432 case Intrinsic::ppc_altivec_stvx:
19433 case Intrinsic::ppc_altivec_stvxl:
19434 case Intrinsic::ppc_altivec_stvebx:
19435 case Intrinsic::ppc_altivec_stvehx:
19436 case Intrinsic::ppc_altivec_stvewx:
19437 case Intrinsic::ppc_vsx_stxvd2x:
19438 case Intrinsic::ppc_vsx_stxvw4x:
19439 case Intrinsic::ppc_vsx_stxvd2x_be:
19440 case Intrinsic::ppc_vsx_stxvw4x_be:
19441 case Intrinsic::ppc_vsx_stxvl:
19442 case Intrinsic::ppc_vsx_stxvll: {
19445 case Intrinsic::ppc_altivec_stvebx:
19448 case Intrinsic::ppc_altivec_stvehx:
19451 case Intrinsic::ppc_altivec_stvewx:
19454 case Intrinsic::ppc_vsx_stxvd2x:
19455 case Intrinsic::ppc_vsx_stxvd2x_be:
19465 Info.ptrVal =
I.getArgOperand(1);
19468 Info.align =
Align(1);
19473 case Intrinsic::ppc_stdcx:
19474 case Intrinsic::ppc_stwcx:
19475 case Intrinsic::ppc_sthcx:
19476 case Intrinsic::ppc_stbcx: {
19478 auto Alignment =
Align(8);
19480 case Intrinsic::ppc_stdcx:
19483 case Intrinsic::ppc_stwcx:
19485 Alignment =
Align(4);
19487 case Intrinsic::ppc_sthcx:
19489 Alignment =
Align(2);
19491 case Intrinsic::ppc_stbcx:
19493 Alignment =
Align(1);
19498 Info.ptrVal =
I.getArgOperand(0);
19500 Info.align = Alignment;
19514 const AttributeList &FuncAttributes)
const {
19518 if (Subtarget.hasAltivec() &&
Op.size() >= 16) {
19519 if (
Op.isMemset() && Subtarget.hasVSX()) {
19524 if (TailSize > 2 && TailSize <= 4) {
19529 if (
Op.isAligned(
Align(16)) || Subtarget.hasP8Vector())
19534 if (Subtarget.isPPC64()) {
19545 assert(Ty->isIntegerTy());
19547 unsigned BitSize = Ty->getPrimitiveSizeInBits();
19548 return !(BitSize == 0 || BitSize > 64);
19556 return NumBits1 == 64 && NumBits2 == 32;
19564 return NumBits1 == 64 && NumBits2 == 32;
19571 EVT MemVT = LD->getMemoryVT();
19572 if ((MemVT == MVT::i1 || MemVT == MVT::i8 || MemVT == MVT::i16 ||
19573 (Subtarget.isPPC64() && MemVT == MVT::i32)) &&
19589 "invalid fpext types");
19591 if (DestVT == MVT::f128)
19606 unsigned *
Fast)
const {
19620 !Subtarget.allowsUnalignedFPAccess())
19624 if (Subtarget.hasVSX()) {
19625 if (VT != MVT::v2f64 && VT != MVT::v2i64 &&
19626 VT != MVT::v4f32 && VT != MVT::v4i32)
19633 if (VT == MVT::ppcf128)
19648 if (!ConstNode->getAPIntValue().isSignedIntN(64))
19656 int64_t Imm = ConstNode->getSExtValue();
19677 if (Subtarget.hasSPE() || Subtarget.useSoftFloat())
19679 switch (Ty->getScalarType()->getTypeID()) {
19684 return Subtarget.hasP9Vector();
19692 if (!
I->hasOneUse())
19696 assert(
User &&
"A single use instruction with no uses.");
19698 switch (
I->getOpcode()) {
19699 case Instruction::FMul: {
19701 if (
User->getOpcode() != Instruction::FSub &&
19702 User->getOpcode() != Instruction::FAdd)
19709 bool AllowContract =
I->getFastMathFlags().allowContract() &&
19710 User->getFastMathFlags().allowContract();
19716 case Instruction::Load: {
19729 if (
User->getOpcode() != Instruction::Store)
19749 static const MCPhysReg ScratchRegs[] = {
19750 PPC::X12, PPC::LR8, PPC::CTR8, 0
19753 return ScratchRegs;
19757 const Constant *PersonalityFn)
const {
19758 return Subtarget.isPPC64() ? PPC::X3 : PPC::R3;
19762 const Constant *PersonalityFn)
const {
19763 return Subtarget.isPPC64() ? PPC::X4 : PPC::R4;
19768 EVT VT ,
unsigned DefinedValues)
const {
19769 if (VT == MVT::v2i64)
19770 return Subtarget.hasDirectMove();
19772 if (Subtarget.hasVSX())
19799 return PPCISD::FNMSUB;
19800 case PPCISD::FNMSUB:
19806 bool LegalOps,
bool OptForSize,
19808 unsigned Depth)
const {
19812 unsigned Opc =
Op.getOpcode();
19813 EVT VT =
Op.getValueType();
19817 case PPCISD::FNMSUB:
19837 if (Flags.hasNoSignedZeros()) {
19841 N0Cost,
Depth + 1);
19845 N1Cost,
Depth + 1);
19847 if (NegN0 && N0Cost <= N1Cost) {
19848 Cost = std::min(N0Cost, N2Cost);
19850 }
else if (NegN1) {
19851 Cost = std::min(N1Cost, N2Cost);
19871 if (M.getStackProtectorGuard() ==
"tls" || Subtarget.isTargetLinux())
19877 bool ForCodeSize)
const {
19878 if (!VT.
isSimple() || !Subtarget.hasVSX())
19888 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
19893 APSInt IntResult(16,
false);
19898 if (IsExact && IntResult <= 15 && IntResult >= -16)
19900 return Imm.isZero();
19903 return Imm.isPosZero();
19915 unsigned Opcode =
N->getOpcode();
19935 if (Mask->getZExtValue() == OpSizeInBits - 1)
19942 DAGCombinerInfo &DCI)
const {
19943 EVT VT =
N->getValueType(0);
19946 unsigned Opc =
N->getOpcode();
19948 "Unexpected opcode.");
19955 if (EltTy != MVT::i64 && EltTy != MVT::i32)
19959 uint64_t SplatBits = 0;
19960 bool AddSplatCase =
false;
19964 AddSplatCase =
true;
19968 if (!AddSplatCase) {
19972 unsigned SplatBitSize;
19974 APInt APSplatBits, APSplatUndef;
19976 bool BVNIsConstantSplat =
19978 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
19979 if (!BVNIsConstantSplat || SplatBitSize != EltBits)
19990 if (SplatBits == (EltBits - 1)) {
19994 NewOpc = PPCISD::SHL;
19997 NewOpc = PPCISD::SRL;
20000 NewOpc = PPCISD::SRA;
20004 return DCI.DAG.getNode(NewOpc,
DL, VT, N0, SplatOnes);
20012 if (EltTy != MVT::i64 || SplatBits != 1)
20015 return DCI.DAG.getNode(
ISD::ADD, SDLoc(
N), VT, N0, N0);
20018SDValue PPCTargetLowering::combineSHL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20022 if (
N->getValueType(0).isVector())
20023 return combineVectorShift(
N, DCI);
20027 if (!Subtarget.isISA3_0() || !Subtarget.isPPC64() ||
20030 N->getValueType(0) != MVT::i64)
20045 ShiftBy = DCI.DAG.getConstant(CN1->
getZExtValue(),
DL, MVT::i32);
20051SDValue PPCTargetLowering::combineSRA(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20055 if (
N->getValueType(0).isVector())
20056 return combineVectorShift(
N, DCI);
20061SDValue PPCTargetLowering::combineSRL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20065 if (
N->getValueType(0).isVector())
20066 return combineVectorShift(
N, DCI);
20077 if (!Subtarget.isPPC64())
20083 auto isZextOfCompareWithConstant = [](
SDValue Op) {
20085 Op.getValueType() != MVT::i64)
20089 if (Cmp.getOpcode() !=
ISD::SETCC || !Cmp.hasOneUse() ||
20090 Cmp.getOperand(0).getValueType() != MVT::i64)
20094 int64_t NegConstant = 0 -
Constant->getSExtValue();
20103 bool LHSHasPattern = isZextOfCompareWithConstant(
LHS);
20104 bool RHSHasPattern = isZextOfCompareWithConstant(
RHS);
20107 if (LHSHasPattern && !RHSHasPattern)
20109 else if (!LHSHasPattern && !RHSHasPattern)
20113 EVT CarryType = Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
20116 SDValue Z = Cmp.getOperand(0);
20118 int64_t NegConstant = 0 -
Constant->getSExtValue();
20131 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
20149 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
20179 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
20182 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
20190 if (!GSDN || !ConstNode)
20218 EVT VT =
N->getValueType(0);
20219 if (!Subtarget.hasVSX())
20223 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
20235 unsigned NumOfEles =
RHS.getNumOperands();
20236 for (
unsigned i = 0; i < NumOfEles; ++i) {
20238 if (!CN || CN->getSExtValue() != 1)
20253SDValue PPCTargetLowering::combineADD(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20275 DAGCombinerInfo &DCI)
const {
20277 if (Subtarget.useCRBits()) {
20279 if (
SDValue CRTruncValue = DAGCombineTruncBoolExt(
N, DCI))
20280 return CRTruncValue;
20287 if (Op0.
getValueType() != MVT::i128 ||
N->getValueType(0) != MVT::i64)
20290 int EltToExtract = DCI.DAG.getDataLayout().isBigEndian() ? 1 : 0;
20300 EltToExtract = EltToExtract ? 0 : 1;
20310 return DCI.DAG.getNode(
20312 DCI.DAG.getTargetConstant(EltToExtract, dl, MVT::i32));
20317SDValue PPCTargetLowering::combineMUL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20318 SelectionDAG &DAG = DCI.DAG;
20321 if (!ConstOpOrElement)
20329 auto IsProfitable = [
this](
bool IsNeg,
bool IsAddOne, EVT VT) ->
bool {
20330 switch (this->Subtarget.getCPUDirective()) {
20353 return IsAddOne && IsNeg ? VT.
isVector() :
true;
20357 EVT VT =
N->getValueType(0);
20362 APInt MulAmtAbs = MulAmt.
abs();
20364 if ((MulAmtAbs - 1).isPowerOf2()) {
20368 if (!IsProfitable(IsNeg,
true, VT))
20381 }
else if ((MulAmtAbs + 1).isPowerOf2()) {
20385 if (!IsProfitable(IsNeg,
false, VT))
20406 DAGCombinerInfo &DCI)
const {
20410 SDNodeFlags
Flags =
N->getFlags();
20411 EVT VT =
N->getValueType(0);
20412 SelectionDAG &DAG = DCI.DAG;
20413 unsigned Opc =
N->getOpcode();
20415 bool LegalOps = !DCI.isBeforeLegalizeOps();
20423 if (!
Flags.hasNoSignedZeros())
20439bool PPCTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
20441 if (!Subtarget.is64BitELFABI())
20451 if (!TM.Options.GuaranteedTailCallOpt &&
DisableSCO)
20456 if (!Callee ||
Callee->isVarArg())
20469bool PPCTargetLowering::
20470isMaskAndCmp0FoldingBeneficial(
const Instruction &AndI)
const {
20475 if (CI->getBitWidth() > 64)
20477 int64_t ConstVal = CI->getZExtValue();
20479 (
isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF));
20488PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(
unsigned Flags)
const {
20494 if ((Flags & FlagSet) == FlagSet)
20497 if ((Flags & FlagSet) == FlagSet)
20500 if ((Flags & FlagSet) == FlagSet)
20503 if ((Flags & FlagSet) == FlagSet)
20524 if ((FrameIndexAlign % 4) != 0)
20525 FlagSet &=
~PPC::MOF_RPlusSImm16Mult4;
20526 if ((FrameIndexAlign % 16) != 0)
20527 FlagSet &=
~PPC::MOF_RPlusSImm16Mult16;
20531 if ((FrameIndexAlign % 4) == 0)
20533 if ((FrameIndexAlign % 16) == 0)
20546 auto SetAlignFlagsForImm = [&](
uint64_t Imm) {
20547 if ((Imm & 0x3) == 0)
20549 if ((Imm & 0xf) == 0)
20555 const APInt &ConstImm = CN->getAPIntValue();
20574 const APInt &ConstImm = CN->getAPIntValue();
20584 }
else if (
RHS.getOpcode() == PPCISD::Lo && !
RHS.getConstantOperandVal(1))
20595 return (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR ||
20604unsigned PPCTargetLowering::computeMOFlags(
const SDNode *Parent,
SDValue N,
20609 if (!Subtarget.hasP9Vector())
20614 if (Subtarget.hasPrefixInstrs())
20617 if (Subtarget.hasSPE())
20626 unsigned ParentOp = Parent->
getOpcode();
20630 if ((
ID == Intrinsic::ppc_vsx_lxvp) || (
ID == Intrinsic::ppc_vsx_stxvp)) {
20631 SDValue IntrinOp = (
ID == Intrinsic::ppc_vsx_lxvp)
20643 if (LSB->isIndexed())
20649 assert(MN &&
"Parent should be a MemSDNode!");
20654 "Not expecting scalar integers larger than 16 bytes!");
20657 else if (
Size == 32)
20664 else if (
Size == 256) {
20665 assert(Subtarget.pairedVectorMemops() &&
20666 "256-bit vectors are only available when paired vector memops is "
20674 else if (MemVT == MVT::f128 || MemVT.
isVector())
20705 FlagSet &= ~PPC::MOF_NoExt;
20710 bool IsNonP1034BitConst =
20714 IsNonP1034BitConst)
20727 int16_t ForceXFormImm = 0;
20730 Disp =
N.getOperand(0);
20731 Base =
N.getOperand(1);
20742 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
20743 Disp =
N.getOperand(0);
20744 Base =
N.getOperand(1);
20749 Disp = DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20758 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
20764 if (PartVT == MVT::f64 &&
20765 (ValVT == MVT::i32 || ValVT == MVT::i16 || ValVT == MVT::i8)) {
20774SDValue PPCTargetLowering::lowerToLibCall(
const char *LibCallName,
SDValue Op,
20778 EVT RetVT =
Op.getValueType();
20785 EVT ArgVT =
N.getValueType();
20789 Entry.IsZExt = !Entry.IsSExt;
20790 Args.push_back(Entry);
20798 (RetTy ==
F.getReturnType() ||
F.getReturnType()->isVoidTy());
20811SDValue PPCTargetLowering::lowerLibCallBasedOnType(
20812 const char *LibCallFloatName,
const char *LibCallDoubleName,
SDValue Op,
20814 if (
Op.getValueType() == MVT::f32)
20815 return lowerToLibCall(LibCallFloatName,
Op, DAG);
20817 if (
Op.getValueType() == MVT::f64)
20818 return lowerToLibCall(LibCallDoubleName,
Op, DAG);
20823bool PPCTargetLowering::isLowringToMASSFiniteSafe(
SDValue Op)
const {
20824 SDNodeFlags
Flags =
Op.getNode()->getFlags();
20825 return isLowringToMASSSafe(
Op) &&
Flags.hasNoSignedZeros() &&
20829bool PPCTargetLowering::isLowringToMASSSafe(
SDValue Op)
const {
20830 return Op.getNode()->getFlags().hasApproximateFuncs();
20833bool PPCTargetLowering::isScalarMASSConversionEnabled()
const {
20837SDValue PPCTargetLowering::lowerLibCallBase(
const char *LibCallDoubleName,
20838 const char *LibCallFloatName,
20839 const char *LibCallDoubleNameFinite,
20840 const char *LibCallFloatNameFinite,
20843 if (!isScalarMASSConversionEnabled() || !isLowringToMASSSafe(
Op))
20846 if (!isLowringToMASSFiniteSafe(
Op))
20847 return lowerLibCallBasedOnType(LibCallFloatName, LibCallDoubleName,
Op,
20850 return lowerLibCallBasedOnType(LibCallFloatNameFinite,
20851 LibCallDoubleNameFinite,
Op, DAG);
20855 return lowerLibCallBase(
"__xl_pow",
"__xl_powf",
"__xl_pow_finite",
20856 "__xl_powf_finite",
Op, DAG);
20860 return lowerLibCallBase(
"__xl_sin",
"__xl_sinf",
"__xl_sin_finite",
20861 "__xl_sinf_finite",
Op, DAG);
20865 return lowerLibCallBase(
"__xl_cos",
"__xl_cosf",
"__xl_cos_finite",
20866 "__xl_cosf_finite",
Op, DAG);
20870 return lowerLibCallBase(
"__xl_log",
"__xl_logf",
"__xl_log_finite",
20871 "__xl_logf_finite",
Op, DAG);
20875 return lowerLibCallBase(
"__xl_log10",
"__xl_log10f",
"__xl_log10_finite",
20876 "__xl_log10f_finite",
Op, DAG);
20880 return lowerLibCallBase(
"__xl_exp",
"__xl_expf",
"__xl_exp_finite",
20881 "__xl_expf_finite",
Op, DAG);
20906 unsigned Flags = computeMOFlags(Parent,
N, DAG);
20917 assert(Subtarget.isUsingPCRelativeCalls() &&
20918 "Must be using PC-Relative calls when a valid PC-Relative node is "
20948 Disp =
N.getOperand(1).getOperand(0);
20953 Base =
N.getOperand(0);
20961 EVT CNType = CN->getValueType(0);
20962 uint64_t CNImm = CN->getZExtValue();
20973 if ((CNType == MVT::i32 ||
isInt<32>(CNImm)) &&
20975 int32_t Addr = (int32_t)CNImm;
20980 uint32_t LIS = CNType == MVT::i32 ? PPC::LIS : PPC::LIS8;
20996 unsigned Opcode =
N.getOpcode();
21004 Base =
N.getOperand(0);
21023 Base = FI ?
N :
N.getOperand(1);
21024 Disp = FI ? DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
21035 bool IsVarArg)
const {
21045 return Subtarget.isPPC64() && Subtarget.hasQuadwordAtomics();
21082 return Intrinsic::ppc_atomicrmw_xchg_i128;
21084 return Intrinsic::ppc_atomicrmw_add_i128;
21086 return Intrinsic::ppc_atomicrmw_sub_i128;
21088 return Intrinsic::ppc_atomicrmw_and_i128;
21090 return Intrinsic::ppc_atomicrmw_or_i128;
21092 return Intrinsic::ppc_atomicrmw_xor_i128;
21094 return Intrinsic::ppc_atomicrmw_nand_i128;
21102 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21106 Value *IncrLo = Builder.CreateTrunc(Incr, Int64Ty,
"incr_lo");
21108 Builder.CreateTrunc(Builder.CreateLShr(Incr, 64), Int64Ty,
"incr_hi");
21109 Value *LoHi = Builder.CreateIntrinsic(
21111 {AlignedAddr, IncrLo, IncrHi});
21112 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21113 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21114 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
21115 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
21116 return Builder.CreateOr(
21117 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
21124 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21130 Value *CmpLo = Builder.CreateTrunc(CmpVal, Int64Ty,
"cmp_lo");
21132 Builder.CreateTrunc(Builder.CreateLShr(CmpVal, 64), Int64Ty,
"cmp_hi");
21133 Value *NewLo = Builder.CreateTrunc(NewVal, Int64Ty,
"new_lo");
21135 Builder.CreateTrunc(Builder.CreateLShr(NewVal, 64), Int64Ty,
"new_hi");
21138 Builder.CreateCall(IntCmpXchg, {AlignedAddr, CmpLo, CmpHi, NewLo, NewHi});
21140 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21141 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21142 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
21143 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
21144 return Builder.CreateOr(
21145 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
21149 return Subtarget.useCRBits();
21154bool PPCTargetLowering::isShuffleMaskLegal(
ArrayRef<int> Mask,
EVT VT)
const {
21165 DAGCombinerInfo &DCI)
const {
21170 EVT ResVT =
N->getValueType(0);
21172 EVT SrcVT = Src.getValueType();
21177 if (ResVT != MVT::i16 && ResVT != MVT::i8)
21180 GenerateVBPERM(DAG, dl, Src, SrcVT, TruncResVT, IsLittleEndian);
21193 bool IsV16i8 = (ResVT == MVT::v16i1 && SrcVT == MVT::v16i8);
21194 bool IsV8i16 = (ResVT == MVT::v8i1 && SrcVT == MVT::v8i16);
21195 bool IsV8i8 = (ResVT == MVT::v8i1 && SrcVT == MVT::v8i8);
21197 if (!IsV16i8 && !IsV8i16 && !IsV8i8)
21205 SmallVector<int, 16> BitIndices(16, 128);
21209 BitIndices[Idx] = EltSize * (NumElts - Idx) - 1;
21210 if (IsV8i8 && IsLE)
21211 BitIndices[Idx] += 64;
21214 std::reverse(BitIndices.begin(), BitIndices.end());
21216 for (
auto Idx : BitIndices)
21221 DAG.
getConstant(Intrinsic::ppc_altivec_vbpermq, dl, MVT::i32),
21229 bool BVNIsConstantSplat,
21230 unsigned SplatBitSize)
const {
21232 if (!BVNIsConstantSplat || !Subtarget.hasVSX() || !Subtarget.hasP8Vector() ||
21233 Subtarget.hasP10Vector())
21236 EVT VT =
Op->getValueType(0);
21237 if (!((SplatBitSize == 64 && VT == MVT::v2f64) ||
21238 (SplatBitSize == 32 && VT == MVT::v4f32)))
21245 APFloat APFloatVal = CN->getValueAPF();
21247 APSInt IntResult(16,
false);
21250 if (!(IsExact && IntResult <= 15 && IntResult >= -16 && !APFloatVal.
isZero()))
21253 int64_t
IntVal = IntResult.getSExtValue();
21258 if (SplatBitSize == 64)
21261 DAG.
getConstant(Intrinsic::ppc_vsx_xvcvsxwdp, dl, MVT::i32), IntSplat);
21263 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.