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) {
648 if (Subtarget.is64BitELFABI()) {
659 }
else if (Subtarget.is32BitELFABI()) {
667 if (Subtarget.is32BitELFABI())
683 if (Subtarget.isISA3_0() && isPPC64) {
711 if (Subtarget.hasSPE()) {
733 if (Subtarget.has64BitSupport()) {
748 if (Subtarget.hasLFIWAX() || isPPC64) {
754 if (Subtarget.hasSPE()) {
764 if (Subtarget.hasFPCVT()) {
765 if (Subtarget.has64BitSupport()) {
786 if (Subtarget.use64BitRegs()) {
804 if (Subtarget.has64BitSupport()) {
811 if (Subtarget.hasVSX()) {
824 if (Subtarget.hasAltivec()) {
825 for (
MVT VT : { MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
842 if (VT.getSizeInBits() <= 128 && VT.getScalarSizeInBits() <= 64) {
855 if (Subtarget.hasVSX()) {
864 if (Subtarget.hasP8Altivec() && (VT.SimpleTy != MVT::v1i128)) {
874 if (Subtarget.hasP9Altivec() && (VT.SimpleTy != MVT::v1i128))
948 if (!Subtarget.hasP8Vector()) {
990 if (Subtarget.hasAltivec())
991 for (
auto VT : {MVT::v4i32, MVT::v8i16, MVT::v16i8})
994 if (Subtarget.hasP8Altivec())
1005 if (Subtarget.hasVSX()) {
1011 if (Subtarget.hasP8Altivec())
1016 if (Subtarget.isISA3_1()) {
1062 if (Subtarget.hasVSX()) {
1065 if (Subtarget.hasP8Vector()) {
1069 if (Subtarget.hasDirectMove() && isPPC64) {
1118 if (Subtarget.hasP8Vector())
1127 if (Subtarget.hasP8Altivec()) {
1154 if (Subtarget.isISA3_1())
1257 if (Subtarget.hasP8Altivec()) {
1262 if (Subtarget.hasP9Vector()) {
1267 if (Subtarget.useCRBits()) {
1327 }
else if (Subtarget.hasVSX()) {
1352 for (
MVT VT : {MVT::f32, MVT::f64}) {
1371 if (Subtarget.hasP9Altivec()) {
1372 if (Subtarget.isISA3_1()) {
1395 if (Subtarget.hasP10Vector()) {
1410 if (Subtarget.pairedVectorMemops()) {
1415 if (Subtarget.hasMMA()) {
1416 if (Subtarget.isISAFuture()) {
1432 if (Subtarget.has64BitSupport())
1435 if (Subtarget.isISA3_1())
1453 if (Subtarget.hasAltivec()) {
1471 if (Subtarget.hasFPCVT())
1474 if (Subtarget.useCRBits())
1483 if (Subtarget.useCRBits()) {
1487 if (Subtarget.hasP8Vector())
1492 if (Subtarget.useCRBits()) {
1508 auto CPUDirective = Subtarget.getCPUDirective();
1509 switch (CPUDirective) {
1532 if (Subtarget.enableMachineScheduler())
1606void PPCTargetLowering::initializeAddrModeMap() {
1657 if (MaxAlign == MaxMaxAlign)
1660 if (MaxMaxAlign >= 32 &&
1661 VTy->getPrimitiveSizeInBits().getFixedValue() >= 256)
1662 MaxAlign =
Align(32);
1663 else if (VTy->getPrimitiveSizeInBits().getFixedValue() >= 128 &&
1665 MaxAlign =
Align(16);
1669 if (EltAlign > MaxAlign)
1670 MaxAlign = EltAlign;
1672 for (
auto *EltTy : STy->elements()) {
1675 if (EltAlign > MaxAlign)
1676 MaxAlign = EltAlign;
1677 if (MaxAlign == MaxMaxAlign)
1690 if (Subtarget.hasAltivec())
1696 return Subtarget.useSoftFloat();
1700 return Subtarget.hasSPE();
1708 Type *VectorTy,
unsigned ElemSizeInBits,
unsigned &Index)
const {
1709 if (!Subtarget.isPPC64() || !Subtarget.hasVSX())
1713 if (VTy->getScalarType()->isIntegerTy()) {
1715 if (ElemSizeInBits == 32) {
1716 Index = Subtarget.isLittleEndian() ? 2 : 1;
1719 if (ElemSizeInBits == 64) {
1720 Index = Subtarget.isLittleEndian() ? 1 : 0;
1731 return Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
1748 return CFP->getValueAPF().isZero();
1753 return CFP->getValueAPF().isZero();
1761 return Op < 0 ||
Op == Val;
1773 if (ShuffleKind == 0) {
1776 for (
unsigned i = 0; i != 16; ++i)
1779 }
else if (ShuffleKind == 2) {
1782 for (
unsigned i = 0; i != 16; ++i)
1785 }
else if (ShuffleKind == 1) {
1786 unsigned j = IsLE ? 0 : 1;
1787 for (
unsigned i = 0; i != 8; ++i)
1804 if (ShuffleKind == 0) {
1807 for (
unsigned i = 0; i != 16; i += 2)
1811 }
else if (ShuffleKind == 2) {
1814 for (
unsigned i = 0; i != 16; i += 2)
1818 }
else if (ShuffleKind == 1) {
1819 unsigned j = IsLE ? 0 : 2;
1820 for (
unsigned i = 0; i != 8; i += 2)
1841 if (!Subtarget.hasP8Vector())
1845 if (ShuffleKind == 0) {
1848 for (
unsigned i = 0; i != 16; i += 4)
1854 }
else if (ShuffleKind == 2) {
1857 for (
unsigned i = 0; i != 16; i += 4)
1863 }
else if (ShuffleKind == 1) {
1864 unsigned j = IsLE ? 0 : 4;
1865 for (
unsigned i = 0; i != 8; i += 4)
1882 unsigned LHSStart,
unsigned RHSStart) {
1883 if (
N->getValueType(0) != MVT::v16i8)
1885 assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) &&
1886 "Unsupported merge size!");
1888 for (
unsigned i = 0; i != 8/UnitSize; ++i)
1889 for (
unsigned j = 0; j != UnitSize; ++j) {
1891 LHSStart+j+i*UnitSize) ||
1893 RHSStart+j+i*UnitSize))
1908 if (ShuffleKind == 1)
1910 else if (ShuffleKind == 2)
1915 if (ShuffleKind == 1)
1917 else if (ShuffleKind == 0)
1933 if (ShuffleKind == 1)
1935 else if (ShuffleKind == 2)
1940 if (ShuffleKind == 1)
1942 else if (ShuffleKind == 0)
1992 unsigned RHSStartValue) {
1993 if (
N->getValueType(0) != MVT::v16i8)
1996 for (
unsigned i = 0; i < 2; ++i)
1997 for (
unsigned j = 0; j < 4; ++j)
1999 i*RHSStartValue+j+IndexOffset) ||
2001 i*RHSStartValue+j+IndexOffset+8))
2023 unsigned indexOffset = CheckEven ? 4 : 0;
2024 if (ShuffleKind == 1)
2026 else if (ShuffleKind == 2)
2032 unsigned indexOffset = CheckEven ? 0 : 4;
2033 if (ShuffleKind == 1)
2035 else if (ShuffleKind == 0)
2051 if (
N->getValueType(0) != MVT::v16i8)
2058 for (i = 0; i != 16 && SVOp->
getMaskElt(i) < 0; ++i)
2061 if (i == 16)
return -1;
2066 if (ShiftAmt < i)
return -1;
2071 if ((ShuffleKind == 0 && !isLE) || (ShuffleKind == 2 && isLE)) {
2073 for (++i; i != 16; ++i)
2076 }
else if (ShuffleKind == 1) {
2078 for (++i; i != 16; ++i)
2085 ShiftAmt = 16 - ShiftAmt;
2094 EVT VT =
N->getValueType(0);
2095 if (VT == MVT::v2i64 || VT == MVT::v2f64)
2096 return EltSize == 8 &&
N->getMaskElt(0) ==
N->getMaskElt(1);
2099 EltSize <= 8 &&
"Can only handle 1,2,4,8 byte element sizes");
2103 if (
N->getMaskElt(0) % EltSize != 0)
2108 unsigned ElementBase =
N->getMaskElt(0);
2111 if (ElementBase >= 16)
2116 for (
unsigned i = 1; i != EltSize; ++i)
2117 if (
N->getMaskElt(i) < 0 ||
N->getMaskElt(i) != (
int)(i+ElementBase))
2120 for (
unsigned i = EltSize, e = 16; i != e; i += EltSize) {
2122 if (
N->getMaskElt(i) < 0) {
2123 for (
unsigned j = 1; j != EltSize; ++j)
2124 if (
N->getMaskElt(i + j) >= 0)
2127 for (
unsigned j = 0; j != EltSize; ++j)
2128 if (
N->getMaskElt(i + j) !=
N->getMaskElt(j))
2145 assert((Width == 2 || Width == 4 || Width == 8 || Width == 16) &&
2146 "Unexpected element width.");
2147 assert((StepLen == 1 || StepLen == -1) &&
"Unexpected element width.");
2149 unsigned NumOfElem = 16 / Width;
2150 unsigned MaskVal[16];
2151 for (
unsigned i = 0; i < NumOfElem; ++i) {
2152 MaskVal[0] =
N->getMaskElt(i * Width);
2153 if ((StepLen == 1) && (MaskVal[0] % Width)) {
2155 }
else if ((StepLen == -1) && ((MaskVal[0] + 1) % Width)) {
2159 for (
unsigned int j = 1; j < Width; ++j) {
2160 MaskVal[j] =
N->getMaskElt(i * Width + j);
2161 if (MaskVal[j] != MaskVal[j-1] + StepLen) {
2171 unsigned &InsertAtByte,
bool &Swap,
bool IsLE) {
2176 unsigned M0 =
N->getMaskElt(0) / 4;
2177 unsigned M1 =
N->getMaskElt(4) / 4;
2178 unsigned M2 =
N->getMaskElt(8) / 4;
2179 unsigned M3 =
N->getMaskElt(12) / 4;
2180 unsigned LittleEndianShifts[] = { 2, 1, 0, 3 };
2181 unsigned BigEndianShifts[] = { 3, 0, 1, 2 };
2186 if ((
M0 > 3 &&
M1 == 1 && M2 == 2 && M3 == 3) ||
2187 (
M0 < 4 &&
M1 == 5 && M2 == 6 && M3 == 7)) {
2188 ShiftElts = IsLE ? LittleEndianShifts[
M0 & 0x3] : BigEndianShifts[
M0 & 0x3];
2189 InsertAtByte = IsLE ? 12 : 0;
2194 if ((
M1 > 3 &&
M0 == 0 && M2 == 2 && M3 == 3) ||
2195 (
M1 < 4 &&
M0 == 4 && M2 == 6 && M3 == 7)) {
2196 ShiftElts = IsLE ? LittleEndianShifts[
M1 & 0x3] : BigEndianShifts[
M1 & 0x3];
2197 InsertAtByte = IsLE ? 8 : 4;
2202 if ((M2 > 3 &&
M0 == 0 &&
M1 == 1 && M3 == 3) ||
2203 (M2 < 4 &&
M0 == 4 &&
M1 == 5 && M3 == 7)) {
2204 ShiftElts = IsLE ? LittleEndianShifts[M2 & 0x3] : BigEndianShifts[M2 & 0x3];
2205 InsertAtByte = IsLE ? 4 : 8;
2210 if ((M3 > 3 &&
M0 == 0 &&
M1 == 1 && M2 == 2) ||
2211 (M3 < 4 &&
M0 == 4 &&
M1 == 5 && M2 == 6)) {
2212 ShiftElts = IsLE ? LittleEndianShifts[M3 & 0x3] : BigEndianShifts[M3 & 0x3];
2213 InsertAtByte = IsLE ? 0 : 12;
2220 if (
N->getOperand(1).isUndef()) {
2223 unsigned XXINSERTWSrcElem = IsLE ? 2 : 1;
2224 if (
M0 == XXINSERTWSrcElem &&
M1 == 1 && M2 == 2 && M3 == 3) {
2225 InsertAtByte = IsLE ? 12 : 0;
2228 if (
M0 == 0 &&
M1 == XXINSERTWSrcElem && M2 == 2 && M3 == 3) {
2229 InsertAtByte = IsLE ? 8 : 4;
2232 if (
M0 == 0 &&
M1 == 1 && M2 == XXINSERTWSrcElem && M3 == 3) {
2233 InsertAtByte = IsLE ? 4 : 8;
2236 if (
M0 == 0 &&
M1 == 1 && M2 == 2 && M3 == XXINSERTWSrcElem) {
2237 InsertAtByte = IsLE ? 0 : 12;
2246 bool &Swap,
bool IsLE) {
2247 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2253 unsigned M0 =
N->getMaskElt(0) / 4;
2254 unsigned M1 =
N->getMaskElt(4) / 4;
2255 unsigned M2 =
N->getMaskElt(8) / 4;
2256 unsigned M3 =
N->getMaskElt(12) / 4;
2260 if (
N->getOperand(1).isUndef()) {
2261 assert(
M0 < 4 &&
"Indexing into an undef vector?");
2262 if (
M1 != (
M0 + 1) % 4 || M2 != (
M1 + 1) % 4 || M3 != (M2 + 1) % 4)
2265 ShiftElts = IsLE ? (4 -
M0) % 4 :
M0;
2271 if (
M1 != (
M0 + 1) % 8 || M2 != (
M1 + 1) % 8 || M3 != (M2 + 1) % 8)
2275 if (
M0 == 0 ||
M0 == 7 ||
M0 == 6 ||
M0 == 5) {
2280 ShiftElts = (8 -
M0) % 8;
2281 }
else if (
M0 == 4 ||
M0 == 3 ||
M0 == 2 ||
M0 == 1) {
2286 ShiftElts = (4 -
M0) % 4;
2291 if (
M0 == 0 ||
M0 == 1 ||
M0 == 2 ||
M0 == 3) {
2296 }
else if (
M0 == 4 ||
M0 == 5 ||
M0 == 6 ||
M0 == 7) {
2308 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2313 for (
int i = 0; i < 16; i += Width)
2314 if (
N->getMaskElt(i) != i + Width - 1)
2345 bool &Swap,
bool IsLE) {
2346 assert(
N->getValueType(0) == MVT::v16i8 &&
"Shuffle vector expects v16i8");
2352 unsigned M0 =
N->getMaskElt(0) / 8;
2353 unsigned M1 =
N->getMaskElt(8) / 8;
2354 assert(((
M0 |
M1) < 4) &&
"A mask element out of bounds?");
2358 if (
N->getOperand(1).isUndef()) {
2359 if ((
M0 |
M1) < 2) {
2360 DM = IsLE ? (((
~M1) & 1) << 1) + ((~
M0) & 1) : (
M0 << 1) + (
M1 & 1);
2368 if (
M0 > 1 &&
M1 < 2) {
2378 DM = (((
~M1) & 1) << 1) + ((~
M0) & 1);
2383 }
else if (
M0 > 1 &&
M1 < 2) {
2391 DM = (
M0 << 1) + (
M1 & 1);
2406 if (VT == MVT::v2i64 || VT == MVT::v2f64)
2411 return (16 / EltSize) - 1 - (SVOp->
getMaskElt(0) / EltSize);
2427 unsigned EltSize = 16/
N->getNumOperands();
2428 if (EltSize < ByteSize) {
2429 unsigned Multiple = ByteSize/EltSize;
2431 assert(Multiple > 1 && Multiple <= 4 &&
"How can this happen?");
2434 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
2435 if (
N->getOperand(i).isUndef())
continue;
2439 if (!UniquedVals[i&(Multiple-1)].
getNode())
2440 UniquedVals[i&(Multiple-1)] =
N->getOperand(i);
2441 else if (UniquedVals[i&(Multiple-1)] !=
N->getOperand(i))
2451 bool LeadingZero =
true;
2452 bool LeadingOnes =
true;
2453 for (
unsigned i = 0; i != Multiple-1; ++i) {
2454 if (!UniquedVals[i].
getNode())
continue;
2461 if (!UniquedVals[Multiple-1].
getNode())
2468 if (!UniquedVals[Multiple-1].
getNode())
2479 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
2480 if (
N->getOperand(i).isUndef())
continue;
2482 OpVal =
N->getOperand(i);
2483 else if (OpVal !=
N->getOperand(i))
2489 unsigned ValSizeInBytes = EltSize;
2492 Value = CN->getZExtValue();
2494 assert(CN->getValueType(0) == MVT::f32 &&
"Only one legal FP vector type!");
2501 if (ValSizeInBytes < ByteSize)
return SDValue();
2512 if (MaskVal == 0)
return SDValue();
2532 Imm = (int16_t)
N->getAsZExtVal();
2533 if (
N->getValueType(0) == MVT::i32)
2534 return Imm == (int32_t)
N->getAsZExtVal();
2536 return Imm == (int64_t)
N->getAsZExtVal();
2554 return (~(LHSKnown.
Zero | RHSKnown.
Zero) == 0);
2562 for (
SDNode *U :
N->users()) {
2564 if (Memop->getMemoryVT() == MVT::f64) {
2565 Base =
N.getOperand(0);
2566 Index =
N.getOperand(1);
2609 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm)))
2611 if (
N.getOperand(1).getOpcode() == PPCISD::Lo)
2614 Base =
N.getOperand(0);
2615 Index =
N.getOperand(1);
2617 }
else if (
N.getOpcode() ==
ISD::OR) {
2619 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm)))
2631 if (~(LHSKnown.
Zero | RHSKnown.
Zero) == 0) {
2632 Base =
N.getOperand(0);
2633 Index =
N.getOperand(1);
2703 (!EncodingAlignment ||
isAligned(*EncodingAlignment, imm))) {
2709 Base =
N.getOperand(0);
2712 }
else if (
N.getOperand(1).getOpcode() == PPCISD::Lo) {
2714 assert(!
N.getOperand(1).getConstantOperandVal(1) &&
2715 "Cannot handle constant offsets yet!");
2716 Disp =
N.getOperand(1).getOperand(0);
2721 Base =
N.getOperand(0);
2724 }
else if (
N.getOpcode() ==
ISD::OR) {
2727 (!EncodingAlignment ||
isAligned(*EncodingAlignment, imm))) {
2741 Base =
N.getOperand(0);
2754 (!EncodingAlignment ||
isAligned(*EncodingAlignment, Imm))) {
2757 CN->getValueType(0));
2762 if ((CN->getValueType(0) == MVT::i32 ||
2763 (int64_t)CN->getZExtValue() == (
int)CN->getZExtValue()) &&
2764 (!EncodingAlignment ||
2765 isAligned(*EncodingAlignment, CN->getZExtValue()))) {
2766 int Addr = (int)CN->getZExtValue();
2773 unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8;
2794 if (
N.getValueType() != MVT::i64)
2807 Base =
N.getOperand(0);
2823 Base =
N.getOperand(0);
2856 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
2857 Base =
N.getOperand(0);
2858 Index =
N.getOperand(1);
2880 if (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR)
2901 EVT MemVT = LD->getMemoryVT();
2908 if (!ST.hasP8Vector())
2913 if (!ST.hasP9Vector())
2925 if (
Use.getResNo() == 0 &&
2927 Use.
getUser()->getOpcode() != PPCISD::SCALAR_TO_VECTOR_PERMUTED)
2947 Ptr = LD->getBasePtr();
2948 VT = LD->getMemoryVT();
2949 Alignment = LD->getAlign();
2951 Ptr = ST->getBasePtr();
2952 VT = ST->getMemoryVT();
2953 Alignment = ST->getAlign();
2992 if (VT != MVT::i64) {
2997 if (Alignment <
Align(4))
3007 if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 &&
3024 unsigned &HiOpFlags,
unsigned &LoOpFlags,
3066 EVT VT = Subtarget.getScalarIntVT();
3068 : Subtarget.isAIXABI()
3073 PPCISD::TOC_ENTRY, dl, DAG.
getVTList(VT, MVT::Other),
Ops, VT,
3080 EVT PtrVT =
Op.getValueType();
3086 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3087 if (Subtarget.isUsingPCRelativeCalls()) {
3092 return DAG.
getNode(PPCISD::MAT_PCREL_ADDR,
DL, Ty, ConstPool);
3096 return getTOCEntry(DAG, SDLoc(CP), GA);
3099 unsigned MOHiFlag, MOLoFlag;
3103 if (IsPIC && Subtarget.isSVR4ABI()) {
3106 return getTOCEntry(DAG, SDLoc(CP), GA);
3129 if (Subtarget.isPPC64() || Subtarget.isAIXABI())
3136 if (!Subtarget.isPPC64() || Subtarget.isAIXABI())
3153 if (!Subtarget.isPPC64() || Subtarget.isAIXABI())
3166 EVT PtrVT =
Op.getValueType();
3184 return getTOCEntry(DAG,
SDLoc(JT), GA);
3187 unsigned MOHiFlag, MOLoFlag;
3191 if (IsPIC && Subtarget.isSVR4ABI()) {
3194 return getTOCEntry(DAG, SDLoc(GA), GA);
3204 EVT PtrVT =
Op.getValueType();
3209 if (Subtarget.isUsingPCRelativeCalls()) {
3220 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3223 return getTOCEntry(DAG, SDLoc(BASDN), GA);
3232 unsigned MOHiFlag, MOLoFlag;
3242 if (Subtarget.isAIXABI())
3243 return LowerGlobalTLSAddressAIX(
Op, DAG);
3245 return LowerGlobalTLSAddressLinux(
Op, DAG);
3267 if (
I.getOpcode() == Instruction::Call)
3269 if (
Function *CF = CI->getCalledFunction())
3270 if (CF->isDeclaration() &&
3271 CF->getIntrinsicID() == Intrinsic::threadlocal_address)
3279 unsigned TLSGVCnt = TLSGV.
size();
3289 <<
" function is using the TLS-IE model for TLS-LD access.\n");
3302 const GlobalValue *GV = GA->
getGlobal();
3304 bool Is64Bit = Subtarget.isPPC64();
3308 if (Subtarget.hasAIXShLibTLSModelOpt())
3318 bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS();
3319 bool HasAIXSmallTLSGlobalAttr =
false;
3322 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3326 if (GVar->hasAttribute(
"aix-small-tls"))
3327 HasAIXSmallTLSGlobalAttr =
true;
3346 if ((HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr) &&
3347 IsTLSLocalExecModel) {
3352 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA, TLSReg);
3362 TLSReg = DAG.
getNode(PPCISD::GET_TPOINTER, dl, PtrVT);
3367 if (HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr)
3369 "currently only supported on AIX (64-bit mode).");
3371 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
3375 bool HasAIXSmallLocalDynamicTLS = Subtarget.hasAIXSmallLocalDynamicTLS();
3379 if (!Is64Bit && HasAIXSmallLocalDynamicTLS)
3381 "currently only supported on AIX (64-bit mode).");
3389 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3392 GlobalVariable *TLSGV =
3396 assert(TLSGV &&
"Not able to create GV for _$TLSML.");
3399 SDValue ModuleHandleTOC = getTOCEntry(DAG, dl, ModuleHandleTGA);
3401 DAG.
getNode(PPCISD::TLSLD_AIX, dl, PtrVT, ModuleHandleTOC);
3410 if (HasAIXSmallLocalDynamicTLS) {
3415 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, VariableOffsetTGA,
3419 return DAG.
getNode(
ISD::ADD, dl, PtrVT, ModuleHandle, VariableOffset);
3432 SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3433 SDValue RegionHandle = getTOCEntry(DAG, dl, RegionHandleTGA);
3434 return DAG.
getNode(PPCISD::TLSGD_AIX, dl, PtrVT, VariableOffset,
3449 const GlobalValue *GV = GA->
getGlobal();
3451 bool is64bit = Subtarget.isPPC64();
3459 if (Subtarget.isUsingPCRelativeCalls()) {
3464 DAG.
getNode(PPCISD::TLS_LOCAL_EXEC_MAT_ADDR, dl, PtrVT, TGA);
3465 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, MatAddr);
3476 return DAG.
getNode(PPCISD::Lo, dl, PtrVT, TGALo,
Hi);
3480 bool IsPCRel = Subtarget.isUsingPCRelativeCalls();
3487 SDValue MatPCRel = DAG.
getNode(PPCISD::MAT_PCREL_ADDR, dl, PtrVT, TGA);
3489 MachinePointerInfo());
3496 DAG.
getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl, PtrVT, GOTReg, TGA);
3498 if (!TM.isPositionIndependent())
3499 GOTPtr = DAG.
getNode(PPCISD::PPC32_GOT, dl, PtrVT);
3505 TPOffset = DAG.
getNode(PPCISD::LD_GOT_TPREL_L, dl, PtrVT, TGA, GOTPtr);
3507 return DAG.
getNode(PPCISD::ADD_TLS, dl, PtrVT, TPOffset, TGATLS);
3511 if (Subtarget.isUsingPCRelativeCalls()) {
3514 return DAG.
getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3522 GOTPtr = DAG.
getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT,
3530 return DAG.
getNode(PPCISD::ADDI_TLSGD_L_ADDR, dl, PtrVT,
3535 if (Subtarget.isUsingPCRelativeCalls()) {
3539 DAG.
getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA);
3540 return DAG.
getNode(PPCISD::PADDI_DTPREL, dl, PtrVT, MatPCRel, TGA);
3548 GOTPtr = DAG.
getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT,
3557 PtrVT, GOTPtr, TGA, TGA);
3559 PtrVT, TLSAddr, TGA);
3560 return DAG.
getNode(PPCISD::ADDI_DTPREL_L, dl, PtrVT, DtvOffsetHi, TGA);
3568 EVT PtrVT =
Op.getValueType();
3571 const GlobalValue *GV = GSDN->
getGlobal();
3575 if (Subtarget.is64BitELFABI() || Subtarget.isAIXABI()) {
3576 if (Subtarget.isUsingPCRelativeCalls()) {
3583 MachinePointerInfo());
3588 return DAG.
getNode(PPCISD::MAT_PCREL_ADDR,
DL, Ty, GA);
3593 return getTOCEntry(DAG,
DL, GA);
3596 unsigned MOHiFlag, MOLoFlag;
3600 if (IsPIC && Subtarget.isSVR4ABI()) {
3604 return getTOCEntry(DAG,
DL, GA);
3616 bool IsStrict =
Op->isStrictFPOpcode();
3617 const SDNodeFlags
Flags =
Op.getNode()->getFlags();
3623 EVT LHSVT =
LHS.getValueType();
3627 if (LHSVT == MVT::f128 ||
3628 (Subtarget.hasSPE() && (LHSVT == MVT::f32 || LHSVT == MVT::f64) &&
3629 (!
Flags.hasNoNaNs() || !
Flags.hasNoInfs()))) {
3630 assert(!Subtarget.hasP9Vector() &&
3631 "SETCC for f128 is already legal under Power9!");
3640 }
else if (LHSVT == MVT::f32 || LHSVT == MVT::f64) {
3644 assert(!IsStrict &&
"Don't know how to handle STRICT_FSETCC!");
3646 if (
Op.getValueType() == MVT::v2i64) {
3649 if (
LHS.getValueType() == MVT::v2i64) {
3657 int ShuffV[] = {1, 0, 3, 2};
3662 dl, MVT::v4i32, Shuff, SetCC32));
3679 if (
C->isAllOnes() ||
C->isZero())
3689 EVT VT =
Op.getValueType();
3697 const SDNodeFlags
Flags =
Op->getFlags();
3703 EVT LHSVT =
LHS.getValueType();
3706 assert(Subtarget.hasSPE() &&
"LowerBR_CC used only for targets with SPE");
3708 if ((LHSVT == MVT::f32 || LHSVT == MVT::f64) &&
Flags.hasNoNaNs() &&
3726 SDNode *
Node =
Op.getNode();
3727 EVT VT =
Node->getValueType(0);
3734 assert(!Subtarget.isPPC64() &&
"LowerVAARG is PPC32 only");
3738 VAListPtr, MachinePointerInfo(SV), MVT::i8);
3741 if (VT == MVT::i64) {
3760 FprPtr, MachinePointerInfo(SV), MVT::i8);
3771 DAG.
getLoad(MVT::i32, dl, InChain, OverflowAreaPtr, MachinePointerInfo());
3772 InChain = OverflowArea.
getValue(1);
3775 DAG.
getLoad(MVT::i32, dl, InChain, RegSaveAreaPtr, MachinePointerInfo());
3805 MachinePointerInfo(SV), MVT::i8);
3818 InChain = DAG.
getTruncStore(InChain, dl, OverflowArea, OverflowAreaPtr,
3819 MachinePointerInfo(), MVT::i32);
3821 return DAG.
getLoad(VT, dl, InChain, Result, MachinePointerInfo());
3825 assert(!Subtarget.isPPC64() &&
"LowerVACOPY is PPC32 only");
3831 Align(8),
false,
true,
nullptr, std::nullopt,
3832 MachinePointerInfo(), MachinePointerInfo());
3837 return Op.getOperand(0);
3842 PPCFunctionInfo &MFI = *MF.
getInfo<PPCFunctionInfo>();
3846 "Expecting Inline ASM node.");
3856 if (
Op.getOperand(
NumOps - 1).getValueType() == MVT::Glue)
3861 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(i));
3862 unsigned NumVals =
Flags.getNumOperandRegisters();
3865 switch (
Flags.getKind()) {
3876 for (; NumVals; --NumVals, ++i) {
3878 if (
Reg != PPC::LR &&
Reg != PPC::LR8)
3901 if (Subtarget.isAIXABI()) {
3905 uint64_t
PointerSize = Subtarget.isPPC64() ? 8 : 4;
3906 MaybeAlign PointerAlign(PointerSize);
3907 auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
3910 : MachineMemOperand::MONone;
3917 const Value *TrampolineAddr =
3927 DAG.
getLoad(PtrVT, dl, Chain, FPtr, MachinePointerInfo(Func, 0),
3928 PointerAlign, MMOFlags);
3930 OutChains[0] = DAG.
getStore(EPLoadChain, dl, LoadEntryPoint, Trmp,
3931 MachinePointerInfo(TrampolineAddr, 0));
3935 SDValue TOCFromDescriptorPtr =
3937 SDValue TOCReg = DAG.
getLoad(PtrVT, dl, Chain, TOCFromDescriptorPtr,
3938 MachinePointerInfo(Func, TOCPointerOffset),
3939 PointerAlign, MMOFlags);
3940 SDValue TrampolineTOCPointer =
3944 DAG.
getStore(TOCLoadChain, dl, TOCReg, TrampolineTOCPointer,
3945 MachinePointerInfo(TrampolineAddr, TOCPointerOffset));
3951 DAG.
getStore(Chain, dl, Nest, EnvPointer,
3952 MachinePointerInfo(TrampolineAddr, EnvPointerOffset));
3959 bool isPPC64 = (PtrVT == MVT::i64);
3963 Args.emplace_back(Trmp, IntPtrTy);
3966 DAG.
getConstant(isPPC64 ? 48 : 40, dl, Subtarget.getScalarIntVT()),
3968 Args.emplace_back(FPtr, IntPtrTy);
3969 Args.emplace_back(Nest, IntPtrTy);
3972 TargetLowering::CallLoweringInfo CLI(DAG);
3973 CLI.setDebugLoc(dl).setChain(Chain).setLibCallee(
3977 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3978 return CallResult.second;
3983 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
3988 if (Subtarget.isPPC64() || Subtarget.isAIXABI()) {
3993 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
3994 MachinePointerInfo(SV));
4028 uint64_t FrameOffset = PtrVT.getSizeInBits()/8;
4031 uint64_t StackOffset = PtrVT.getSizeInBits()/8 - 1;
4034 uint64_t FPROffset = 1;
4042 MachinePointerInfo(SV), MVT::i8);
4043 uint64_t nextOffset = FPROffset;
4050 MachinePointerInfo(SV, nextOffset), MVT::i8);
4051 nextOffset += StackOffset;
4052 nextPtr = DAG.
getNode(
ISD::ADD, dl, PtrVT, nextPtr, ConstStackOffset);
4055 SDValue thirdStore = DAG.
getStore(secondStore, dl, StackOffsetFI, nextPtr,
4056 MachinePointerInfo(SV, nextOffset));
4057 nextOffset += FrameOffset;
4058 nextPtr = DAG.
getNode(
ISD::ADD, dl, PtrVT, nextPtr, ConstFrameOffset);
4061 return DAG.
getStore(thirdStore, dl, FR, nextPtr,
4062 MachinePointerInfo(SV, nextOffset));
4067static const MCPhysReg FPR[] = {PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5,
4068 PPC::F6, PPC::F7, PPC::F8, PPC::F9, PPC::F10,
4069 PPC::F11, PPC::F12, PPC::F13};
4074 unsigned PtrByteSize) {
4076 if (Flags.isByVal())
4077 ArgSize = Flags.getByValSize();
4081 if (!Flags.isInConsecutiveRegs())
4082 ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4091 unsigned PtrByteSize) {
4092 Align Alignment(PtrByteSize);
4095 if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 ||
4096 ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 ||
4097 ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 ||
4098 ArgVT == MVT::v1i128 || ArgVT == MVT::f128)
4099 Alignment =
Align(16);
4102 if (Flags.isByVal()) {
4103 auto BVAlign = Flags.getNonZeroByValAlign();
4104 if (BVAlign > PtrByteSize) {
4105 if (BVAlign.value() % PtrByteSize != 0)
4107 "ByVal alignment is not a multiple of the pointer size");
4109 Alignment = BVAlign;
4114 if (Flags.isInConsecutiveRegs()) {
4118 if (Flags.isSplit() && OrigVT != MVT::ppcf128)
4132 unsigned PtrByteSize,
unsigned LinkageSize,
4133 unsigned ParamAreaSize,
unsigned &ArgOffset,
4134 unsigned &AvailableFPRs,
4135 unsigned &AvailableVRs) {
4136 bool UseMemory =
false;
4141 ArgOffset =
alignTo(ArgOffset, Alignment);
4144 if (ArgOffset >= LinkageSize + ParamAreaSize)
4149 if (Flags.isInConsecutiveRegsLast())
4150 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4153 if (ArgOffset > LinkageSize + ParamAreaSize)
4158 if (!Flags.isByVal()) {
4159 if (ArgVT == MVT::f32 || ArgVT == MVT::f64)
4160 if (AvailableFPRs > 0) {
4164 if (ArgVT == MVT::v4f32 || ArgVT == MVT::v4i32 ||
4165 ArgVT == MVT::v8i16 || ArgVT == MVT::v16i8 ||
4166 ArgVT == MVT::v2f64 || ArgVT == MVT::v2i64 ||
4167 ArgVT == MVT::v1i128 || ArgVT == MVT::f128)
4168 if (AvailableVRs > 0) {
4180 unsigned NumBytes) {
4184SDValue PPCTargetLowering::LowerFormalArguments(
4188 if (Subtarget.isAIXABI())
4189 return LowerFormalArguments_AIX(Chain, CallConv, isVarArg, Ins, dl, DAG,
4191 if (Subtarget.is64BitELFABI())
4192 return LowerFormalArguments_64SVR4(Chain, CallConv, isVarArg, Ins, dl, DAG,
4194 assert(Subtarget.is32BitELFABI());
4195 return LowerFormalArguments_32SVR4(Chain, CallConv, isVarArg, Ins, dl, DAG,
4199SDValue PPCTargetLowering::LowerFormalArguments_32SVR4(
4235 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
4241 const Align PtrAlign(4);
4249 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
4250 CCInfo.AllocateStack(LinkageSize, PtrAlign);
4253 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4254 CCValAssign &VA = ArgLocs[i];
4258 const TargetRegisterClass *RC;
4266 RC = &PPC::GPRCRegClass;
4269 if (Subtarget.hasP8Vector())
4270 RC = &PPC::VSSRCRegClass;
4271 else if (Subtarget.hasSPE())
4272 RC = &PPC::GPRCRegClass;
4274 RC = &PPC::F4RCRegClass;
4277 if (Subtarget.hasVSX())
4278 RC = &PPC::VSFRCRegClass;
4279 else if (Subtarget.hasSPE())
4281 RC = &PPC::GPRCRegClass;
4283 RC = &PPC::F8RCRegClass;
4288 RC = &PPC::VRRCRegClass;
4291 RC = &PPC::VRRCRegClass;
4295 RC = &PPC::VRRCRegClass;
4302 if (VA.
getLocVT() == MVT::f64 && Subtarget.hasSPE()) {
4303 assert(i + 1 < e &&
"No second half of double precision argument");
4308 if (!Subtarget.isLittleEndian())
4310 ArgValue = DAG.
getNode(PPCISD::BUILD_SPE64, dl, MVT::f64, ArgValueLo,
4315 ValVT == MVT::i1 ? MVT::i32 : ValVT);
4316 if (ValVT == MVT::i1)
4331 ArgOffset += ArgSize - ObjSize;
4349 CCByValInfo.AllocateStack(CCInfo.getStackSize(), PtrAlign);
4354 unsigned MinReservedArea = CCByValInfo.getStackSize();
4355 MinReservedArea = std::max(MinReservedArea, LinkageSize);
4371 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
4372 PPC::R7, PPC::R8, PPC::R9, PPC::R10,
4374 const unsigned NumGPArgRegs = std::size(GPArgRegs);
4377 PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
4380 unsigned NumFPArgRegs = std::size(FPArgRegs);
4389 int Depth = NumGPArgRegs * PtrVT.getSizeInBits()/8 +
4390 NumFPArgRegs * MVT(MVT::f64).getSizeInBits()/8;
4393 PtrVT.getSizeInBits() / 8, CCInfo.getStackSize(),
true));
4406 VReg = MF.
addLiveIn(GPArgReg, &PPC::GPRCRegClass);
4421 for (
unsigned FPRIndex = 0; FPRIndex != NumFPArgRegs; ++FPRIndex) {
4425 VReg = MF.
addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass);
4438 if (!MemOps.
empty())
4449 const SDLoc &dl)
const {
4453 else if (
Flags.isZExt())
4460SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
4466 bool isELFv2ABI = Subtarget.isELFv2ABI();
4467 bool isLittleEndian = Subtarget.isLittleEndian();
4470 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
4473 "fastcc not supported on varargs functions");
4479 unsigned PtrByteSize = 8;
4480 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
4483 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
4484 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
4487 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
4488 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
4491 const unsigned Num_GPR_Regs = std::size(GPR);
4493 const unsigned Num_VR_Regs = std::size(VR);
4501 bool HasParameterArea = !isELFv2ABI || isVarArg;
4502 unsigned ParamAreaSize = Num_GPR_Regs * PtrByteSize;
4503 unsigned NumBytes = LinkageSize;
4504 unsigned AvailableFPRs = Num_FPR_Regs;
4505 unsigned AvailableVRs = Num_VR_Regs;
4506 for (
const ISD::InputArg &In : Ins) {
4507 if (
In.Flags.isNest())
4511 LinkageSize, ParamAreaSize, NumBytes,
4512 AvailableFPRs, AvailableVRs))
4513 HasParameterArea =
true;
4520 unsigned ArgOffset = LinkageSize;
4521 unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
4524 unsigned CurArgIdx = 0;
4525 for (
unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
4527 bool needsLoad =
false;
4528 EVT ObjectVT = Ins[ArgNo].VT;
4529 EVT OrigVT = Ins[ArgNo].ArgVT;
4531 unsigned ArgSize = ObjSize;
4532 ISD::ArgFlagsTy
Flags = Ins[ArgNo].Flags;
4533 if (Ins[ArgNo].isOrigArg()) {
4534 std::advance(FuncArg, Ins[ArgNo].getOrigArgIndex() - CurArgIdx);
4535 CurArgIdx = Ins[ArgNo].getOrigArgIndex();
4540 unsigned CurArgOffset;
4542 auto ComputeArgOffset = [&]() {
4546 ArgOffset =
alignTo(ArgOffset, Alignment);
4547 CurArgOffset = ArgOffset;
4554 GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
4555 GPR_idx = std::min(GPR_idx, Num_GPR_Regs);
4560 if (
Flags.isByVal()) {
4561 assert(Ins[ArgNo].isOrigArg() &&
"Byval arguments cannot be implicit");
4567 ObjSize =
Flags.getByValSize();
4568 ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4590 if (HasParameterArea ||
4591 ArgSize + ArgOffset > LinkageSize + Num_GPR_Regs * PtrByteSize)
4598 if (ObjSize < PtrByteSize) {
4602 if (!isLittleEndian) {
4608 if (GPR_idx != Num_GPR_Regs) {
4615 MachinePointerInfo(&*FuncArg), ObjType);
4620 ArgOffset += PtrByteSize;
4629 for (
unsigned j = 0;
j < ArgSize;
j += PtrByteSize) {
4630 if (GPR_idx == Num_GPR_Regs)
4641 unsigned StoreSizeInBits = std::min(PtrByteSize, (ObjSize - j)) * 8;
4645 MachinePointerInfo(&*FuncArg, j), ObjType);
4649 ArgOffset += ArgSize;
4658 if (
Flags.isNest()) {
4663 if (ObjectVT == MVT::i32 || ObjectVT == MVT::i1)
4664 ArgVal = extendArgForPPC64(Flags, ObjectVT, DAG, ArgVal, dl);
4672 if (GPR_idx != Num_GPR_Regs) {
4677 if (ObjectVT == MVT::i32 || ObjectVT == MVT::i1)
4680 ArgVal = extendArgForPPC64(Flags, ObjectVT, DAG, ArgVal, dl);
4686 ArgSize = PtrByteSize;
4697 if (FPR_idx != Num_FPR_Regs) {
4700 if (ObjectVT == MVT::f32)
4702 Subtarget.hasP8Vector()
4703 ? &PPC::VSSRCRegClass
4704 : &PPC::F4RCRegClass);
4707 ? &PPC::VSFRCRegClass
4708 : &PPC::F8RCRegClass);
4723 if (ObjectVT == MVT::f32) {
4724 if ((ArgOffset % PtrByteSize) == (isLittleEndian ? 4 : 0))
4742 ArgSize =
Flags.isInConsecutiveRegs() ? ObjSize : PtrByteSize;
4743 ArgOffset += ArgSize;
4744 if (
Flags.isInConsecutiveRegsLast())
4745 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
4759 if (VR_idx != Num_VR_Regs) {
4776 if (ObjSize < ArgSize && !isLittleEndian)
4777 CurArgOffset += ArgSize - ObjSize;
4780 ArgVal = DAG.
getLoad(ObjectVT, dl, Chain, FIN, MachinePointerInfo());
4787 unsigned MinReservedArea;
4788 if (HasParameterArea)
4789 MinReservedArea = std::max(ArgOffset, LinkageSize + 8 * PtrByteSize);
4791 MinReservedArea = LinkageSize;
4808 int Depth = ArgOffset;
4817 for (GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
4818 GPR_idx < Num_GPR_Regs; ++GPR_idx) {
4830 if (!MemOps.
empty())
4839 unsigned ParamSize) {
4841 if (!isTailCall)
return 0;
4845 int SPDiff = (int)CallerMinReservedArea - (
int)ParamSize;
4847 if (SPDiff < FI->getTailCallSPDelta())
4863 "PC Relative callers do not have a TOC and cannot share a TOC Base");
4922 Caller->hasComdat() || CalleeGV->
getSection() != Caller->getSection())
4925 if (
F->getSectionPrefix() != Caller->getSectionPrefix())
4937 const unsigned PtrByteSize = 8;
4941 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
4942 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
4945 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
4946 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
4949 const unsigned NumGPRs = std::size(GPR);
4950 const unsigned NumFPRs = 13;
4951 const unsigned NumVRs = std::size(VR);
4952 const unsigned ParamAreaSize = NumGPRs * PtrByteSize;
4954 unsigned NumBytes = LinkageSize;
4955 unsigned AvailableFPRs = NumFPRs;
4956 unsigned AvailableVRs = NumVRs;
4959 if (Param.Flags.isNest())
continue;
4962 LinkageSize, ParamAreaSize, NumBytes,
4963 AvailableFPRs, AvailableVRs))
4974 auto CalleeArgEnd = CB.
arg_end();
4977 for (; CalleeArgIter != CalleeArgEnd; ++CalleeArgIter, ++CallerArgIter) {
4978 const Value* CalleeArg = *CalleeArgIter;
4979 const Value* CallerArg = &(*CallerArgIter);
4980 if (CalleeArg == CallerArg)
5006 if (!isTailCallableCC(CallerCC) || !isTailCallableCC(CalleeCC))
5016bool PPCTargetLowering::IsEligibleForTailCallOptimization_64SVR4(
5021 bool isCalleeExternalSymbol)
const {
5024 if (
DisableSCO && !TailCallOpt)
return false;
5027 if (isVarArg)
return false;
5034 if (
any_of(Ins, [](
const ISD::InputArg &IA) {
return IA.Flags.isByVal(); }))
5070 if (!Subtarget.isUsingPCRelativeCalls() &&
5075 if (!Subtarget.isUsingPCRelativeCalls() &&
5103bool PPCTargetLowering::IsEligibleForTailCallOptimization(
5116 if (
any_of(Ins, [](
const ISD::InputArg &IA) {
return IA.Flags.isByVal(); }))
5137 if (!
C)
return nullptr;
5139 int Addr =
C->getZExtValue();
5140 if ((Addr & 3) != 0 ||
5146 (
int)
C->getZExtValue() >> 2,
SDLoc(
Op),
5153struct TailCallArgumentInfo {
5158 TailCallArgumentInfo() =
default;
5168 for (
unsigned i = 0, e = TailCallArgs.
size(); i != e; ++i) {
5169 SDValue Arg = TailCallArgs[i].Arg;
5170 SDValue FIN = TailCallArgs[i].FrameIdxOp;
5171 int FI = TailCallArgs[i].FrameIdx;
5174 Chain, dl, Arg, FIN,
5183 int SPDiff,
const SDLoc &dl) {
5189 int SlotSize = Subtarget.isPPC64() ? 8 : 4;
5190 int NewRetAddrLoc = SPDiff + FL->getReturnSaveOffset();
5192 NewRetAddrLoc,
true);
5195 Chain = DAG.
getStore(Chain, dl, OldRetAddr, NewRetAddrFrIdx,
5205 int SPDiff,
unsigned ArgOffset,
5207 int Offset = ArgOffset + SPDiff;
5210 EVT VT = IsPPC64 ? MVT::i64 : MVT::i32;
5212 TailCallArgumentInfo Info;
5214 Info.FrameIdxOp = FIN;
5222SDValue PPCTargetLowering::EmitTailCallLoadFPAndRetAddr(
5227 LROpOut = getReturnAddrFrameIndex(DAG);
5228 LROpOut = DAG.
getLoad(Subtarget.getScalarIntVT(), dl, Chain, LROpOut,
5229 MachinePointerInfo());
5245 Align Alignment = Flags.getNonZeroByValAlign();
5247 Chain, dl, Dst, Src, SizeNode, Alignment, Alignment,
false,
false,
5255 SDValue PtrOff,
int SPDiff,
unsigned ArgOffset,
bool isPPC64,
5279 const SDLoc &dl,
int SPDiff,
unsigned NumBytes,
SDValue LROp,
5289 if (!MemOpChains2.
empty())
5313SDValue PPCTargetLowering::LowerCallResult(
5321 CCRetInfo.AnalyzeCallResult(
5327 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
5328 CCValAssign &VA = RVLocs[i];
5333 if (Subtarget.hasSPE() && VA.
getLocVT() == MVT::f64) {
5343 if (!Subtarget.isLittleEndian())
5345 Val = DAG.
getNode(PPCISD::BUILD_SPE64, dl, MVT::f64,
Lo,
Hi);
5411 bool IsStrictFPCall =
false) {
5413 return PPCISD::TC_RETURN;
5415 unsigned RetOpc = 0;
5426 if (Subtarget.usePointerGlueHelper())
5427 RetOpc = PPCISD::BL_LOAD_TOC;
5433 RetOpc = PPCISD::CALL_NOTOC;
5448 RetOpc = PPCISD::CALL;
5449 if (IsStrictFPCall) {
5453 case PPCISD::BCTRL_LOAD_TOC:
5454 RetOpc = PPCISD::BCTRL_LOAD_TOC_RM;
5457 RetOpc = PPCISD::BCTRL_RM;
5459 case PPCISD::BL_LOAD_TOC:
5460 RetOpc = PPCISD::BL_LOAD_TOC_RM;
5462 case PPCISD::CALL_NOTOC:
5463 RetOpc = PPCISD::CALL_NOTOC_RM;
5466 RetOpc = PPCISD::CALL_RM;
5468 case PPCISD::CALL_NOP:
5469 RetOpc = PPCISD::CALL_NOP_RM;
5483 auto isLocalCallee = [&]() {
5499 const auto getAIXFuncEntryPointSymbolSDNode = [&](
const GlobalValue *GV) {
5515 return getAIXFuncEntryPointSymbolSDNode(GV);
5522 const char *SymName = S->getSymbol();
5529 return getAIXFuncEntryPointSymbolSDNode(
F);
5535 const auto getExternalFunctionEntryPointSymbol = [&](
StringRef SymName) {
5543 SymName = getExternalFunctionEntryPointSymbol(SymName)->getName().data();
5550 assert(Callee.getNode() &&
"What no callee?");
5556 "Expected a CALLSEQ_STARTSDNode.");
5573 SDValue MTCTROps[] = {Chain, Callee, Glue};
5574 EVT ReturnTypes[] = {MVT::Other, MVT::Glue};
5575 Chain = DAG.
getNode(PPCISD::MTCTR, dl, ReturnTypes,
5615 auto MMOFlags = Subtarget.hasInvariantFunctionDescriptors()
5634 SDValue LoadFuncPtr = DAG.
getLoad(RegVT, dl, LDChain, Callee, MPI,
5635 Alignment, MMOFlags);
5642 DAG.
getLoad(RegVT, dl, LDChain, AddTOC,
5649 DAG.
getLoad(RegVT, dl, LDChain, AddPtr,
5661 "Nest parameter is not supported on AIX.");
5676 const SDLoc &dl,
bool hasNest,
5686 Chain = MoveToPhysicalReg.
getValue(0);
5687 Glue = MoveToPhysicalReg.
getValue(1);
5694 SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass,
5697 const bool IsPPC64 = Subtarget.isPPC64();
5702 Ops.push_back(Chain);
5706 Ops.push_back(Callee);
5707 else if (Subtarget.usePointerGlueHelper()) {
5708 Ops.push_back(Callee);
5731 Ops.push_back(AddTOC);
5742 Ops.push_back(DAG.
getRegister(IsPPC64 ? PPC::CTR8 : PPC::CTR, RegVT));
5751 for (
const auto &[
Reg,
N] : RegsToPass)
5769 assert(Mask &&
"Missing call preserved mask for calling convention");
5774 Ops.push_back(Glue);
5777SDValue PPCTargetLowering::FinishCall(
5784 if ((Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls()) ||
5785 Subtarget.isAIXABI())
5792 if (!CFlags.IsIndirect)
5794 else if (Subtarget.usesFunctionDescriptors()) {
5795 if (Subtarget.usePointerGlueHelper()) {
5797 CFlags.HasNest, Subtarget);
5803 dl, CFlags.HasNest, Subtarget);
5815 if (CFlags.IsTailCall) {
5823 (CFlags.IsIndirect && Subtarget.isUsingPCRelativeCalls())) &&
5824 "Expecting a global address, external symbol, absolute value, "
5825 "register or an indirect tail call when PC Relative calls are "
5828 assert(CallOpc == PPCISD::TC_RETURN &&
5829 "Unexpected call opcode for a tail call.");
5836 std::array<EVT, 2> ReturnTypes = {{MVT::Other, MVT::Glue}};
5837 Chain = DAG.
getNode(CallOpc, dl, ReturnTypes,
Ops);
5849 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, BytesCalleePops, Glue, dl);
5852 return LowerCallResult(Chain, Glue, CFlags.CallConv, CFlags.IsVarArg, Ins, dl,
5872 return isEligibleForTCO(CalleeGV, CalleeCC, CallerCC, CB,
5873 CalleeFunc->
isVarArg(), Outs, Ins, CallerFunc,
5877bool PPCTargetLowering::isEligibleForTCO(
5882 bool isCalleeExternalSymbol)
const {
5886 if (Subtarget.
isSVR4ABI() && Subtarget.isPPC64())
5887 return IsEligibleForTailCallOptimization_64SVR4(
5888 CalleeGV, CalleeCC, CallerCC, CB, isVarArg, Outs, Ins, CallerFunc,
5889 isCalleeExternalSymbol);
5891 return IsEligibleForTailCallOptimization(CalleeGV, CalleeCC, CallerCC,
5919 isEligibleForTCO(GV, CallConv, CallerCC, CB, isVarArg, Outs, Ins,
5934 "Callee should be an llvm::Function object.");
5937 <<
"\nTCO callee: ");
5944 "site marked musttail");
5951 Callee = LowerGlobalAddress(Callee, DAG);
5954 CallConv, isTailCall, isVarArg, isPatchPoint,
5957 Subtarget.is64BitELFABI() &&
5961 if (Subtarget.isAIXABI())
5962 return LowerCall_AIX(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5965 assert(Subtarget.isSVR4ABI());
5966 if (Subtarget.isPPC64())
5967 return LowerCall_64SVR4(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5969 return LowerCall_32SVR4(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
5973SDValue PPCTargetLowering::LowerCall_32SVR4(
5984 const bool IsVarArg = CFlags.IsVarArg;
5985 const bool IsTailCall = CFlags.IsTailCall;
5991 const Align PtrAlign(4);
6002 MF.
getInfo<PPCFunctionInfo>()->setHasFastCall();
6010 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.
getContext());
6013 CCInfo.AllocateStack(Subtarget.getFrameLowering()->getLinkageSize(),
6020 unsigned NumArgs = Outs.
size();
6022 for (
unsigned i = 0; i != NumArgs; ++i) {
6023 MVT ArgVT = Outs[i].VT;
6024 ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
6029 Outs[i].OrigTy, CCInfo);
6032 ArgFlags, Outs[i].OrigTy, CCInfo);
6037 errs() <<
"Call operand #" << i <<
" has unhandled type "
6050 CCState CCByValInfo(CallConv, IsVarArg, MF, ByValArgLocs, *DAG.
getContext());
6053 CCByValInfo.AllocateStack(CCInfo.getStackSize(), PtrAlign);
6060 unsigned NumBytes = CCByValInfo.getStackSize();
6074 Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, dl);
6085 bool seenFloatArg =
false;
6090 for (
unsigned i = 0, RealArgIdx = 0, j = 0, e = ArgLocs.
size();
6092 ++i, ++RealArgIdx) {
6093 CCValAssign &VA = ArgLocs[i];
6094 SDValue Arg = OutVals[RealArgIdx];
6095 ISD::ArgFlagsTy
Flags = Outs[RealArgIdx].Flags;
6097 if (
Flags.isByVal()) {
6102 assert((j < ByValArgLocs.
size()) &&
"Index out of bounds!");
6103 CCValAssign &ByValVA = ByValArgLocs[
j++];
6125 Chain = CallSeqStart = NewCallSeqStart;
6144 if (Subtarget.hasSPE() && Arg.
getValueType() == MVT::f64) {
6145 bool IsLE = Subtarget.isLittleEndian();
6146 SDValue SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
6149 SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
6151 RegsToPass.
push_back(std::make_pair(ArgLocs[++i].getLocReg(),
6166 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
6175 if (!MemOpChains.
empty())
6181 for (
const auto &[
Reg,
N] : RegsToPass) {
6189 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
6192 Chain = DAG.
getNode(seenFloatArg ? PPCISD::CR6SET : PPCISD::CR6UNSET, dl,
6202 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
6203 Callee, SPDiff, NumBytes, Ins, InVals, CB);
6208SDValue PPCTargetLowering::createMemcpyOutsideCallSeq(
6220 return NewCallSeqStart;
6223SDValue PPCTargetLowering::LowerCall_64SVR4(
6230 bool isELFv2ABI = Subtarget.isELFv2ABI();
6231 bool isLittleEndian = Subtarget.isLittleEndian();
6233 bool IsSibCall =
false;
6237 unsigned PtrByteSize = 8;
6250 MF.
getInfo<PPCFunctionInfo>()->setHasFastCall();
6252 assert(!(IsFastCall && CFlags.IsVarArg) &&
6253 "fastcc not supported on varargs functions");
6259 unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
6260 unsigned NumBytes = LinkageSize;
6261 unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
6264 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6265 PPC::X7, PPC::X8, PPC::X9, PPC::X10,
6268 PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
6269 PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
6272 const unsigned NumGPRs = std::size(GPR);
6274 const unsigned NumVRs = std::size(VR);
6280 bool HasParameterArea = !isELFv2ABI || CFlags.IsVarArg || IsFastCall;
6281 if (!HasParameterArea) {
6282 unsigned ParamAreaSize = NumGPRs * PtrByteSize;
6283 unsigned AvailableFPRs = NumFPRs;
6284 unsigned AvailableVRs = NumVRs;
6285 unsigned NumBytesTmp = NumBytes;
6286 for (
unsigned i = 0; i !=
NumOps; ++i) {
6287 if (Outs[i].
Flags.isNest())
continue;
6289 PtrByteSize, LinkageSize, ParamAreaSize,
6290 NumBytesTmp, AvailableFPRs, AvailableVRs))
6291 HasParameterArea =
true;
6297 unsigned NumGPRsUsed = 0, NumFPRsUsed = 0, NumVRsUsed = 0;
6302 HasParameterArea =
false;
6305 for (
unsigned i = 0; i !=
NumOps; ++i) {
6306 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
6307 EVT ArgVT = Outs[i].VT;
6308 EVT OrigVT = Outs[i].ArgVT;
6314 if (
Flags.isByVal()) {
6315 NumGPRsUsed += (
Flags.getByValSize()+7)/8;
6316 if (NumGPRsUsed > NumGPRs)
6317 HasParameterArea =
true;
6324 if (++NumGPRsUsed <= NumGPRs)
6334 if (++NumVRsUsed <= NumVRs)
6338 if (++NumVRsUsed <= NumVRs)
6343 if (++NumFPRsUsed <= NumFPRs)
6347 HasParameterArea =
true;
6354 NumBytes =
alignTo(NumBytes, Alignement);
6357 if (
Flags.isInConsecutiveRegsLast())
6358 NumBytes = ((NumBytes + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
6361 unsigned NumBytesActuallyUsed = NumBytes;
6371 if (HasParameterArea)
6372 NumBytes = std::max(NumBytes, LinkageSize + 8 * PtrByteSize);
6374 NumBytes = LinkageSize;
6389 if (CFlags.IsTailCall)
6401 Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, dl);
6412 unsigned ArgOffset = LinkageSize;
6418 for (
unsigned i = 0; i !=
NumOps; ++i) {
6420 ISD::ArgFlagsTy
Flags = Outs[i].Flags;
6421 EVT ArgVT = Outs[i].VT;
6422 EVT OrigVT = Outs[i].ArgVT;
6431 auto ComputePtrOff = [&]() {
6435 ArgOffset =
alignTo(ArgOffset, Alignment);
6446 GPR_idx = (ArgOffset - LinkageSize) / PtrByteSize;
6447 GPR_idx = std::min(GPR_idx, NumGPRs);
6454 Arg = DAG.
getNode(ExtOp, dl, MVT::i64, Arg);
6460 if (
Flags.isByVal()) {
6478 EVT VT = (
Size==1) ? MVT::i8 : ((
Size==2) ? MVT::i16 : MVT::i32);
6479 if (GPR_idx != NumGPRs) {
6481 MachinePointerInfo(), VT);
6483 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6485 ArgOffset += PtrByteSize;
6490 if (GPR_idx == NumGPRs &&
Size < 8) {
6492 if (!isLittleEndian) {
6497 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, AddPtr,
6500 ArgOffset += PtrByteSize;
6509 if ((NumGPRs - GPR_idx) * PtrByteSize <
Size)
6510 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, PtrOff,
6515 if (
Size < 8 && GPR_idx != NumGPRs) {
6525 if (!isLittleEndian) {
6529 Chain = CallSeqStart = createMemcpyOutsideCallSeq(Arg, AddPtr,
6535 DAG.
getLoad(PtrVT, dl, Chain, PtrOff, MachinePointerInfo());
6537 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6540 ArgOffset += PtrByteSize;
6546 for (
unsigned j=0;
j<
Size;
j+=PtrByteSize) {
6549 if (GPR_idx != NumGPRs) {
6550 unsigned LoadSizeInBits = std::min(PtrByteSize, (
Size - j)) * 8;
6553 MachinePointerInfo(), ObjType);
6556 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6557 ArgOffset += PtrByteSize;
6559 ArgOffset += ((
Size -
j + PtrByteSize-1)/PtrByteSize)*PtrByteSize;
6571 if (
Flags.isNest()) {
6573 RegsToPass.
push_back(std::make_pair(PPC::X11, Arg));
6580 if (GPR_idx != NumGPRs) {
6581 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Arg));
6586 assert(HasParameterArea &&
6587 "Parameter area must exist to pass an argument in memory.");
6589 true, CFlags.IsTailCall,
false, MemOpChains,
6590 TailCallArguments, dl);
6592 ArgOffset += PtrByteSize;
6595 ArgOffset += PtrByteSize;
6608 bool NeedGPROrStack = CFlags.IsVarArg || FPR_idx == NumFPRs;
6609 bool NeededLoad =
false;
6612 if (FPR_idx != NumFPRs)
6613 RegsToPass.
push_back(std::make_pair(
FPR[FPR_idx++], Arg));
6616 if (!NeedGPROrStack)
6618 else if (GPR_idx != NumGPRs && !IsFastCall) {
6632 }
else if (!
Flags.isInConsecutiveRegs()) {
6638 }
else if (ArgOffset % PtrByteSize != 0) {
6642 if (!isLittleEndian)
6647 }
else if (
Flags.isInConsecutiveRegsLast()) {
6650 if (!isLittleEndian)
6660 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], ArgVal));
6668 !isLittleEndian && !
Flags.isInConsecutiveRegs()) {
6673 assert(HasParameterArea &&
6674 "Parameter area must exist to pass an argument in memory.");
6676 true, CFlags.IsTailCall,
false, MemOpChains,
6677 TailCallArguments, dl);
6684 if (!IsFastCall || NeededLoad) {
6686 Flags.isInConsecutiveRegs()) ? 4 : 8;
6687 if (
Flags.isInConsecutiveRegsLast())
6688 ArgOffset = ((ArgOffset + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
6708 if (CFlags.IsVarArg) {
6709 assert(HasParameterArea &&
6710 "Parameter area must exist if we have a varargs call.");
6714 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
6716 if (VR_idx != NumVRs) {
6718 DAG.
getLoad(MVT::v4f32, dl, Store, PtrOff, MachinePointerInfo());
6720 RegsToPass.
push_back(std::make_pair(VR[VR_idx++], Load));
6723 for (
unsigned i=0; i<16; i+=PtrByteSize) {
6724 if (GPR_idx == NumGPRs)
6729 DAG.
getLoad(PtrVT, dl, Store, Ix, MachinePointerInfo());
6731 RegsToPass.
push_back(std::make_pair(GPR[GPR_idx++], Load));
6737 if (VR_idx != NumVRs) {
6738 RegsToPass.
push_back(std::make_pair(VR[VR_idx++], Arg));
6743 assert(HasParameterArea &&
6744 "Parameter area must exist to pass an argument in memory.");
6746 true, CFlags.IsTailCall,
true, MemOpChains,
6747 TailCallArguments, dl);
6758 assert((!HasParameterArea || NumBytesActuallyUsed == ArgOffset) &&
6759 "mismatch in size of parameter area");
6760 (void)NumBytesActuallyUsed;
6762 if (!MemOpChains.
empty())
6768 if (CFlags.IsIndirect) {
6772 assert(!CFlags.IsTailCall &&
"Indirect tails calls not supported");
6777 unsigned TOCSaveOffset = Subtarget.getFrameLowering()->getTOCSaveOffset();
6787 if (isELFv2ABI && !CFlags.IsPatchPoint)
6788 RegsToPass.
push_back(std::make_pair((
unsigned)PPC::X12, Callee));
6794 for (
const auto &[
Reg,
N] : RegsToPass) {
6799 if (CFlags.IsTailCall && !IsSibCall)
6803 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
6804 Callee, SPDiff, NumBytes, Ins, InVals, CB);
6811 "Required alignment greater than stack alignment.");
6831 return RequiredAlign <= 8;
6836 return RequiredAlign <= 4;
6844 State.getMachineFunction().getSubtarget());
6845 const bool IsPPC64 = Subtarget.isPPC64();
6846 const unsigned PtrSize = IsPPC64 ? 8 : 4;
6847 const Align PtrAlign(PtrSize);
6848 const Align StackAlign(16);
6851 if (ValVT == MVT::f128)
6855 PPC::R3, PPC::R4, PPC::R5, PPC::R6,
6856 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
6858 PPC::X3, PPC::X4, PPC::X5, PPC::X6,
6859 PPC::X7, PPC::X8, PPC::X9, PPC::X10};
6862 PPC::V2, PPC::V3, PPC::V4, PPC::V5,
6863 PPC::V6, PPC::V7, PPC::V8, PPC::V9,
6864 PPC::V10, PPC::V11, PPC::V12, PPC::V13};
6869 MCRegister EnvReg = State.AllocateReg(IsPPC64 ? PPC::X11 : PPC::R11);
6878 if (ByValAlign > StackAlign)
6880 "16 are not supported.");
6883 const Align ObjAlign = ByValAlign > PtrAlign ? ByValAlign : PtrAlign;
6887 if (ByValSize == 0) {
6889 State.getStackSize(), RegVT, LocInfo));
6894 unsigned NextReg = State.getFirstUnallocated(GPRs);
6895 while (NextReg != GPRs.
size() &&
6900 State.AllocateStack(PtrSize, PtrAlign);
6901 assert(
Reg &&
"Alocating register unexpectedly failed.");
6903 NextReg = State.getFirstUnallocated(GPRs);
6906 const unsigned StackSize =
alignTo(ByValSize, ObjAlign);
6907 unsigned Offset = State.AllocateStack(StackSize, ObjAlign);
6927 assert(IsPPC64 &&
"PPC32 should have split i64 values.");
6931 const unsigned Offset = State.AllocateStack(PtrSize, PtrAlign);
6950 State.AllocateStack(IsPPC64 ? 8 : StoreSize,
Align(4));
6956 for (
unsigned I = 0;
I < StoreSize;
I += PtrSize) {
6958 assert(FReg &&
"An FPR should be available when a GPR is reserved.");
6959 if (State.isVarArg()) {
6991 const unsigned VecSize = 16;
6992 const Align VecAlign(VecSize);
6994 if (!State.isVarArg()) {
6997 if (
MCRegister VReg = State.AllocateReg(VR)) {
7004 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7009 unsigned NextRegIndex = State.getFirstUnallocated(GPRs);
7012 while (NextRegIndex != GPRs.
size() &&
7016 State.AllocateStack(PtrSize, PtrAlign);
7017 assert(
Reg &&
"Allocating register unexpectedly failed.");
7019 NextRegIndex = State.getFirstUnallocated(GPRs);
7027 if (
MCRegister VReg = State.AllocateReg(VR)) {
7030 for (
unsigned I = 0;
I != VecSize;
I += PtrSize)
7031 State.AllocateReg(GPRs);
7032 State.AllocateStack(VecSize, VecAlign);
7036 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7042 if (NextRegIndex == GPRs.
size()) {
7043 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7051 if (GPRs[NextRegIndex] == PPC::R9) {
7052 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7056 const MCRegister FirstReg = State.AllocateReg(PPC::R9);
7057 const MCRegister SecondReg = State.AllocateReg(PPC::R10);
7058 assert(FirstReg && SecondReg &&
7059 "Allocating R9 or R10 unexpectedly failed.");
7070 const unsigned Offset = State.AllocateStack(VecSize, VecAlign);
7073 for (
unsigned I = 0;
I != VecSize;
I += PtrSize) {
7075 assert(
Reg &&
"Failed to allocated register for vararg vector argument");
7090 assert((IsPPC64 || SVT != MVT::i64) &&
7091 "i64 should have been split for 32-bit codegen.");
7099 return IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
7101 return HasP8Vector ? &PPC::VSSRCRegClass : &PPC::F4RCRegClass;
7103 return HasVSX ? &PPC::VSFRCRegClass : &PPC::F8RCRegClass;
7111 return &PPC::VRRCRegClass;
7124 else if (Flags.isZExt())
7136 "Reg must be a valid argument register!");
7137 return LASize + 4 * (
Reg - PPC::R3);
7142 "Reg must be a valid argument register!");
7143 return LASize + 8 * (
Reg - PPC::X3);
7189SDValue PPCTargetLowering::LowerFormalArguments_AIX(
7196 "Unexpected calling convention!");
7204 const PPCSubtarget &Subtarget = DAG.
getSubtarget<PPCSubtarget>();
7206 const bool IsPPC64 = Subtarget.isPPC64();
7207 const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
7213 PPCFunctionInfo *FuncInfo = MF.
getInfo<PPCFunctionInfo>();
7214 CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.
getContext());
7218 const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
7219 CCInfo.AllocateStack(LinkageSize,
Align(PtrByteSize));
7220 uint64_t SaveStackPos = CCInfo.getStackSize();
7222 CCInfo.AnalyzeFormalArguments(Ins,
CC_AIX);
7226 for (
size_t I = 0, End = ArgLocs.
size();
I != End; ) {
7227 CCValAssign &VA = ArgLocs[
I++];
7232 EVT ArgVT = Ins[VA.
getValNo()].ArgVT;
7233 bool ArgSignExt = Ins[VA.
getValNo()].Flags.isSExt();
7245 LocVT.
SimpleTy, IsPPC64, Subtarget.hasP8Vector(), Subtarget.hasVSX());
7247 MVT SaveVT = RegClass == &PPC::G8RCRegClass ? MVT::i64 : LocVT;
7253 MachinePointerInfo(),
Align(PtrByteSize));
7259 unsigned StoreSize =
7261 SaveStackPos =
alignTo(SaveStackPos + StoreSize, PtrByteSize);
7264 auto HandleMemLoc = [&]() {
7267 assert((ValSize <= LocSize) &&
7268 "Object size is larger than size of MemLoc");
7271 if (LocSize > ValSize)
7272 CurArgOffset += LocSize - ValSize;
7274 const bool IsImmutable =
7280 DAG.
getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo());
7314 assert(isVarArg &&
"Only use custom memloc for vararg.");
7317 const unsigned OriginalValNo = VA.
getValNo();
7318 (void)OriginalValNo;
7320 auto HandleCustomVecRegLoc = [&]() {
7321 assert(
I != End && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7322 "Missing custom RegLoc.");
7325 "Unexpected Val type for custom RegLoc.");
7327 "ValNo mismatch between custom MemLoc and RegLoc.");
7331 Subtarget.hasVSX()));
7338 HandleCustomVecRegLoc();
7339 HandleCustomVecRegLoc();
7343 if (
I != End && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom()) {
7345 "Only 2 custom RegLocs expected for 64-bit codegen.");
7346 HandleCustomVecRegLoc();
7347 HandleCustomVecRegLoc();
7391 const unsigned Size =
7403 if (
Flags.isByVal()) {
7407 const PPCFrameLowering *FL = Subtarget.getFrameLowering();
7409 const unsigned StackSize =
alignTo(
Flags.getByValSize(), PtrByteSize);
7417 const TargetRegisterClass *RegClass =
7418 IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
7420 auto HandleRegLoc = [&, RegClass, LocVT](
const MCPhysReg PhysReg,
7433 CopyFrom.
getValue(1), dl, CopyFrom,
7443 for (;
Offset != StackSize && ArgLocs[
I].isRegLoc();
7446 "RegLocs should be for ByVal argument.");
7448 const CCValAssign RL = ArgLocs[
I++];
7453 if (
Offset != StackSize) {
7455 "Expected MemLoc for remaining bytes.");
7456 assert(ArgLocs[
I].isMemLoc() &&
"Expected MemLoc for remaining bytes.");
7470 Subtarget.hasVSX()));
7487 const unsigned MinParameterSaveArea = 8 * PtrByteSize;
7489 unsigned CallerReservedArea = std::max<unsigned>(
7490 CCInfo.getStackSize(), LinkageSize + MinParameterSaveArea);
7496 CallerReservedArea =
7501 int VAListIndex = 0;
7505 if (CCInfo.getStackSize() < (LinkageSize + MinParameterSaveArea)) {
7506 unsigned FixedStackSize =
7507 LinkageSize + MinParameterSaveArea - CCInfo.getStackSize();
7523 static const MCPhysReg GPR_32[] = {PPC::R3, PPC::R4, PPC::R5, PPC::R6,
7524 PPC::R7, PPC::R8, PPC::R9, PPC::R10};
7526 static const MCPhysReg GPR_64[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6,
7527 PPC::X7, PPC::X8, PPC::X9, PPC::X10};
7528 const unsigned NumGPArgRegs = std::size(IsPPC64 ? GPR_64 : GPR_32);
7534 GPRIndex = (CCInfo.getStackSize() - LinkageSize) / PtrByteSize,
7536 GPRIndex < NumGPArgRegs; ++GPRIndex,
Offset += PtrByteSize) {
7539 IsPPC64 ? MF.
addLiveIn(GPR_64[GPRIndex], &PPC::G8RCRegClass)
7540 : MF.
addLiveIn(GPR_32[GPRIndex], &PPC::GPRCRegClass);
7543 MachinePointerInfo MPI =
7553 if (!MemOps.
empty())
7559SDValue PPCTargetLowering::LowerCall_AIX(
7572 "Unexpected calling convention!");
7574 if (CFlags.IsPatchPoint)
7577 const PPCSubtarget &Subtarget = DAG.
getSubtarget<PPCSubtarget>();
7581 CCState CCInfo(CFlags.CallConv, CFlags.IsVarArg, MF, ArgLocs,
7588 const unsigned LinkageSize = Subtarget.getFrameLowering()->getLinkageSize();
7589 const bool IsPPC64 = Subtarget.isPPC64();
7591 const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
7592 CCInfo.AllocateStack(LinkageSize,
Align(PtrByteSize));
7593 CCInfo.AnalyzeCallOperands(Outs,
CC_AIX);
7601 const unsigned MinParameterSaveAreaSize = 8 * PtrByteSize;
7602 const unsigned NumBytes = std::max<unsigned>(
7603 LinkageSize + MinParameterSaveAreaSize, CCInfo.getStackSize());
7619 for (
unsigned I = 0,
E = ArgLocs.
size();
I !=
E;) {
7620 const unsigned ValNo = ArgLocs[
I].getValNo();
7622 ISD::ArgFlagsTy
Flags = Outs[ValNo].Flags;
7624 if (
Flags.isByVal()) {
7625 const unsigned ByValSize =
Flags.getByValSize();
7633 auto GetLoad = [&](EVT VT,
unsigned LoadOffset) {
7639 MachinePointerInfo(), VT);
7642 unsigned LoadOffset = 0;
7645 while (LoadOffset + PtrByteSize <= ByValSize && ArgLocs[
I].isRegLoc()) {
7648 LoadOffset += PtrByteSize;
7649 const CCValAssign &ByValVA = ArgLocs[
I++];
7651 "Unexpected location for pass-by-value argument.");
7655 if (LoadOffset == ByValSize)
7659 assert(ArgLocs[
I].getValNo() == ValNo &&
7660 "Expected additional location for by-value argument.");
7662 if (ArgLocs[
I].isMemLoc()) {
7663 assert(LoadOffset < ByValSize &&
"Unexpected memloc for by-val arg.");
7664 const CCValAssign &ByValVA = ArgLocs[
I++];
7665 ISD::ArgFlagsTy MemcpyFlags =
Flags;
7668 Chain = CallSeqStart = createMemcpyOutsideCallSeq(
7674 CallSeqStart, MemcpyFlags, DAG, dl);
7683 const unsigned ResidueBytes = ByValSize % PtrByteSize;
7684 assert(ResidueBytes != 0 && LoadOffset + PtrByteSize > ByValSize &&
7685 "Unexpected register residue for by-value argument.");
7687 for (
unsigned Bytes = 0; Bytes != ResidueBytes;) {
7691 : ((
N == 2) ? MVT::i16 : (
N == 4 ? MVT::i32 : MVT::i64));
7701 "Unexpected load emitted during handling of pass-by-value "
7709 ResidueVal = ResidueVal ? DAG.
getNode(
ISD::OR, dl, PtrVT, ResidueVal,
7714 const CCValAssign &ByValVA = ArgLocs[
I++];
7719 CCValAssign &VA = ArgLocs[
I++];
7744 assert(CFlags.IsVarArg &&
"Custom MemLocs only used for Vector args.");
7750 DAG.
getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
7752 const unsigned OriginalValNo = VA.
getValNo();
7754 unsigned LoadOffset = 0;
7755 auto HandleCustomVecRegLoc = [&]() {
7756 assert(
I !=
E &&
"Unexpected end of CCvalAssigns.");
7757 assert(ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7758 "Expected custom RegLoc.");
7759 CCValAssign RegVA = ArgLocs[
I++];
7761 "Custom MemLoc ValNo and custom RegLoc ValNo must match.");
7767 LoadOffset += PtrByteSize;
7773 HandleCustomVecRegLoc();
7774 HandleCustomVecRegLoc();
7776 if (
I !=
E && ArgLocs[
I].isRegLoc() && ArgLocs[
I].needsCustom() &&
7777 ArgLocs[
I].getValNo() == OriginalValNo) {
7779 "Only 2 custom RegLocs expected for 64-bit codegen.");
7780 HandleCustomVecRegLoc();
7781 HandleCustomVecRegLoc();
7792 DAG.
getStore(Chain, dl, Arg, PtrOff,
7794 Subtarget.getFrameLowering()->getStackAlign()));
7801 "Unexpected register handling for calling convention.");
7807 "Custom register handling only expected for VarArg.");
7812 if (Arg.getValueType().getStoreSize() == LocVT.
getStoreSize())
7816 else if (Arg.getValueType().getFixedSizeInBits() <
7824 assert(Arg.getValueType() == MVT::f64 && CFlags.IsVarArg && !IsPPC64 &&
7825 "Unexpected custom register for argument!");
7826 CCValAssign &GPR1 = VA;
7835 CCValAssign &PeekArg = ArgLocs[
I];
7838 CCValAssign &GPR2 = ArgLocs[
I++];
7846 if (!MemOpChains.
empty())
7851 if (CFlags.IsIndirect && !Subtarget.usePointerGlueHelper()) {
7852 assert(!CFlags.IsTailCall &&
"Indirect tail-calls not supported.");
7853 const MCRegister TOCBaseReg = Subtarget.getTOCPointerRegister();
7854 const MCRegister StackPtrReg = Subtarget.getStackPointerRegister();
7855 const MVT PtrVT = Subtarget.getScalarIntVT();
7856 const unsigned TOCSaveOffset =
7857 Subtarget.getFrameLowering()->getTOCSaveOffset();
7872 for (
auto Reg : RegsToPass) {
7877 const int SPDiff = 0;
7878 return FinishCall(CFlags, dl, DAG, RegsToPass, InGlue, Chain, CallSeqStart,
7879 Callee, SPDiff, NumBytes, Ins, InVals, CB);
7887 const Type *RetTy)
const {
7889 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
7890 return CCInfo.CheckReturn(
7905 CCInfo.AnalyzeReturn(Outs,
7914 for (
unsigned i = 0, RealResIdx = 0; i != RVLocs.
size(); ++i, ++RealResIdx) {
7915 CCValAssign &VA = RVLocs[i];
7918 SDValue Arg = OutVals[RealResIdx];
7933 if (Subtarget.hasSPE() && VA.
getLocVT() == MVT::f64) {
7934 bool isLittleEndian = Subtarget.isLittleEndian();
7937 DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
7941 SVal = DAG.
getNode(PPCISD::EXTRACT_SPE, dl, MVT::i32, Arg,
7956 RetOps.push_back(Glue);
7958 return DAG.
getNode(PPCISD::RET_GLUE, dl, MVT::Other, RetOps);
7962PPCTargetLowering::LowerGET_DYNAMIC_AREA_OFFSET(
SDValue Op,
7967 EVT IntVT =
Op.getValueType();
7971 SDValue FPSIdx = getFramePointerFrameIndex(DAG);
7975 return DAG.
getNode(PPCISD::DYNAREAOFFSET, dl, VTs,
Ops);
7987 bool isPPC64 = Subtarget.isPPC64();
7988 unsigned SP = isPPC64 ? PPC::X1 : PPC::R1;
7997 DAG.
getLoad(PtrVT, dl, Chain, StackPtr, MachinePointerInfo());
8003 return DAG.
getStore(Chain, dl, LoadLinkSP, StackPtr, MachinePointerInfo());
8008 bool isPPC64 = Subtarget.isPPC64();
8013 PPCFunctionInfo *FI = MF.
getInfo<PPCFunctionInfo>();
8019 int LROffset = Subtarget.getFrameLowering()->getReturnSaveOffset();
8029PPCTargetLowering::getFramePointerFrameIndex(
SelectionDAG & DAG)
const {
8031 bool isPPC64 = Subtarget.isPPC64();
8036 PPCFunctionInfo *FI = MF.
getInfo<PPCFunctionInfo>();
8042 int FPOffset = Subtarget.getFrameLowering()->getFramePointerSaveOffset();
8065 SDValue FPSIdx = getFramePointerFrameIndex(DAG);
8067 SDVTList VTs = DAG.
getVTList(PtrVT, MVT::Other);
8069 return DAG.
getNode(PPCISD::PROBED_ALLOCA, dl, VTs,
Ops);
8070 return DAG.
getNode(PPCISD::DYNALLOC, dl, VTs,
Ops);
8077 bool isPPC64 = Subtarget.isPPC64();
8087 return DAG.
getNode(PPCISD::EH_SJLJ_SETJMP,
DL,
8089 Op.getOperand(0),
Op.getOperand(1));
8095 return DAG.
getNode(PPCISD::EH_SJLJ_LONGJMP,
DL, MVT::Other,
8096 Op.getOperand(0),
Op.getOperand(1));
8100 if (
Op.getValueType().isVector())
8101 return LowerVectorLoad(
Op, DAG);
8103 assert(
Op.getValueType() == MVT::i1 &&
8104 "Custom lowering only for i1 loads");
8113 MachineMemOperand *MMO =
LD->getMemOperand();
8117 BasePtr, MVT::i8, MMO);
8125 if (
Op.getOperand(1).getValueType().isVector())
8126 return LowerVectorStore(
Op, DAG);
8128 assert(
Op.getOperand(1).getValueType() == MVT::i1 &&
8129 "Custom lowering only for i1 stores");
8139 MachineMemOperand *MMO =
ST->getMemOperand();
8148 assert(
Op.getValueType() == MVT::i1 &&
8149 "Custom lowering only for i1 results");
8177 EVT TrgVT =
Op.getValueType();
8201 if (SrcSize == 256) {
8212 Op1 = SrcSize == 128 ? N1 :
widenVec(DAG, N1,
DL);
8218 SmallVector<int, 16> ShuffV;
8219 if (Subtarget.isLittleEndian())
8220 for (
unsigned i = 0; i < TrgNumElts; ++i)
8223 for (
unsigned i = 1; i <= TrgNumElts; ++i)
8227 for (
unsigned i = TrgNumElts; i < WideNumElts; ++i)
8240 EVT ResVT =
Op.getValueType();
8241 EVT CmpVT =
Op.getOperand(0).getValueType();
8243 SDValue TV =
Op.getOperand(2), FV =
Op.getOperand(3);
8249 if (!Subtarget.hasP9Vector() && CmpVT == MVT::f128) {
8262 SDNodeFlags
Flags =
Op.getNode()->getFlags();
8266 if (Subtarget.hasP9Vector() &&
LHS == TV &&
RHS == FV) {
8283 if (!
Flags.hasNoInfs() || !
Flags.hasNoNaNs() || ResVT == MVT::f128)
8296 if (
LHS.getValueType() == MVT::f32)
8298 Sel1 = DAG.
getNode(PPCISD::FSEL, dl, ResVT,
LHS, TV, FV);
8301 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8309 if (
LHS.getValueType() == MVT::f32)
8311 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
LHS, TV, FV);
8318 if (
LHS.getValueType() == MVT::f32)
8320 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8332 if (
Cmp.getValueType() == MVT::f32)
8334 Sel1 = DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8337 return DAG.
getNode(PPCISD::FSEL, dl, ResVT,
8342 if (
Cmp.getValueType() == MVT::f32)
8344 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV);
8348 if (
Cmp.getValueType() == MVT::f32)
8350 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8354 if (
Cmp.getValueType() == MVT::f32)
8356 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV);
8360 if (
Cmp.getValueType() == MVT::f32)
8362 return DAG.
getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV);
8371 case PPCISD::FCTIDZ:
8372 return PPCISD::STRICT_FCTIDZ;
8373 case PPCISD::FCTIWZ:
8374 return PPCISD::STRICT_FCTIWZ;
8375 case PPCISD::FCTIDUZ:
8376 return PPCISD::STRICT_FCTIDUZ;
8377 case PPCISD::FCTIWUZ:
8378 return PPCISD::STRICT_FCTIWUZ;
8380 return PPCISD::STRICT_FCFID;
8381 case PPCISD::FCFIDU:
8382 return PPCISD::STRICT_FCFIDU;
8383 case PPCISD::FCFIDS:
8384 return PPCISD::STRICT_FCFIDS;
8385 case PPCISD::FCFIDUS:
8386 return PPCISD::STRICT_FCFIDUS;
8393 bool IsStrict =
Op->isStrictFPOpcode();
8402 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8404 MVT DestTy =
Op.getSimpleValueType();
8405 assert(Src.getValueType().isFloatingPoint() &&
8406 (DestTy == MVT::i8 || DestTy == MVT::i16 || DestTy == MVT::i32 ||
8407 DestTy == MVT::i64) &&
8408 "Invalid FP_TO_INT types");
8409 if (Src.getValueType() == MVT::f32) {
8413 DAG.
getVTList(MVT::f64, MVT::Other), {Chain, Src}, Flags);
8418 if ((DestTy == MVT::i8 || DestTy == MVT::i16) && Subtarget.hasP9Vector())
8424 Opc = IsSigned ? PPCISD::FCTIWZ
8425 : (Subtarget.hasFPCVT() ? PPCISD::FCTIWUZ : PPCISD::FCTIDZ);
8428 assert((IsSigned || Subtarget.hasFPCVT()) &&
8429 "i64 FP_TO_UINT is supported only with FPCVT");
8430 Opc = IsSigned ? PPCISD::FCTIDZ : PPCISD::FCTIDUZ;
8432 EVT ConvTy = Src.getValueType() == MVT::f128 ? MVT::f128 : MVT::f64;
8444void PPCTargetLowering::LowerFP_TO_INTForReuse(
SDValue Op, ReuseLoadInfo &RLI,
8446 const SDLoc &dl)
const {
8450 bool IsStrict =
Op->isStrictFPOpcode();
8453 bool i32Stack =
Op.getValueType() == MVT::i32 && Subtarget.hasSTFIWX() &&
8454 (IsSigned || Subtarget.hasFPCVT());
8457 MachinePointerInfo MPI =
8465 Alignment =
Align(4);
8466 MachineMemOperand *MMO =
8472 Chain = DAG.
getStore(Chain, dl, Tmp, FIPtr, MPI, Alignment);
8476 if (
Op.getValueType() == MVT::i32 && !i32Stack &&
8477 !Subtarget.isLittleEndian()) {
8486 RLI.Alignment = Alignment;
8494 const SDLoc &dl)
const {
8497 if (
Op->isStrictFPOpcode())
8504 const SDLoc &dl)
const {
8505 bool IsStrict =
Op->isStrictFPOpcode();
8508 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8509 EVT SrcVT = Src.getValueType();
8510 EVT DstVT =
Op.getValueType();
8513 if (SrcVT == MVT::f128)
8514 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8518 if (SrcVT == MVT::ppcf128) {
8519 if (DstVT == MVT::i32) {
8524 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8535 {Op.getOperand(0), Lo, Hi}, Flags);
8538 {Res.getValue(1), Res}, Flags);
8544 const uint64_t TwoE31[] = {0x41e0000000000000LL, 0};
8568 {Chain, Src, FltOfs}, Flags);
8572 {Chain, Val}, Flags);
8575 dl, DstVT, Sel, DAG.
getConstant(0, dl, DstVT), SignMask);
8593 if (Subtarget.hasDirectMove() && Subtarget.isPPC64())
8594 return LowerFP_TO_INTDirectMove(
Op, DAG, dl);
8597 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8599 return DAG.
getLoad(
Op.getValueType(), dl, RLI.Chain, RLI.Ptr, RLI.MPI,
8600 RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo, RLI.Ranges);
8611bool PPCTargetLowering::canReuseLoadAddress(
SDValue Op,
EVT MemVT,
8616 if (
Op->isStrictFPOpcode())
8621 (Subtarget.hasFPCVT() ||
Op.getValueType() == MVT::i32);
8625 Op.getOperand(0).getValueType())) {
8627 LowerFP_TO_INTForReuse(
Op, RLI, DAG, dl);
8632 if (!LD ||
LD->getExtensionType() != ET ||
LD->isVolatile() ||
8633 LD->isNonTemporal())
8635 if (
LD->getMemoryVT() != MemVT)
8645 RLI.Ptr =
LD->getBasePtr();
8646 if (
LD->isIndexed() && !
LD->getOffset().isUndef()) {
8648 "Non-pre-inc AM on PPC?");
8653 RLI.Chain =
LD->getChain();
8654 RLI.MPI =
LD->getPointerInfo();
8655 RLI.IsDereferenceable =
LD->isDereferenceable();
8656 RLI.IsInvariant =
LD->isInvariant();
8657 RLI.Alignment =
LD->getAlign();
8658 RLI.AAInfo =
LD->getAAInfo();
8659 RLI.Ranges =
LD->getRanges();
8661 RLI.ResChain =
SDValue(LD,
LD->isIndexed() ? 2 : 1);
8668bool PPCTargetLowering::directMoveIsProfitable(
const SDValue &
Op)
const {
8669 SDNode *Origin =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0).getNode();
8676 if (!Subtarget.hasP9Vector() &&
8680 for (SDUse &Use : Origin->
uses()) {
8683 if (
Use.getResNo() != 0)
8710 bool IsSingle =
Op.getValueType() == MVT::f32 && Subtarget.hasFPCVT();
8711 unsigned ConvOpc = IsSingle ? (IsSigned ? PPCISD::FCFIDS : PPCISD::FCFIDUS)
8712 : (IsSigned ? PPCISD::FCFID : PPCISD::FCFIDU);
8713 EVT ConvTy = IsSingle ? MVT::f32 : MVT::f64;
8714 if (
Op->isStrictFPOpcode()) {
8716 Chain =
Op.getOperand(0);
8718 DAG.
getVTList(ConvTy, MVT::Other), {Chain, Src}, Flags);
8720 return DAG.
getNode(ConvOpc, dl, ConvTy, Src);
8728 const SDLoc &dl)
const {
8729 assert((
Op.getValueType() == MVT::f32 ||
8730 Op.getValueType() == MVT::f64) &&
8731 "Invalid floating point type as target of conversion");
8732 assert(Subtarget.hasFPCVT() &&
8733 "Int to FP conversions with direct moves require FPCVT");
8734 SDValue Src =
Op.getOperand(
Op->isStrictFPOpcode() ? 1 : 0);
8735 bool WordInt = Src.getSimpleValueType().SimpleTy == MVT::i32;
8738 unsigned MovOpc = (WordInt && !
Signed) ? PPCISD::MTVSRZ : PPCISD::MTVSRA;
8757 for (
unsigned i = 1; i < NumConcat; ++i)
8764 const SDLoc &dl)
const {
8765 bool IsStrict =
Op->isStrictFPOpcode();
8766 unsigned Opc =
Op.getOpcode();
8767 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8770 "Unexpected conversion type");
8771 assert((
Op.getValueType() == MVT::v2f64 ||
Op.getValueType() == MVT::v4f32) &&
8772 "Supports conversions to v2f64/v4f32 only.");
8776 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8779 bool FourEltRes =
Op.getValueType() == MVT::v4f32;
8784 MVT IntermediateVT = FourEltRes ? MVT::v4i32 : MVT::v2i64;
8786 SmallVector<int, 16> ShuffV;
8787 for (
unsigned i = 0; i < WideNumElts; ++i)
8790 int Stride = FourEltRes ? WideNumElts / 4 : WideNumElts / 2;
8791 int SaveElts = FourEltRes ? 4 : 2;
8792 if (Subtarget.isLittleEndian())
8793 for (
int i = 0; i < SaveElts; i++)
8794 ShuffV[i * Stride] = i;
8796 for (
int i = 1; i <= SaveElts; i++)
8797 ShuffV[i * Stride - 1] = i - 1;
8805 Arrange = DAG.
getBitcast(IntermediateVT, Arrange);
8806 EVT ExtVT = Src.getValueType();
8807 if (Subtarget.hasP9Altivec())
8818 {Op.getOperand(0), Extend}, Flags);
8820 return DAG.
getNode(
Opc, dl,
Op.getValueType(), Extend);
8828 bool IsStrict =
Op->isStrictFPOpcode();
8829 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8834 Flags.setNoFPExcept(
Op->getFlags().hasNoFPExcept());
8836 EVT InVT = Src.getValueType();
8837 EVT OutVT =
Op.getValueType();
8840 return LowerINT_TO_FPVector(
Op, DAG, dl);
8843 if (
Op.getValueType() == MVT::f128)
8844 return Subtarget.hasP9Vector() ?
Op :
SDValue();
8847 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
8850 if (Src.getValueType() == MVT::i1) {
8862 if (Subtarget.hasDirectMove() && directMoveIsProfitable(
Op) &&
8863 Subtarget.isPPC64() && Subtarget.hasFPCVT())
8864 return LowerINT_TO_FPDirectMove(
Op, DAG, dl);
8866 assert((IsSigned || Subtarget.hasFPCVT()) &&
8867 "UINT_TO_FP is supported only with FPCVT");
8869 if (Src.getValueType() == MVT::i64) {
8884 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT() &&
8885 !
Op->getFlags().hasApproximateFuncs()) {
8925 if (canReuseLoadAddress(SINT, MVT::i64, RLI, DAG)) {
8928 Bits = DAG.
getLoad(MVT::f64, dl, RLI.Chain, RLI.Ptr, RLI.MPI,
8929 RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo,
nullptr);
8932 }
else if (Subtarget.hasLFIWAX() &&
8933 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::SEXTLOAD)) {
8934 MachineMemOperand *MMO =
8936 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8940 Ops, MVT::i32, MMO);
8943 }
else if (Subtarget.hasFPCVT() &&
8944 canReuseLoadAddress(SINT, MVT::i32, RLI, DAG,
ISD::ZEXTLOAD)) {
8945 MachineMemOperand *MMO =
8947 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8951 Ops, MVT::i32, MMO);
8954 }
else if (((Subtarget.hasLFIWAX() &&
8956 (Subtarget.hasFPCVT() &&
8971 "Expected an i32 store");
8977 RLI.Alignment =
Align(4);
8979 MachineMemOperand *MMO =
8981 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
8984 PPCISD::LFIWZX : PPCISD::LFIWAX,
8985 dl, DAG.
getVTList(MVT::f64, MVT::Other),
8986 Ops, MVT::i32, MMO);
8987 Chain =
Bits.getValue(1);
8995 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
8999 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)},
9008 assert(Src.getValueType() == MVT::i32 &&
9009 "Unhandled INT_TO_FP type in custom expander!");
9019 if (Subtarget.hasLFIWAX() || Subtarget.hasFPCVT()) {
9022 if (!(ReusingLoad = canReuseLoadAddress(Src, MVT::i32, RLI, DAG))) {
9032 "Expected an i32 store");
9038 RLI.Alignment =
Align(4);
9041 MachineMemOperand *MMO =
9043 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
9049 if (ReusingLoad && RLI.ResChain) {
9053 assert(Subtarget.isPPC64() &&
9054 "i32->FP without LFIWAX supported only on PPC64");
9063 Chain, dl, Ext64, FIdx,
9069 MVT::f64, dl, Chain, FIdx,
9078 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
9082 {Chain, FP, DAG.getIntPtrConstant(0, dl, true)}, Flags);
9099 uint64_t
Mode = CVal->getZExtValue();
9100 assert(
Mode < 4 &&
"Unsupported rounding mode!");
9101 unsigned InternalRnd =
Mode ^ (~(
Mode >> 1) & 1);
9102 if (Subtarget.isISA3_0())
9105 PPC::MFFSCRNI, Dl, {MVT::f64, MVT::Other},
9106 {DAG.getConstant(InternalRnd, Dl, MVT::i32, true), Chain}),
9109 (InternalRnd & 2) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
9110 {DAG.
getConstant(30, Dl, MVT::i32,
true), Chain});
9112 (InternalRnd & 1) ? PPC::MTFSB1 : PPC::MTFSB0, Dl, MVT::Other,
9130 if (!Subtarget.isISA3_0()) {
9131 MFFS = DAG.
getNode(PPCISD::MFFS, Dl, {MVT::f64, MVT::Other}, Chain);
9135 if (Subtarget.isPPC64()) {
9136 if (Subtarget.isISA3_0()) {
9141 PPC::RLDIMI, Dl, MVT::i64,
9146 NewFPSCR =
SDValue(InsertRN, 0);
9153 SDValue Addr = Subtarget.isLittleEndian()
9157 if (Subtarget.isISA3_0()) {
9158 Chain = DAG.
getStore(Chain, Dl, DstFlag, Addr, MachinePointerInfo());
9160 Chain = DAG.
getStore(Chain, Dl, MFFS, StackSlot, MachinePointerInfo());
9162 DAG.
getLoad(MVT::i32, Dl, Chain, Addr, MachinePointerInfo());
9165 PPC::RLWIMI, Dl, MVT::i32,
9166 {Tmp, DstFlag, DAG.getTargetConstant(0, Dl, MVT::i32),
9167 DAG.getTargetConstant(30, Dl, MVT::i32),
9168 DAG.getTargetConstant(31, Dl, MVT::i32)}),
9170 Chain = DAG.
getStore(Chain, Dl, Tmp, Addr, MachinePointerInfo());
9173 DAG.
getLoad(MVT::f64, Dl, Chain, StackSlot, MachinePointerInfo());
9176 if (Subtarget.isISA3_0())
9182 PPC::MTFSF, Dl, MVT::Other,
9210 EVT VT =
Op.getValueType();
9215 SDValue MFFS = DAG.
getNode(PPCISD::MFFS, dl, {MVT::f64, MVT::Other}, Chain);
9226 Chain = DAG.
getStore(Chain, dl, MFFS, StackSlot, MachinePointerInfo());
9230 "Stack slot adjustment is valid only on big endian subtargets!");
9233 CWD = DAG.
getLoad(MVT::i32, dl, Chain, Addr, MachinePointerInfo());
9260 EVT VT =
Op.getValueType();
9264 VT ==
Op.getOperand(1).getValueType() &&
9284 SDValue OutOps[] = { OutLo, OutHi };
9289 EVT VT =
Op.getValueType();
9293 VT ==
Op.getOperand(1).getValueType() &&
9313 SDValue OutOps[] = { OutLo, OutHi };
9319 EVT VT =
Op.getValueType();
9322 VT ==
Op.getOperand(1).getValueType() &&
9342 SDValue OutOps[] = { OutLo, OutHi };
9349 EVT VT =
Op.getValueType();
9356 EVT AmtVT =
Z.getValueType();
9366 X = DAG.
getNode(PPCISD::SHL, dl, VT,
X, IsFSHL ? Z : SubZ);
9367 Y = DAG.
getNode(PPCISD::SRL, dl, VT,
Y, IsFSHL ? SubZ : Z);
9379 static const MVT VTys[] = {
9380 MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
9383 EVT ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1];
9386 if (Val == ((1LLU << (SplatSize * 8)) - 1)) {
9391 EVT CanonicalVT = VTys[SplatSize-1];
9404 const SDLoc &dl,
EVT DestVT = MVT::Other) {
9405 if (DestVT == MVT::Other) DestVT =
Op.getValueType();
9414 EVT DestVT = MVT::Other) {
9415 if (DestVT == MVT::Other) DestVT =
LHS.getValueType();
9424 EVT DestVT = MVT::Other) {
9427 DAG.
getConstant(IID, dl, MVT::i32), Op0, Op1, Op2);
9439 for (
unsigned i = 0; i != 16; ++i)
9460 EVT VecVT = V->getValueType(0);
9461 bool RightType = VecVT == MVT::v2f64 ||
9462 (HasP8Vector && VecVT == MVT::v4f32) ||
9463 (HasDirectMove && (VecVT == MVT::v2i64 || VecVT == MVT::v4i32));
9467 bool IsSplat =
true;
9468 bool IsLoad =
false;
9474 if (V->isConstant())
9476 for (
int i = 0, e = V->getNumOperands(); i < e; ++i) {
9477 if (V->getOperand(i).isUndef())
9481 if (V->getOperand(i).getOpcode() ==
ISD::LOAD ||
9483 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD) ||
9485 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD) ||
9487 V->getOperand(i).getOperand(0).getOpcode() ==
ISD::LOAD))
9491 if (V->getOperand(i) != Op0 ||
9492 (!IsLoad && !V->isOnlyUserOf(V->getOperand(i).getNode())))
9495 return !(IsSplat && IsLoad);
9505 (
Op.getValueType() != MVT::f128))
9510 if ((
Lo.getValueType() != MVT::i64) || (
Hi.getValueType() != MVT::i64))
9513 if (!Subtarget.isLittleEndian())
9516 return DAG.
getNode(PPCISD::BUILD_FP128, dl, MVT::f128,
Lo,
Hi);
9524 InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED) {
9525 IsPermuted = InputLoad->
getOpcode() == PPCISD::SCALAR_TO_VECTOR_PERMUTED;
9538 APFloat APFloatToConvert = ArgAPFloat;
9539 bool LosesInfo =
true;
9544 ArgAPFloat = APFloatToConvert;
9566 APFloat APFloatToConvert = ArgAPFloat;
9567 bool LosesInfo =
true;
9571 return (!LosesInfo && !APFloatToConvert.
isDenormal());
9580 EVT Ty =
Op->getValueType(0);
9583 if ((Ty == MVT::v2f64 || Ty == MVT::v4f32 || Ty == MVT::v4i32) &&
9592 if ((Ty == MVT::v8i16 || Ty == MVT::v16i8) &&
ISD::isEXTLoad(InputNode) &&
9596 if (Ty == MVT::v2i64) {
9599 if (MemVT == MVT::i32) {
9601 Opcode = PPCISD::ZEXT_LD_SPLAT;
9603 Opcode = PPCISD::SEXT_LD_SPLAT;
9611 bool IsLittleEndian) {
9617 APInt ConstValue(VTSize, 0);
9621 unsigned BitPos = 0;
9629 ConstValue.
insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth),
9630 IsLittleEndian ? BitPos : VTSize - EltWidth - BitPos);
9634 for (
unsigned J = 0; J < 16; ++J) {
9636 if (ExtractValue != 0x00 && ExtractValue != 0xFF)
9638 if (ExtractValue == 0xFF)
9653 assert(BVN &&
"Expected a BuildVectorSDNode in LowerBUILD_VECTOR");
9655 if (Subtarget.hasP10Vector()) {
9656 APInt BitMask(32, 0);
9662 BitMask != 0 && BitMask != 0xffff) {
9664 MachineSDNode *MSDNode =
9676 if (
SDValue VecPat = combineBVLoadsSpecialValue(
Op, DAG))
9680 APInt APSplatBits, APSplatUndef;
9681 unsigned SplatBitSize = 0;
9683 bool BVNIsConstantSplat =
9685 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
9691 if (BVNIsConstantSplat && (SplatBitSize == 64) &&
9692 Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
9695 if ((
Op->getValueType(0) == MVT::v2f64) &&
9698 PPCISD::XXSPLTI_SP_TO_DP, dl, MVT::v2f64,
9714 PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9720 DAG.
getNode(PPCISD::XXSPLTI32DX, dl, MVT::v2i64, SplatNode,
9729 LowerVecSplatSmallFP(
Op, DAG, BVNIsConstantSplat, SplatBitSize))
9732 bool IsSplat64 =
false;
9733 uint64_t SplatBits = 0;
9734 int32_t SextVal = 0;
9735 if (BVNIsConstantSplat && SplatBitSize <= 64) {
9737 if (SplatBitSize <= 32) {
9739 }
else if (SplatBitSize == 64 && Subtarget.hasP8Altivec()) {
9740 int64_t Splat64Val =
static_cast<int64_t
>(SplatBits);
9741 bool P9Vector = Subtarget.hasP9Vector();
9742 int32_t
Hi = P9Vector ? 127 : 15;
9743 int32_t
Lo = P9Vector ? -128 : -16;
9744 IsSplat64 = Splat64Val >=
Lo && Splat64Val <=
Hi;
9745 SextVal =
static_cast<int32_t
>(SplatBits);
9749 if (!BVNIsConstantSplat || (SplatBitSize > 32 && !IsSplat64)) {
9750 unsigned NewOpcode = PPCISD::LD_SPLAT;
9756 const SDValue *InputLoad = &
Op.getOperand(0);
9761 unsigned MemorySize =
LD->getMemoryVT().getScalarSizeInBits();
9762 unsigned ElementSize =
9763 MemorySize * ((NewOpcode == PPCISD::LD_SPLAT) ? 1 : 2);
9765 assert(((ElementSize == 2 * MemorySize)
9766 ? (NewOpcode == PPCISD::ZEXT_LD_SPLAT ||
9767 NewOpcode == PPCISD::SEXT_LD_SPLAT)
9768 : (NewOpcode == PPCISD::LD_SPLAT)) &&
9769 "Unmatched element size and opcode!\n");
9774 unsigned NumUsesOfInputLD = 128 / ElementSize;
9776 if (BVInOp.isUndef())
9791 if (NumUsesOfInputLD == 1 &&
9792 (
Op->getValueType(0) == MVT::v2i64 && NewOpcode != PPCISD::LD_SPLAT &&
9793 !Subtarget.isLittleEndian() && Subtarget.hasVSX() &&
9794 Subtarget.hasLFIWAX()))
9802 if (NumUsesOfInputLD == 1 && Subtarget.isLittleEndian() &&
9803 Subtarget.isISA3_1() && ElementSize <= 16)
9806 assert(NumUsesOfInputLD > 0 &&
"No uses of input LD of a build_vector?");
9808 Subtarget.hasVSX()) {
9815 NewOpcode, dl, DAG.
getVTList(
Op.getValueType(), MVT::Other),
Ops,
9816 LD->getMemoryVT(),
LD->getMemOperand());
9828 if (Subtarget.hasVSX() && Subtarget.isPPC64() &&
9830 Subtarget.hasP8Vector()))
9836 unsigned SplatSize = SplatBitSize / 8;
9841 if (SplatBits == 0) {
9843 if (
Op.getValueType() != MVT::v4i32 || HasAnyUndefs) {
9855 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 2)
9857 Op.getValueType(), DAG, dl);
9859 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector() && SplatSize == 4)
9864 if (Subtarget.hasP9Vector() && SplatSize == 1)
9870 if (SextVal >= -16 && SextVal <= 15) {
9873 unsigned UseSize = SplatSize == 8 ? 4 : SplatSize;
9880 DAG.
getBitcast(MVT::v4i32, Res), DAG, dl, MVT::v2i64);
9886 if (Subtarget.hasP9Vector() && SextVal >= -128 && SextVal <= 127) {
9892 switch (SplatSize) {
9896 IID = Intrinsic::ppc_altivec_vupklsb;
9900 IID = Intrinsic::ppc_altivec_vextsb2w;
9904 IID = Intrinsic::ppc_altivec_vextsb2d;
9911 assert(!IsSplat64 &&
"Unhandled 64-bit splat pattern");
9920 if (SextVal >= -32 && SextVal <= 31) {
9925 EVT VT = (SplatSize == 1 ? MVT::v16i8 :
9926 (SplatSize == 2 ? MVT::v8i16 : MVT::v4i32));
9929 if (VT ==
Op.getValueType())
9938 if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) {
9952 static const signed char SplatCsts[] = {
9953 -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
9954 -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
9957 for (
unsigned idx = 0; idx < std::size(SplatCsts); ++idx) {
9960 int i = SplatCsts[idx];
9964 unsigned TypeShiftAmt = i & (SplatBitSize-1);
9967 if (SextVal == (
int)((
unsigned)i << TypeShiftAmt)) {
9969 static const unsigned IIDs[] = {
9970 Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
9971 Intrinsic::ppc_altivec_vslw
9978 if (SextVal == (
int)((
unsigned)i >> TypeShiftAmt)) {
9980 static const unsigned IIDs[] = {
9981 Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
9982 Intrinsic::ppc_altivec_vsrw
9989 if (SextVal == (
int)(((
unsigned)i << TypeShiftAmt) |
9990 ((
unsigned)i >> (SplatBitSize-TypeShiftAmt)))) {
9992 static const unsigned IIDs[] = {
9993 Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0,
9994 Intrinsic::ppc_altivec_vrlw
10001 if (SextVal == (
int)(((
unsigned)i << 8) | (i < 0 ? 0xFF : 0))) {
10003 unsigned Amt = Subtarget.isLittleEndian() ? 15 : 1;
10007 if (SextVal == (
int)(((
unsigned)i << 16) | (i < 0 ? 0xFFFF : 0))) {
10009 unsigned Amt = Subtarget.isLittleEndian() ? 14 : 2;
10013 if (SextVal == (
int)(((
unsigned)i << 24) | (i < 0 ? 0xFFFFFF : 0))) {
10015 unsigned Amt = Subtarget.isLittleEndian() ? 13 : 3;
10028 unsigned OpNum = (PFEntry >> 26) & 0x0F;
10029 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
10030 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
10046 if (LHSID == (1*9+2)*9+3)
return LHS;
10047 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
10059 ShufIdxs[ 0] = 0; ShufIdxs[ 1] = 1; ShufIdxs[ 2] = 2; ShufIdxs[ 3] = 3;
10060 ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19;
10061 ShufIdxs[ 8] = 4; ShufIdxs[ 9] = 5; ShufIdxs[10] = 6; ShufIdxs[11] = 7;
10062 ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23;
10065 ShufIdxs[ 0] = 8; ShufIdxs[ 1] = 9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11;
10066 ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27;
10067 ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15;
10068 ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31;
10071 for (
unsigned i = 0; i != 16; ++i)
10072 ShufIdxs[i] = (i&3)+0;
10075 for (
unsigned i = 0; i != 16; ++i)
10076 ShufIdxs[i] = (i&3)+4;
10079 for (
unsigned i = 0; i != 16; ++i)
10080 ShufIdxs[i] = (i&3)+8;
10083 for (
unsigned i = 0; i != 16; ++i)
10084 ShufIdxs[i] = (i&3)+12;
10105 const unsigned BytesInVector = 16;
10106 bool IsLE = Subtarget.isLittleEndian();
10110 unsigned ShiftElts = 0, InsertAtByte = 0;
10114 unsigned LittleEndianShifts[] = {8, 7, 6, 5, 4, 3, 2, 1,
10115 0, 15, 14, 13, 12, 11, 10, 9};
10116 unsigned BigEndianShifts[] = {9, 10, 11, 12, 13, 14, 15, 0,
10117 1, 2, 3, 4, 5, 6, 7, 8};
10119 ArrayRef<int>
Mask =
N->getMask();
10120 int OriginalOrder[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
10132 bool FoundCandidate =
false;
10136 unsigned VINSERTBSrcElem = IsLE ? 8 : 7;
10139 for (
unsigned i = 0; i < BytesInVector; ++i) {
10140 unsigned CurrentElement =
Mask[i];
10143 if (V2.
isUndef() && CurrentElement != VINSERTBSrcElem)
10146 bool OtherElementsInOrder =
true;
10149 for (
unsigned j = 0;
j < BytesInVector; ++
j) {
10156 (!V2.
isUndef() && CurrentElement < BytesInVector) ? BytesInVector : 0;
10157 if (Mask[j] != OriginalOrder[j] + MaskOffset) {
10158 OtherElementsInOrder =
false;
10165 if (OtherElementsInOrder) {
10172 ShiftElts = IsLE ? LittleEndianShifts[CurrentElement & 0xF]
10173 : BigEndianShifts[CurrentElement & 0xF];
10174 Swap = CurrentElement < BytesInVector;
10176 InsertAtByte = IsLE ? BytesInVector - (i + 1) : i;
10177 FoundCandidate =
true;
10182 if (!FoundCandidate)
10192 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10194 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8,
V1, Shl,
10197 return DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v16i8,
V1, V2,
10206 const unsigned NumHalfWords = 8;
10207 const unsigned BytesInVector = NumHalfWords * 2;
10212 bool IsLE = Subtarget.isLittleEndian();
10216 unsigned ShiftElts = 0, InsertAtByte = 0;
10220 unsigned LittleEndianShifts[] = {4, 3, 2, 1, 0, 7, 6, 5};
10221 unsigned BigEndianShifts[] = {5, 6, 7, 0, 1, 2, 3, 4};
10224 uint32_t OriginalOrderLow = 0x1234567;
10225 uint32_t OriginalOrderHigh = 0x89ABCDEF;
10228 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10229 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10246 bool FoundCandidate =
false;
10249 for (
unsigned i = 0; i < NumHalfWords; ++i) {
10250 unsigned MaskShift = (NumHalfWords - 1 - i) * 4;
10252 uint32_t MaskOtherElts = ~(0xF <<
MaskShift);
10253 uint32_t TargetOrder = 0x0;
10260 unsigned VINSERTHSrcElem = IsLE ? 4 : 3;
10261 TargetOrder = OriginalOrderLow;
10265 if (MaskOneElt == VINSERTHSrcElem &&
10266 (Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10267 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10268 FoundCandidate =
true;
10274 (MaskOneElt < NumHalfWords) ? OriginalOrderHigh : OriginalOrderLow;
10276 if ((Mask & MaskOtherElts) == (TargetOrder & MaskOtherElts)) {
10278 ShiftElts = IsLE ? LittleEndianShifts[MaskOneElt & 0x7]
10279 : BigEndianShifts[MaskOneElt & 0x7];
10280 InsertAtByte = IsLE ? BytesInVector - (i + 1) * 2 : i * 2;
10281 Swap = MaskOneElt < NumHalfWords;
10282 FoundCandidate =
true;
10288 if (!FoundCandidate)
10300 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v16i8, V2, V2,
10303 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10308 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v8i16, Conv1, Conv2,
10323 auto ShuffleMask = SVN->
getMask();
10338 ShuffleMask = CommutedSV->
getMask();
10347 APInt APSplatValue, APSplatUndef;
10348 unsigned SplatBitSize;
10351 HasAnyUndefs, 0, !Subtarget.isLittleEndian()) ||
10363 bool IsLE = Subtarget.isLittleEndian();
10364 if ((ShuffleMask[0] == 0 && ShuffleMask[8] == 8) &&
10365 (ShuffleMask[4] % 4 == 0 && ShuffleMask[12] % 4 == 0 &&
10366 ShuffleMask[4] > 15 && ShuffleMask[12] > 15))
10368 else if ((ShuffleMask[4] == 4 && ShuffleMask[12] == 12) &&
10369 (ShuffleMask[0] % 4 == 0 && ShuffleMask[8] % 4 == 0 &&
10370 ShuffleMask[0] > 15 && ShuffleMask[8] > 15))
10378 for (; SplatBitSize < 32; SplatBitSize <<= 1)
10379 SplatVal |= (SplatVal << SplatBitSize);
10382 PPCISD::XXSPLTI32DX,
DL, MVT::v2i64, DAG.
getBitcast(MVT::v2i64,
LHS),
10393 assert(
Op.getValueType() == MVT::v1i128 &&
10394 "Only set v1i128 as custom, other type shouldn't reach here!");
10399 if (SHLAmt % 8 == 0) {
10400 std::array<int, 16>
Mask;
10401 std::iota(
Mask.begin(),
Mask.end(), 0);
10402 std::rotate(
Mask.begin(),
Mask.begin() + SHLAmt / 8,
Mask.end());
10431 if (
SDValue NewShuffle = combineVectorShuffle(SVOp, DAG)) {
10436 V1 =
Op.getOperand(0);
10437 V2 =
Op.getOperand(1);
10439 EVT VT =
Op.getValueType();
10440 bool isLittleEndian = Subtarget.isLittleEndian();
10442 unsigned ShiftElts, InsertAtByte;
10448 bool IsPermutedLoad =
false;
10450 if (InputLoad && Subtarget.hasVSX() && V2.
isUndef() &&
10460 if (IsPermutedLoad) {
10461 assert((isLittleEndian || IsFourByte) &&
10462 "Unexpected size for permuted load on big endian target");
10463 SplatIdx += IsFourByte ? 2 : 1;
10464 assert((SplatIdx < (IsFourByte ? 4 : 2)) &&
10465 "Splat of a value outside of the loaded memory");
10470 if ((IsFourByte && Subtarget.hasP9Vector()) || !IsFourByte) {
10473 Offset = isLittleEndian ? (3 - SplatIdx) * 4 : SplatIdx * 4;
10475 Offset = isLittleEndian ? (1 - SplatIdx) * 8 : SplatIdx * 8;
10479 if (
LD->getValueType(0).getSizeInBits() == (IsFourByte ? 32 : 64))
10492 DAG.
getVTList(IsFourByte ? MVT::v4i32 : MVT::v2i64, MVT::Other);
10495 Ops,
LD->getMemoryVT(),
LD->getMemOperand());
10504 if (VT == MVT::v2i64 || VT == MVT::v2f64)
10507 if (Subtarget.hasP9Vector() &&
10517 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv2, Conv2,
10519 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Shl,
10523 SDValue Ins = DAG.
getNode(PPCISD::VECINSERT, dl, MVT::v4i32, Conv1, Conv2,
10528 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
10530 if ((SplatInsertNode = lowerToXXSPLTI32DX(SVOp, DAG)))
10531 return SplatInsertNode;
10534 if (Subtarget.hasP9Altivec()) {
10536 if ((NewISDNode = lowerToVINSERTH(SVOp, DAG)))
10539 if ((NewISDNode = lowerToVINSERTB(SVOp, DAG)))
10543 if (Subtarget.hasVSX() &&
10551 SDValue Shl = DAG.
getNode(PPCISD::VECSHL, dl, MVT::v4i32, Conv1, Conv2,
10556 if (Subtarget.hasVSX() &&
10564 SDValue PermDI = DAG.
getNode(PPCISD::XXPERMDI, dl, MVT::v2i64, Conv1, Conv2,
10569 if (Subtarget.hasP9Vector()) {
10589 if (Subtarget.hasVSX()) {
10602 SDValue Swap = DAG.
getNode(PPCISD::SWAP_NO_CHAIN, dl, MVT::v2f64, Conv);
10610 if (V2.isUndef()) {
10623 (Subtarget.hasP8Altivec() && (
10634 unsigned int ShuffleKind = isLittleEndian ? 2 : 0;
10644 (Subtarget.hasP8Altivec() && (
10652 ArrayRef<int> PermMask = SVOp->
getMask();
10655 unsigned PFIndexes[4];
10656 bool isFourElementShuffle =
true;
10657 for (
unsigned i = 0; i != 4 && isFourElementShuffle;
10659 unsigned EltNo = 8;
10660 for (
unsigned j = 0;
j != 4; ++
j) {
10661 if (PermMask[i * 4 + j] < 0)
10664 unsigned ByteSource = PermMask[i * 4 +
j];
10665 if ((ByteSource & 3) != j) {
10666 isFourElementShuffle =
false;
10671 EltNo = ByteSource / 4;
10672 }
else if (EltNo != ByteSource / 4) {
10673 isFourElementShuffle =
false;
10677 PFIndexes[i] = EltNo;
10685 if (isFourElementShuffle) {
10687 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
10688 PFIndexes[2] * 9 + PFIndexes[3];
10691 unsigned Cost = (PFEntry >> 30);
10711 if (V2.isUndef()) V2 =
V1;
10713 return LowerVPERM(
Op, DAG, PermMask, VT,
V1, V2);
10719 unsigned Opcode = PPCISD::VPERM;
10722 bool NeedSwap =
false;
10723 bool isLittleEndian = Subtarget.isLittleEndian();
10724 bool isPPC64 = Subtarget.isPPC64();
10726 if (Subtarget.hasVSX() && Subtarget.hasP9Vector() &&
10728 LLVM_DEBUG(
dbgs() <<
"At least one of two input vectors are dead - using "
10729 "XXPERM instead\n");
10730 Opcode = PPCISD::XXPERM;
10735 if ((!isLittleEndian && !V2->
hasOneUse() &&
V1->hasOneUse()) ||
10736 (isLittleEndian && !
V1->hasOneUse() && V2->
hasOneUse())) {
10738 NeedSwap = !NeedSwap;
10752 bool V1HasXXSWAPD =
V1->getOperand(0)->getOpcode() == PPCISD::XXSWAPD;
10773 unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i];
10775 if (V1HasXXSWAPD) {
10778 else if (SrcElt < 16)
10781 if (V2HasXXSWAPD) {
10784 else if (SrcElt > 15)
10793 for (
unsigned j = 0;
j != BytesPerElement; ++
j)
10794 if (isLittleEndian)
10796 DAG.
getConstant(31 - (SrcElt * BytesPerElement + j), dl, MVT::i32));
10799 DAG.
getConstant(SrcElt * BytesPerElement + j, dl, MVT::i32));
10802 if (V1HasXXSWAPD) {
10803 dl = SDLoc(
V1->getOperand(0));
10804 V1 =
V1->getOperand(0)->getOperand(1);
10806 if (V2HasXXSWAPD) {
10811 if (isPPC64 && (V1HasXXSWAPD || V2HasXXSWAPD)) {
10812 if (ValType != MVT::v2f64)
10818 ShufflesHandledWithVPERM++;
10822 if (Opcode == PPCISD::XXPERM) {
10823 dbgs() <<
"Emitting a XXPERM for the following shuffle:\n";
10825 dbgs() <<
"Emitting a VPERM for the following shuffle:\n";
10828 dbgs() <<
"With the following permute control vector:\n";
10832 if (Opcode == PPCISD::XXPERM)
10833 VPermMask = DAG.
getBitcast(MVT::v4i32, VPermMask);
10837 if (isLittleEndian)
10841 DAG.
getNode(Opcode, dl,
V1.getValueType(),
V1, V2, VPermMask);
10843 VPERMNode = DAG.
getBitcast(ValType, VPERMNode);
10855 switch (IntrinsicID) {
10859 case Intrinsic::ppc_altivec_vcmpbfp_p:
10863 case Intrinsic::ppc_altivec_vcmpeqfp_p:
10867 case Intrinsic::ppc_altivec_vcmpequb_p:
10871 case Intrinsic::ppc_altivec_vcmpequh_p:
10875 case Intrinsic::ppc_altivec_vcmpequw_p:
10879 case Intrinsic::ppc_altivec_vcmpequd_p:
10880 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10886 case Intrinsic::ppc_altivec_vcmpneb_p:
10887 case Intrinsic::ppc_altivec_vcmpneh_p:
10888 case Intrinsic::ppc_altivec_vcmpnew_p:
10889 case Intrinsic::ppc_altivec_vcmpnezb_p:
10890 case Intrinsic::ppc_altivec_vcmpnezh_p:
10891 case Intrinsic::ppc_altivec_vcmpnezw_p:
10892 if (Subtarget.hasP9Altivec()) {
10893 switch (IntrinsicID) {
10896 case Intrinsic::ppc_altivec_vcmpneb_p:
10899 case Intrinsic::ppc_altivec_vcmpneh_p:
10902 case Intrinsic::ppc_altivec_vcmpnew_p:
10905 case Intrinsic::ppc_altivec_vcmpnezb_p:
10908 case Intrinsic::ppc_altivec_vcmpnezh_p:
10911 case Intrinsic::ppc_altivec_vcmpnezw_p:
10919 case Intrinsic::ppc_altivec_vcmpgefp_p:
10923 case Intrinsic::ppc_altivec_vcmpgtfp_p:
10927 case Intrinsic::ppc_altivec_vcmpgtsb_p:
10931 case Intrinsic::ppc_altivec_vcmpgtsh_p:
10935 case Intrinsic::ppc_altivec_vcmpgtsw_p:
10939 case Intrinsic::ppc_altivec_vcmpgtsd_p:
10940 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10946 case Intrinsic::ppc_altivec_vcmpgtub_p:
10950 case Intrinsic::ppc_altivec_vcmpgtuh_p:
10954 case Intrinsic::ppc_altivec_vcmpgtuw_p:
10958 case Intrinsic::ppc_altivec_vcmpgtud_p:
10959 if (Subtarget.hasVSX() || Subtarget.hasP8Altivec()) {
10966 case Intrinsic::ppc_altivec_vcmpequq:
10967 case Intrinsic::ppc_altivec_vcmpgtsq:
10968 case Intrinsic::ppc_altivec_vcmpgtuq:
10969 if (!Subtarget.isISA3_1())
10971 switch (IntrinsicID) {
10974 case Intrinsic::ppc_altivec_vcmpequq:
10977 case Intrinsic::ppc_altivec_vcmpgtsq:
10980 case Intrinsic::ppc_altivec_vcmpgtuq:
10987 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10988 case Intrinsic::ppc_vsx_xvcmpgedp_p:
10989 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
10990 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
10991 case Intrinsic::ppc_vsx_xvcmpgesp_p:
10992 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
10993 if (Subtarget.hasVSX()) {
10994 switch (IntrinsicID) {
10995 case Intrinsic::ppc_vsx_xvcmpeqdp_p:
10998 case Intrinsic::ppc_vsx_xvcmpgedp_p:
11001 case Intrinsic::ppc_vsx_xvcmpgtdp_p:
11004 case Intrinsic::ppc_vsx_xvcmpeqsp_p:
11007 case Intrinsic::ppc_vsx_xvcmpgesp_p:
11010 case Intrinsic::ppc_vsx_xvcmpgtsp_p:
11020 case Intrinsic::ppc_altivec_vcmpbfp:
11023 case Intrinsic::ppc_altivec_vcmpeqfp:
11026 case Intrinsic::ppc_altivec_vcmpequb:
11029 case Intrinsic::ppc_altivec_vcmpequh:
11032 case Intrinsic::ppc_altivec_vcmpequw:
11035 case Intrinsic::ppc_altivec_vcmpequd:
11036 if (Subtarget.hasP8Altivec())
11041 case Intrinsic::ppc_altivec_vcmpneb:
11042 case Intrinsic::ppc_altivec_vcmpneh:
11043 case Intrinsic::ppc_altivec_vcmpnew:
11044 case Intrinsic::ppc_altivec_vcmpnezb:
11045 case Intrinsic::ppc_altivec_vcmpnezh:
11046 case Intrinsic::ppc_altivec_vcmpnezw:
11047 if (Subtarget.hasP9Altivec())
11048 switch (IntrinsicID) {
11051 case Intrinsic::ppc_altivec_vcmpneb:
11054 case Intrinsic::ppc_altivec_vcmpneh:
11057 case Intrinsic::ppc_altivec_vcmpnew:
11060 case Intrinsic::ppc_altivec_vcmpnezb:
11063 case Intrinsic::ppc_altivec_vcmpnezh:
11066 case Intrinsic::ppc_altivec_vcmpnezw:
11073 case Intrinsic::ppc_altivec_vcmpgefp:
11076 case Intrinsic::ppc_altivec_vcmpgtfp:
11079 case Intrinsic::ppc_altivec_vcmpgtsb:
11082 case Intrinsic::ppc_altivec_vcmpgtsh:
11085 case Intrinsic::ppc_altivec_vcmpgtsw:
11088 case Intrinsic::ppc_altivec_vcmpgtsd:
11089 if (Subtarget.hasP8Altivec())
11094 case Intrinsic::ppc_altivec_vcmpgtub:
11097 case Intrinsic::ppc_altivec_vcmpgtuh:
11100 case Intrinsic::ppc_altivec_vcmpgtuw:
11103 case Intrinsic::ppc_altivec_vcmpgtud:
11104 if (Subtarget.hasP8Altivec())
11109 case Intrinsic::ppc_altivec_vcmpequq_p:
11110 case Intrinsic::ppc_altivec_vcmpgtsq_p:
11111 case Intrinsic::ppc_altivec_vcmpgtuq_p:
11112 if (!Subtarget.isISA3_1())
11114 switch (IntrinsicID) {
11117 case Intrinsic::ppc_altivec_vcmpequq_p:
11120 case Intrinsic::ppc_altivec_vcmpgtsq_p:
11123 case Intrinsic::ppc_altivec_vcmpgtuq_p:
11137 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11143 auto MapNodeWithSplatVector =
11144 [&](
unsigned Opcode,
11145 std::initializer_list<SDValue> ExtraOps = {}) ->
SDValue {
11150 Ops.append(ExtraOps.begin(), ExtraOps.end());
11151 return DAG.
getNode(Opcode, dl, MVT::v16i8,
Ops);
11154 switch (IntrinsicID) {
11155 case Intrinsic::thread_pointer:
11157 if (Subtarget.isPPC64())
11161 case Intrinsic::ppc_rldimi: {
11162 assert(Subtarget.isPPC64() &&
"rldimi is only available in 64-bit!");
11164 APInt
Mask =
Op.getConstantOperandAPInt(4);
11166 return Op.getOperand(2);
11167 if (
Mask.isAllOnes())
11169 uint64_t SH =
Op.getConstantOperandVal(3);
11170 unsigned MB = 0, ME = 0;
11174 if (ME < 63 - SH) {
11177 }
else if (ME > 63 - SH) {
11183 {Op.getOperand(2), Src,
11184 DAG.getTargetConstant(63 - ME, dl, MVT::i32),
11185 DAG.getTargetConstant(MB, dl, MVT::i32)}),
11189 case Intrinsic::ppc_rlwimi: {
11190 APInt
Mask =
Op.getConstantOperandAPInt(4);
11192 return Op.getOperand(2);
11193 if (
Mask.isAllOnes())
11196 unsigned MB = 0, ME = 0;
11200 PPC::RLWIMI, dl, MVT::i32,
11201 {Op.getOperand(2), Op.getOperand(1), Op.getOperand(3),
11202 DAG.getTargetConstant(MB, dl, MVT::i32),
11203 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11207 case Intrinsic::ppc_bcdshift:
11208 return MapNodeWithSplatVector(PPCISD::BCDSHIFT, {
Op.getOperand(3)});
11209 case Intrinsic::ppc_bcdshiftround:
11210 return MapNodeWithSplatVector(PPCISD::BCDSHIFTROUND, {
Op.getOperand(3)});
11211 case Intrinsic::ppc_bcdtruncate:
11212 return MapNodeWithSplatVector(PPCISD::BCDTRUNC, {
Op.getOperand(3)});
11213 case Intrinsic::ppc_bcdunsignedtruncate:
11214 return MapNodeWithSplatVector(PPCISD::BCDUTRUNC);
11215 case Intrinsic::ppc_bcdunsignedshift:
11216 return MapNodeWithSplatVector(PPCISD::BCDUSHIFT);
11218 case Intrinsic::ppc_rlwnm: {
11219 if (
Op.getConstantOperandVal(3) == 0)
11221 unsigned MB = 0, ME = 0;
11226 {Op.getOperand(1), Op.getOperand(2),
11227 DAG.getTargetConstant(MB, dl, MVT::i32),
11228 DAG.getTargetConstant(ME, dl, MVT::i32)}),
11232 case Intrinsic::ppc_mma_disassemble_acc: {
11233 if (Subtarget.isISAFuture()) {
11234 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11245 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11246 Subtarget.isLittleEndian() ? Value2 :
Value,
11247 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11251 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11252 Subtarget.isLittleEndian() ? Value2 :
Value,
11253 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11257 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11258 Subtarget.isLittleEndian() ?
Value : Value2,
11259 DAG.
getConstant(Subtarget.isLittleEndian() ? 1 : 0,
11263 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
11264 Subtarget.isLittleEndian() ?
Value : Value2,
11265 DAG.
getConstant(Subtarget.isLittleEndian() ? 0 : 1,
11272 case Intrinsic::ppc_vsx_disassemble_pair: {
11275 if (IntrinsicID == Intrinsic::ppc_mma_disassemble_acc) {
11277 WideVec = DAG.
getNode(PPCISD::XXMFACC, dl, MVT::v512i1, WideVec);
11280 for (
int VecNo = 0; VecNo < NumVecs; VecNo++) {
11282 PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8, WideVec,
11283 DAG.
getConstant(Subtarget.isLittleEndian() ? NumVecs - 1 - VecNo
11291 case Intrinsic::ppc_build_dmr: {
11294 for (
int i = 1; i < 9; i += 2) {
11302 DAG.
getNode(PPCISD::PAIR_BUILD, dl, MVT::v256i1, {Hi, Lo}));
11309 case Intrinsic::ppc_mma_dmxxextfdmr512: {
11310 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr512 requires ISA Future");
11312 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11313 "Specify P of 0 or 1 for lower or upper 512 bytes");
11314 unsigned HiLo = Idx->getSExtValue();
11318 Opcode = PPC::DMXXEXTFDMR512;
11319 Subx = PPC::sub_wacc_lo;
11321 Opcode = PPC::DMXXEXTFDMR512_HI;
11322 Subx = PPC::sub_wacc_hi;
11325 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
11329 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
11333 case Intrinsic::ppc_mma_dmxxextfdmr256: {
11334 assert(Subtarget.isISAFuture() &&
"dmxxextfdmr256 requires ISA Future");
11336 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11337 "Specify a dmr row pair 0-3");
11338 unsigned IdxVal = Idx->getSExtValue();
11342 Subx = PPC::sub_dmrrowp0;
11345 Subx = PPC::sub_dmrrowp1;
11348 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11351 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11355 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v256i1,
11361 DAG.
getMachineNode(PPC::DMXXEXTFDMR256, dl, MVT::v256i1, {Subreg, P}),
11365 case Intrinsic::ppc_mma_dmxxinstdmr512: {
11366 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr512 requires ISA Future");
11368 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11369 "Specify P of 0 or 1 for lower or upper 512 bytes");
11370 unsigned HiLo = Idx->getSExtValue();
11374 Opcode = PPCISD::INST512;
11375 Subx = PPC::sub_wacc_lo;
11377 Opcode = PPCISD::INST512HI;
11378 Subx = PPC::sub_wacc_hi;
11384 Op.getOperand(1), Wacc, SubReg),
11388 case Intrinsic::ppc_mma_dmxxinstdmr256: {
11389 assert(Subtarget.isISAFuture() &&
"dmxxinstdmr256 requires ISA Future");
11391 assert(Idx && (Idx->getSExtValue() >= 0 || Idx->getSExtValue() <= 3) &&
11392 "Specify a dmr row pair 0-3");
11393 unsigned IdxVal = Idx->getSExtValue();
11397 Subx = PPC::sub_dmrrowp0;
11400 Subx = PPC::sub_dmrrowp1;
11403 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp0;
11406 Subx = PPC::sub_wacc_hi_then_sub_dmrrowp1;
11412 DAG.
getNode(PPCISD::INST256, dl, MVT::v256i1,
Op.getOperand(2),
P);
11414 Op.getOperand(1), DMRRowp, SubReg),
11418 case Intrinsic::ppc_mma_xxmfacc:
11419 case Intrinsic::ppc_mma_xxmtacc: {
11421 if (!Subtarget.isISAFuture())
11432 case Intrinsic::ppc_unpack_longdouble: {
11434 assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) &&
11435 "Argument of long double unpack must be 0 or 1!");
11438 Idx->getValueType(0)));
11441 case Intrinsic::ppc_compare_exp_lt:
11442 case Intrinsic::ppc_compare_exp_gt:
11443 case Intrinsic::ppc_compare_exp_eq:
11444 case Intrinsic::ppc_compare_exp_uo: {
11446 switch (IntrinsicID) {
11447 case Intrinsic::ppc_compare_exp_lt:
11450 case Intrinsic::ppc_compare_exp_gt:
11453 case Intrinsic::ppc_compare_exp_eq:
11456 case Intrinsic::ppc_compare_exp_uo:
11462 PPC::SELECT_CC_I4, dl, MVT::i32,
11463 {SDValue(DAG.getMachineNode(PPC::XSCMPEXPDP, dl, MVT::i32,
11464 Op.getOperand(1), Op.getOperand(2)),
11466 DAG.getConstant(1, dl, MVT::i32), DAG.getConstant(0, dl, MVT::i32),
11467 DAG.getTargetConstant(Pred, dl, MVT::i32)}),
11470 case Intrinsic::ppc_test_data_class: {
11471 EVT OpVT =
Op.getOperand(1).getValueType();
11472 unsigned CmprOpc = OpVT == MVT::f128 ? PPC::XSTSTDCQP
11473 : (OpVT == MVT::f64 ? PPC::XSTSTDCDP
11486 {Op.getOperand(2), Op.getOperand(1)}),
11488 if (Subtarget.isISA3_1()) {
11495 TestDataClass, SubRegIdx),
11498 return DAG.
getNode(PPCISD::SETBC, dl, MVT::i32, CRBit);
11504 {TestDataClass, DAG.getConstant(1, dl, MVT::i32),
11505 DAG.getConstant(0, dl, MVT::i32),
11506 DAG.getTargetConstant(PPC::PRED_EQ, dl, MVT::i32)}),
11509 case Intrinsic::ppc_fnmsub: {
11510 EVT VT =
Op.getOperand(1).getValueType();
11511 if (!Subtarget.hasVSX() || (!Subtarget.hasFloat128() && VT == MVT::f128))
11516 return DAG.
getNode(PPCISD::FNMSUB, dl, VT,
Op.getOperand(1),
11517 Op.getOperand(2),
Op.getOperand(3));
11519 case Intrinsic::ppc_convert_f128_to_ppcf128:
11520 case Intrinsic::ppc_convert_ppcf128_to_f128: {
11521 RTLIB::Libcall LC = IntrinsicID == Intrinsic::ppc_convert_ppcf128_to_f128
11522 ? RTLIB::CONVERT_PPCF128_F128
11523 : RTLIB::CONVERT_F128_PPCF128;
11525 std::pair<SDValue, SDValue>
Result =
11526 makeLibCall(DAG, LC,
Op.getValueType(),
Op.getOperand(1), CallOptions,
11530 case Intrinsic::ppc_maxfe:
11531 case Intrinsic::ppc_maxfl:
11532 case Intrinsic::ppc_maxfs:
11533 case Intrinsic::ppc_minfe:
11534 case Intrinsic::ppc_minfl:
11535 case Intrinsic::ppc_minfs: {
11536 EVT VT =
Op.getValueType();
11539 [VT](
const SDUse &Use) { return Use.getValueType() == VT; }) &&
11540 "ppc_[max|min]f[e|l|s] must have uniform type arguments");
11543 if (IntrinsicID == Intrinsic::ppc_minfe ||
11544 IntrinsicID == Intrinsic::ppc_minfl ||
11545 IntrinsicID == Intrinsic::ppc_minfs)
11566 SDValue Tmp = DAG.
getNode(PPCISD::VCMP, dl,
Op.getOperand(2).getValueType(),
11567 Op.getOperand(1),
Op.getOperand(2),
11578 EVT VTs[] = {
Op.getOperand(2).getValueType(), MVT::Glue };
11586 switch (
Op.getConstantOperandVal(1)) {
11591 Bitx = PPC::sub_eq;
11592 SetOp = PPCISD::SETBC;
11597 Bitx = PPC::sub_eq;
11598 SetOp = PPCISD::SETBCR;
11603 Bitx = PPC::sub_lt;
11604 SetOp = PPCISD::SETBC;
11609 Bitx = PPC::sub_lt;
11610 SetOp = PPCISD::SETBCR;
11615 if (Subtarget.isISA3_1()) {
11620 CR6Reg, SubRegIdx, GlueOp),
11622 return DAG.
getNode(SetOp, dl, MVT::i32, CRBit);
11650 switch (
Op.getConstantOperandVal(ArgStart)) {
11651 case Intrinsic::ppc_cfence: {
11652 assert(ArgStart == 1 &&
"llvm.ppc.cfence must carry a chain argument.");
11653 SDValue Val =
Op.getOperand(ArgStart + 1);
11655 if (Ty == MVT::i128) {
11660 unsigned Opcode = Subtarget.isPPC64() ? PPC::CFENCE8 : PPC::CFENCE;
11663 Opcode,
DL, MVT::Other,
11668 case Intrinsic::ppc_disassemble_dmr: {
11670 "llvm.ppc.disassemble.dmr must carry a chain argument.");
11671 return DAG.
getStore(
Op.getOperand(0),
DL,
Op.getOperand(ArgStart + 2),
11672 Op.getOperand(ArgStart + 1), MachinePointerInfo());
11683 if (!Subtarget.isPPC64())
11686 if (Subtarget.hasP9Vector()) {
11693 int VectorIndex = 0;
11694 if (Subtarget.isLittleEndian())
11704 auto CreateRotateInsert =
11705 [&](
unsigned Opcode, MVT VT,
SDValue Dest,
SDValue Src,
unsigned RotAmt,
11706 unsigned MaskBegin,
11707 std::optional<unsigned> MaskEnd = std::nullopt) ->
SDValue {
11711 if (MaskEnd.has_value())
11723 CreateRotateInsert(PPC::RLWIMI, MVT::i32, Rot, Val32, 24, 0, 7);
11725 return CreateRotateInsert(PPC::RLWIMI, MVT::i32, Swap, Val32, 24, 16, 23);
11738 return CreateRotateInsert(PPC::RLDIMI, MVT::i64, HiSwap, LoSwap, 32, 0);
11746 "Expecting an atomic compare-and-swap here.");
11749 EVT MemVT = AtomicNode->getMemoryVT();
11767 for (
int i = 0, e = AtomicNode->getNumOperands(); i < e; i++)
11768 Ops.push_back(AtomicNode->getOperand(i));
11770 MachineMemOperand *MMO = AtomicNode->getMemOperand();
11771 SDVTList Tys = DAG.
getVTList(MVT::i32, MVT::Other);
11773 (MemVT == MVT::i8) ? PPCISD::ATOMIC_CMP_SWAP_8 : PPCISD::ATOMIC_CMP_SWAP_16;
11780 EVT MemVT =
N->getMemoryVT();
11782 "Expect quadword atomic operations");
11784 unsigned Opc =
N->getOpcode();
11789 SDVTList Tys = DAG.
getVTList(MVT::i64, MVT::i64, MVT::Other);
11792 DAG.
getConstant(Intrinsic::ppc_atomic_load_i128, dl, MVT::i32)};
11793 for (
int I = 1,
E =
N->getNumOperands();
I <
E; ++
I)
11794 Ops.push_back(
N->getOperand(
I));
11796 Ops, MemVT,
N->getMemOperand());
11803 DAG.
getNode(
ISD::OR, dl, {MVT::i128, MVT::Other}, {ValLo, ValHi});
11810 SDVTList Tys = DAG.
getVTList(MVT::Other);
11813 DAG.
getConstant(Intrinsic::ppc_atomic_store_i128, dl, MVT::i32)};
11819 Ops.push_back(ValLo);
11820 Ops.push_back(ValHi);
11821 Ops.push_back(
N->getOperand(2));
11823 N->getMemOperand());
11835 enum DataClassMask {
11837 DC_NEG_INF = 1 << 4,
11838 DC_POS_INF = 1 << 5,
11839 DC_NEG_ZERO = 1 << 2,
11840 DC_POS_ZERO = 1 << 3,
11841 DC_NEG_SUBNORM = 1,
11842 DC_POS_SUBNORM = 1 << 1,
11845 EVT VT =
Op.getValueType();
11847 unsigned TestOp = VT == MVT::f128 ? PPC::XSTSTDCQP
11848 : VT == MVT::f64 ? PPC::XSTSTDCDP
11859 return DAG.
getNOT(Dl, Rev, MVT::i1);
11866 TestOp, Dl, MVT::i32,
11868 DC_NEG_ZERO | DC_POS_ZERO |
11869 DC_NEG_SUBNORM | DC_POS_SUBNORM,
11875 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11881 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1, Rev,
11886 Sign = DAG.
getNOT(Dl, Sign, MVT::i1);
11899 bool IsQuiet = Mask &
fcQNan;
11905 if (VT == MVT::f128) {
11909 QuietMask = 0x8000;
11910 }
else if (VT == MVT::f64) {
11911 if (Subtarget.isPPC64()) {
11922 QuietMask = 0x80000;
11923 }
else if (VT == MVT::f32) {
11925 QuietMask = 0x400000;
11941 unsigned NativeMask = 0;
11943 NativeMask |= DC_NAN;
11945 NativeMask |= DC_NEG_INF;
11947 NativeMask |= DC_POS_INF;
11949 NativeMask |= DC_NEG_ZERO;
11951 NativeMask |= DC_POS_ZERO;
11953 NativeMask |= DC_NEG_SUBNORM;
11955 NativeMask |= DC_POS_SUBNORM;
11958 TargetOpcode::EXTRACT_SUBREG, Dl, MVT::i1,
11960 TestOp, Dl, MVT::i32,
11969 assert(Subtarget.hasP9Vector() &&
"Test data class requires Power9");
11971 uint64_t RHSC =
Op.getConstantOperandVal(1);
11974 if (
LHS.getValueType() == MVT::ppcf128) {
11998 bool Future = Subtarget.isISAFuture();
12001 "Mask predication not supported");
12004 unsigned IID = Future ? Intrinsic::ppc_vsx_lxvrl : Intrinsic::ppc_vsx_lxvl;
12005 unsigned EltBits =
Op->getValueType(0).getScalarType().getSizeInBits();
12009 SDVTList Tys = DAG.
getVTList(
Op->getValueType(0), MVT::Other);
12012 VPLD->getMemoryVT(), VPLD->getMemOperand());
12019 "Mask predication not supported");
12024 Op->getOperand(1).getValueType().getScalarType().getSizeInBits();
12025 bool Future = Subtarget.isISAFuture();
12026 unsigned IID = Future ? Intrinsic::ppc_vsx_stxvrl : Intrinsic::ppc_vsx_stxvl;
12029 VPST->getChain(), DAG.
getConstant(IID, dl, MVT::i32),
12032 SDVTList Tys = DAG.
getVTList(MVT::Other);
12035 VPST->getMemoryVT(), VPST->getMemOperand());
12046 "Unexpected partial reduction");
12069 unsigned EltSize =
Op.getValueType().getScalarSizeInBits();
12071 int64_t
IntVal =
Op.getConstantOperandVal(0);
12072 if (IntVal >= -16 && IntVal <= 15)
12078 if (Subtarget.hasLFIWAX() && Subtarget.hasVSX() &&
12083 MachineMemOperand *MMO =
12085 RLI.Alignment, RLI.AAInfo, RLI.Ranges);
12088 PPCISD::LD_SPLAT, dl, DAG.
getVTList(MVT::v4i32, MVT::Other),
Ops,
12092 return Bits.getValue(0);
12108 !Subtarget.isLittleEndian() && ValVT.
isInteger() &&
12113 64 -
Op.getValueType().getScalarSizeInBits(), dl, ShiftAmountTy);
12120 return DAG.
getLoad(
Op.getValueType(), dl, Store, FIdx,
12121 MachinePointerInfo());
12128 return DAG.
getLoad(
Op.getValueType(), dl, Store, FIdx, MachinePointerInfo());
12134 "Should only be called for ISD::INSERT_VECTOR_ELT");
12138 EVT VT =
Op.getValueType();
12143 if (VT == MVT::v2f64 &&
C)
12146 if (Subtarget.hasP9Vector()) {
12155 if ((VT == MVT::v4f32) && (V2.
getValueType() == MVT::f32) &&
12161 BitcastLoad,
Op.getOperand(2));
12162 return DAG.
getBitcast(MVT::v4f32, InsVecElt);
12166 if (Subtarget.isISA3_1()) {
12167 if ((VT == MVT::v2i64 || VT == MVT::v2f64) && !Subtarget.isPPC64())
12171 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
12172 VT == MVT::v2i64 || VT == MVT::v4f32 || VT == MVT::v2f64)
12182 if (VT == MVT::v8i16 || VT == MVT::v16i8) {
12185 unsigned InsertAtElement =
C->getZExtValue();
12186 unsigned InsertAtByte = InsertAtElement * BytesInEachElement;
12187 if (Subtarget.isLittleEndian()) {
12188 InsertAtByte = (16 - BytesInEachElement) - InsertAtByte;
12190 return DAG.
getNode(PPCISD::VECINSERT, dl, VT,
V1, Mtvsrz,
12202 EVT VT =
Op.getValueType();
12203 bool IsV1024i1 = VT == MVT::v1024i1;
12204 bool IsV2048i1 = VT == MVT::v2048i1;
12208 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12210 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12211 "Dense Math support required.");
12212 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12221 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12222 MachineMemOperand *NewMMO =
12230 DAG.
getVTList(MVT::v256i1, MVT::Other),
12231 LoadOps, MVT::v256i1, NewMMO);
12236 if (Subtarget.isLittleEndian()) {
12237 std::reverse(Loads.
begin(), Loads.
end());
12238 std::reverse(LoadChains.
begin(), LoadChains.
end());
12250 SDValue Dmr1Value = DMFInsert1024(MoreLoads, dl, DAG);
12256 const SDValue DmrPOps[] = {DmrPRC,
Value, Dmr0Sub, Dmr1Value, Dmr1Sub};
12259 DAG.
getMachineNode(PPC::REG_SEQUENCE, dl, MVT::v2048i1, DmrPOps), 0);
12268 DAG.
getNode(PPCISD::INST512, dl, MVT::v512i1, Pairs[0], Pairs[1]);
12271 DAG.
getNode(PPCISD::INST512HI, dl, MVT::v512i1, Pairs[2], Pairs[3]);
12276 {RC, Lo, LoSub, Hi, HiSub}),
12286 EVT VT =
Op.getValueType();
12288 if (VT == MVT::v1024i1 || VT == MVT::v2048i1)
12289 return LowerDMFVectorLoad(
Op, DAG);
12291 if (VT != MVT::v256i1 && VT != MVT::v512i1)
12295 assert((VT != MVT::v512i1 || Subtarget.hasMMA()) &&
12296 "Type unsupported without MMA");
12297 assert((VT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12298 "Type unsupported without paired vector support");
12302 if (VT == MVT::v256i1 && Subtarget.isISAFuture())
12311 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12313 DAG.
getLoad(MVT::v16i8, dl, LoadChain, BasePtr,
12322 if (Subtarget.isLittleEndian()) {
12323 std::reverse(Loads.
begin(), Loads.
end());
12324 std::reverse(LoadChains.
begin(), LoadChains.
end());
12328 DAG.
getNode(VT == MVT::v512i1 ? PPCISD::ACC_BUILD : PPCISD::PAIR_BUILD,
12344 bool IsV1024i1 = VT == MVT::v1024i1;
12345 bool IsV2048i1 = VT == MVT::v2048i1;
12349 assert((IsV1024i1 || IsV2048i1) &&
"Unsupported type.");
12351 assert((Subtarget.hasMMA() && Subtarget.isISAFuture()) &&
12352 "Dense Math support required.");
12353 assert(Subtarget.pairedVectorMemops() &&
"Vector pair support required.");
12355 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12358 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12363 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1,
12367 MachineSDNode *ExtNode =
12371 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes,
Hi);
12377 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12383 DAG.
getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::v1024i1,
12389 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12394 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr0,
12399 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12404 TargetOpcode::EXTRACT_SUBREG, dl, MVT::v512i1, Dmr1,
12408 MachineSDNode *ExtNode =
12409 DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr0Lo);
12413 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr0Hi);
12416 ExtNode = DAG.
getMachineNode(PPC::DMXXEXTFDMR512, dl, ReturnTypes, Dmr1Lo);
12420 DAG.
getMachineNode(PPC::DMXXEXTFDMR512_HI, dl, ReturnTypes, Dmr1Hi);
12425 if (Subtarget.isLittleEndian())
12426 std::reverse(Values.
begin(), Values.
end());
12428 SDVTList Tys = DAG.
getVTList(MVT::Other);
12430 StoreChain, DAG.
getConstant(Intrinsic::ppc_vsx_stxvp, dl, MVT::i32),
12434 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12435 MachineMemOperand *NewMMO =
12442 Ops[2] = Values[Idx];
12444 MVT::v256i1, NewMMO);
12460 EVT StoreVT =
Value.getValueType();
12462 if (StoreVT == MVT::v1024i1 || StoreVT == MVT::v2048i1)
12463 return LowerDMFVectorStore(
Op, DAG);
12465 if (StoreVT != MVT::v256i1 && StoreVT != MVT::v512i1)
12469 assert((StoreVT != MVT::v512i1 || Subtarget.hasMMA()) &&
12470 "Type unsupported without MMA");
12471 assert((StoreVT != MVT::v256i1 || Subtarget.pairedVectorMemops()) &&
12472 "Type unsupported without paired vector support");
12476 if (StoreVT == MVT::v256i1 && Subtarget.isISAFuture() &&
12484 unsigned NumVecs = 2;
12485 if (StoreVT == MVT::v512i1) {
12486 if (Subtarget.isISAFuture()) {
12487 EVT ReturnTypes[] = {MVT::v256i1, MVT::v256i1};
12489 PPC::DMXXEXTFDMR512, dl, ReturnTypes,
Op.getOperand(1));
12492 Value2 =
SDValue(ExtNode, 1);
12497 for (
unsigned Idx = 0; Idx < NumVecs; ++Idx) {
12498 unsigned VecNum = Subtarget.isLittleEndian() ? NumVecs - 1 - Idx : Idx;
12500 if (Subtarget.isISAFuture()) {
12501 VecNum = Subtarget.isLittleEndian() ? 1 - (Idx % 2) : (Idx % 2);
12502 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
12503 Idx > 1 ? Value2 :
Value,
12506 Elt = DAG.
getNode(PPCISD::EXTRACT_VSX_REG, dl, MVT::v16i8,
Value,
12510 DAG.
getStore(StoreChain, dl, Elt, BasePtr,
12524 if (
Op.getValueType() == MVT::v4i32) {
12541 LHS,
RHS, DAG, dl, MVT::v4i32);
12544 LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32);
12549 }
else if (
Op.getValueType() == MVT::v16i8) {
12551 bool isLittleEndian = Subtarget.isLittleEndian();
12555 LHS,
RHS, DAG, dl, MVT::v8i16);
12560 LHS,
RHS, DAG, dl, MVT::v8i16);
12568 for (
unsigned i = 0; i != 8; ++i) {
12569 if (isLittleEndian) {
12571 Ops[i*2+1] = 2*i+16;
12574 Ops[i*2+1] = 2*i+1+16;
12577 if (isLittleEndian)
12587 bool IsStrict =
Op->isStrictFPOpcode();
12588 if (
Op.getOperand(IsStrict ? 1 : 0).getValueType() == MVT::f128 &&
12589 !Subtarget.hasP9Vector())
12599 "Should only be called for ISD::FP_EXTEND");
12603 if (
Op.getValueType() != MVT::v2f64 ||
12604 Op.getOperand(0).getValueType() != MVT::v2f32)
12616 "Node should have 2 operands with second one being a constant!");
12628 int DWord = Idx >> 1;
12631 if (Subtarget.isLittleEndian())
12634 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64,
12648 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12650 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12651 LD->getMemoryVT(),
LD->getMemOperand());
12656 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewOp,
12661 SDValue LoadOps[] = {
LD->getChain(),
LD->getBasePtr()};
12663 PPCISD::LD_VSX_LH, dl, DAG.
getVTList(MVT::v4f32, MVT::Other), LoadOps,
12664 LD->getMemoryVT(),
LD->getMemOperand());
12665 return DAG.
getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewLd,
12676 if (STI.useCRBits())
12693 PPCISD::ADDE,
DL, DAG.
getVTList(SumType, MVT::i32), Zero, Zero, Flag);
12694 if (STI.useCRBits())
12702 SDNode *
N =
Op.getNode();
12703 EVT VT =
N->getValueType(0);
12704 EVT CarryType =
N->getValueType(1);
12705 unsigned Opc =
N->getOpcode();
12707 Opc = IsAdd ? PPCISD::ADDC : PPCISD::SUBC;
12709 N->getOperand(0),
N->getOperand(1));
12721 SDNode *
N =
Op.getNode();
12722 unsigned Opc =
N->getOpcode();
12723 EVT VT =
N->getValueType(0);
12724 EVT CarryType =
N->getValueType(1);
12725 SDValue CarryOp =
N->getOperand(2);
12727 Opc = IsAdd ? PPCISD::ADDE : PPCISD::SUBE;
12733 Op.getOperand(0),
Op.getOperand(1), CarryOp);
12747 EVT VT =
Op.getNode()->getValueType(0);
12773 EVT VT =
Op.getNode()->getValueType(0);
12802 EVT OpVT =
A.getValueType();
12803 EVT ResVT =
Op.getValueType();
12809 SDVTList VTs = DAG.
getVTList(OpVT, MVT::i32);
12827 switch (
Op.getOpcode()) {
12848 return LowerSSUBO(
Op, DAG);
12850 return LowerSADDO(
Op, DAG);
12862 return LowerGET_DYNAMIC_AREA_OFFSET(
Op, DAG);
12883 return LowerSET_ROUNDING(
Op, DAG);
12890 case ISD::FSHL:
return LowerFunnelShift(
Op, DAG);
12891 case ISD::FSHR:
return LowerFunnelShift(
Op, DAG);
12903 return LowerFP_ROUND(
Op, DAG);
12917 return LowerINTRINSIC_VOID(
Op, DAG);
12919 return LowerBSWAP(
Op, DAG);
12921 return LowerATOMIC_CMP_SWAP(
Op, DAG);
12923 return LowerATOMIC_LOAD_STORE(
Op, DAG);
12925 return LowerIS_FPCLASS(
Op, DAG);
12928 return LowerADDSUBO(
Op, DAG);
12931 return LowerADDSUBO_CARRY(
Op, DAG);
12933 return LowerUCMP(
Op, DAG);
12939 if (
Op->getFlags().hasNoFPExcept())
12943 return LowerVP_LOAD(
Op, DAG);
12944 case ISD::VP_STORE:
12945 return LowerVP_STORE(
Op, DAG);
12947 return LowerPartialReduce(
Op, DAG);
12955 switch (
N->getOpcode()) {
12957 llvm_unreachable(
"Do not know how to custom type legalize this operation!");
12974 if (
N->getConstantOperandVal(1) != Intrinsic::loop_decrement)
12977 assert(
N->getValueType(0) == MVT::i1 &&
12978 "Unexpected result type for CTR decrement intrinsic");
12980 N->getValueType(0));
12990 switch (
N->getConstantOperandVal(0)) {
12991 case Intrinsic::ppc_pack_longdouble:
12993 N->getOperand(2),
N->getOperand(1)));
12995 case Intrinsic::ppc_maxfe:
12996 case Intrinsic::ppc_minfe:
12997 case Intrinsic::ppc_fnmsub:
12998 case Intrinsic::ppc_convert_f128_to_ppcf128:
13005 if (!Subtarget.isSVR4ABI() || Subtarget.isPPC64())
13008 EVT VT =
N->getValueType(0);
13010 if (VT == MVT::i64) {
13023 if (
N->getOperand(
N->isStrictFPOpcode() ? 1 : 0).getValueType() ==
13027 Results.push_back(LoweredValue);
13028 if (
N->isStrictFPOpcode())
13033 if (!
N->getValueType(0).isVector())
13066 return Builder.CreateIntrinsic(Id, {});
13072 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
13074 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
13075 "Only 8/16/32/64-bit atomic loads supported");
13081 IntID = Intrinsic::ppc_lbarx;
13082 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13085 IntID = Intrinsic::ppc_lharx;
13086 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13089 IntID = Intrinsic::ppc_lwarx;
13092 IntID = Intrinsic::ppc_ldarx;
13096 Builder.CreateIntrinsic(IntID, Addr,
nullptr,
"larx");
13098 return Builder.CreateTruncOrBitCast(
Call, ValueTy);
13109 assert((SZ == 8 || SZ == 16 || SZ == 32 || SZ == 64) &&
13110 "Only 8/16/32/64-bit atomic loads supported");
13116 IntID = Intrinsic::ppc_stbcx;
13117 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13120 IntID = Intrinsic::ppc_sthcx;
13121 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
13124 IntID = Intrinsic::ppc_stwcx;
13127 IntID = Intrinsic::ppc_stdcx;
13131 if (SZ == 8 || SZ == 16)
13132 Val = Builder.CreateZExt(Val, Builder.getInt32Ty());
13134 Value *
Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
13136 return Builder.CreateXor(
Call, Builder.getInt32(1));
13159 return Builder.CreateIntrinsic(Intrinsic::ppc_cfence, {Inst->
getType()},
13169 unsigned BinOpcode,
13170 unsigned CmpOpcode,
13171 unsigned CmpPred)
const {
13176 unsigned AtomicSize =
MI.getOperand(3).getImm();
13178 auto LoadMnemonic = PPC::LDARX;
13179 auto StoreMnemonic = PPC::STDCX;
13180 switch (AtomicSize) {
13184 LoadMnemonic = PPC::LBARX;
13185 StoreMnemonic = PPC::STBCX;
13186 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13189 LoadMnemonic = PPC::LHARX;
13190 StoreMnemonic = PPC::STHCX;
13191 assert(Subtarget.hasPartwordAtomics() &&
"Call this only with size >=4");
13194 LoadMnemonic = PPC::LWARX;
13195 StoreMnemonic = PPC::STWCX;
13198 LoadMnemonic = PPC::LDARX;
13199 StoreMnemonic = PPC::STDCX;
13207 if (CmpOpcode == PPC::CMPW && (AtomicSize == 1 || AtomicSize == 2))
13218 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13220 F->insert(It, loopMBB);
13222 F->insert(It, loop2MBB);
13223 F->insert(It, exitMBB);
13229 Register TmpReg = (!BinOpcode) ? incr :
13230 RegInfo.createVirtualRegister( AtomicSize == 8 ? &PPC::G8RCRegClass
13231 : &PPC::GPRCRegClass);
13256 BuildMI(BB, dl,
TII->get(LoadMnemonic), dest)
13261 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13263 if (CmpOpcode == PPC::CMPW && AtomicSize < 4) {
13264 Register ExtReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13265 BuildMI(BB, dl,
TII->get(AtomicSize == 1 ? PPC::EXTSB : PPC::EXTSH),
13295 switch(
MI.getOpcode()) {
13299 return TII->isSignExtended(
MI.getOperand(1).getReg(),
13300 &
MI.getMF()->getRegInfo());
13324 case PPC::EXTSB8_32_64:
13325 case PPC::EXTSB8_rec:
13326 case PPC::EXTSB_rec:
13329 case PPC::EXTSH8_32_64:
13330 case PPC::EXTSH8_rec:
13331 case PPC::EXTSH_rec:
13333 case PPC::EXTSWSLI:
13334 case PPC::EXTSWSLI_32_64:
13335 case PPC::EXTSWSLI_32_64_rec:
13336 case PPC::EXTSWSLI_rec:
13337 case PPC::EXTSW_32:
13338 case PPC::EXTSW_32_64:
13339 case PPC::EXTSW_32_64_rec:
13340 case PPC::EXTSW_rec:
13343 case PPC::SRAWI_rec:
13344 case PPC::SRAW_rec:
13354 unsigned OpIdx,
bool IsByte,
13359 bool IsSignExtended =
13362 if (!IsSignExtended) {
13363 Register ValueReg =
RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
13365 TII->get(IsByte ? PPC::EXTSB : PPC::EXTSH), ValueReg)
13367 MI.getOperand(
OpIdx).setReg(ValueReg);
13373 unsigned CmpOpcode,
unsigned CmpPred)
const {
13377 assert(!Subtarget.hasPartwordAtomics() &&
13378 "Assumes that part-word atomics are not available");
13386 const bool is8bit =
MI.getOperand(3).getImm() == 1;
13387 if (CmpOpcode == PPC::CMPW)
13395 bool is64bit = Subtarget.isPPC64();
13396 bool isLittleEndian = Subtarget.isLittleEndian();
13397 unsigned ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
13408 CmpOpcode ?
F->CreateMachineBasicBlock(LLVM_BB) :
nullptr;
13410 F->insert(It, loopMBB);
13412 F->insert(It, loop2MBB);
13413 F->insert(It, exitMBB);
13419 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13422 Register PtrReg = RegInfo.createVirtualRegister(RC);
13423 Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
13425 isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
13426 Register Incr2Reg = RegInfo.createVirtualRegister(GPRC);
13427 Register MaskReg = RegInfo.createVirtualRegister(GPRC);
13428 Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
13429 Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
13430 Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
13431 Register Tmp3Reg = RegInfo.createVirtualRegister(GPRC);
13432 Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
13433 Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
13434 Register SrwDestReg = RegInfo.createVirtualRegister(GPRC);
13437 (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(GPRC);
13464 if (ptrA != ZeroReg) {
13465 Ptr1Reg = RegInfo.createVirtualRegister(RC);
13466 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
13474 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
13475 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
13478 .
addImm(is8bit ? 28 : 27);
13479 if (!isLittleEndian)
13480 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
13482 .
addImm(is8bit ? 24 : 16);
13484 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
13489 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
13499 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
13503 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
13508 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
13512 BuildMI(BB, dl,
TII->get(BinOpcode), TmpReg)
13515 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
13522 Register SReg = RegInfo.createVirtualRegister(GPRC);
13523 Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
13527 unsigned ValueReg = SReg;
13528 unsigned CmpReg = Incr2Reg;
13529 if (CmpOpcode == PPC::CMPW) {
13530 ValueReg = RegInfo.createVirtualRegister(GPRC);
13531 BuildMI(BB, dl,
TII->get(PPC::SRW), ValueReg)
13534 Register ValueSReg = RegInfo.createVirtualRegister(GPRC);
13535 BuildMI(BB, dl,
TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueSReg)
13537 ValueReg = ValueSReg;
13569 .
addImm(is8bit ? 24 : 16)
13590 Register DstReg =
MI.getOperand(0).getReg();
13592 assert(
TRI->isTypeLegalForClass(*RC, MVT::i32) &&
"Invalid destination!");
13597 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13598 "Invalid Pointer Size!");
13647 Register BufReg =
MI.getOperand(1).getReg();
13649 if (Subtarget.is64BitELFABI()) {
13662 BaseReg = Subtarget.isPPC64() ? PPC::X1 : PPC::R1;
13664 BaseReg = Subtarget.isPPC64() ? PPC::BP8 : PPC::BP;
13667 TII->get(Subtarget.isPPC64() ? PPC::STD : PPC::STW))
13690 TII->get(Subtarget.isPPC64() ? PPC::MFLR8 : PPC::MFLR), LabelReg);
13693 if (Subtarget.isPPC64()) {
13711 TII->get(PPC::PHI), DstReg)
13715 MI.eraseFromParent();
13729 assert((PVT == MVT::i64 || PVT == MVT::i32) &&
13730 "Invalid Pointer Size!");
13733 (PVT == MVT::i64) ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
13736 unsigned FP = (PVT == MVT::i64) ? PPC::X31 : PPC::R31;
13737 unsigned SP = (PVT == MVT::i64) ? PPC::X1 : PPC::R1;
13751 Register BufReg =
MI.getOperand(0).getReg();
13756 if (PVT == MVT::i64) {
13768 if (PVT == MVT::i64) {
13780 if (PVT == MVT::i64) {
13792 if (PVT == MVT::i64) {
13804 if (PVT == MVT::i64 && Subtarget.isSVR4ABI()) {
13814 TII->get(PVT == MVT::i64 ? PPC::MTCTR8 : PPC::MTCTR)).
addReg(Tmp);
13817 MI.eraseFromParent();
13833 "Unexpected stack alignment");
13837 unsigned StackProbeSize =
13840 StackProbeSize &= ~(StackAlign - 1);
13841 return StackProbeSize ? StackProbeSize : StackAlign;
13853 const bool isPPC64 = Subtarget.isPPC64();
13885 MF->
insert(MBBIter, TestMBB);
13886 MF->
insert(MBBIter, BlockMBB);
13887 MF->
insert(MBBIter, TailMBB);
13892 Register DstReg =
MI.getOperand(0).getReg();
13893 Register NegSizeReg =
MI.getOperand(1).getReg();
13905 isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_64 : PPC::PREPARE_PROBED_ALLOCA_32;
13911 ProbeOpc = isPPC64 ? PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_64
13912 : PPC::PREPARE_PROBED_ALLOCA_NEGSIZE_SAME_REG_32;
13914 .
addDef(ActualNegSizeReg)
13916 .
add(
MI.getOperand(2))
13917 .
add(
MI.getOperand(3));
13923 .
addReg(ActualNegSizeReg);
13926 int64_t NegProbeSize = -(int64_t)ProbeSize;
13932 .
addImm(NegProbeSize >> 16);
13936 .
addImm(NegProbeSize & 0xFFFF);
13945 .
addReg(ActualNegSizeReg)
13954 .
addReg(ActualNegSizeReg);
13964 BuildMI(TestMBB,
DL,
TII->get(isPPC64 ? PPC::CMPD : PPC::CMPW), CmpResult)
13991 TII->get(isPPC64 ? PPC::DYNAREAOFFSET8 : PPC::DYNAREAOFFSET),
13992 MaxCallFrameSizeReg)
13993 .
add(
MI.getOperand(2))
13994 .
add(
MI.getOperand(3));
13995 BuildMI(TailMBB,
DL,
TII->get(isPPC64 ? PPC::ADD8 : PPC::ADD4), DstReg)
13997 .
addReg(MaxCallFrameSizeReg);
14003 MBB->addSuccessor(TestMBB);
14006 MI.eraseFromParent();
14008 ++NumDynamicAllocaProbed;
14016static bool IsSelect(
unsigned Opcode,
bool CheckOnlyCC =
false) {
14019 case PPC::SELECT_CC_I4:
14020 case PPC::SELECT_CC_I8:
14021 case PPC::SELECT_CC_F4:
14022 case PPC::SELECT_CC_F8:
14023 case PPC::SELECT_CC_F16:
14024 case PPC::SELECT_CC_VRRC:
14025 case PPC::SELECT_CC_VSFRC:
14026 case PPC::SELECT_CC_VSSRC:
14027 case PPC::SELECT_CC_VSRC:
14028 case PPC::SELECT_CC_SPE4:
14029 case PPC::SELECT_CC_SPE:
14032 case PPC::SELECT_I4:
14033 case PPC::SELECT_I8:
14034 case PPC::SELECT_F4:
14035 case PPC::SELECT_F8:
14036 case PPC::SELECT_F16:
14037 case PPC::SELECT_SPE:
14038 case PPC::SELECT_SPE4:
14039 case PPC::SELECT_VRRC:
14040 case PPC::SELECT_VSFRC:
14041 case PPC::SELECT_VSSRC:
14042 case PPC::SELECT_VSRC:
14043 return !CheckOnlyCC;
14059 assert(
IsSelect(
MI.getOpcode()) &&
"Instruction must be a SELECT variant");
14062 if (Subtarget.hasISEL() &&
14063 (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
14064 MI.getOpcode() == PPC::SELECT_CC_I8 ||
14065 MI.getOpcode() == PPC::SELECT_I4 ||
MI.getOpcode() == PPC::SELECT_I8)) {
14067 if (
MI.getOpcode() == PPC::SELECT_CC_I4 ||
14068 MI.getOpcode() == PPC::SELECT_CC_I8)
14069 Cond.push_back(
MI.getOperand(4));
14072 Cond.push_back(
MI.getOperand(1));
14075 TII->insertSelect(*BB,
MI, dl,
MI.getOperand(0).getReg(),
Cond,
14076 MI.getOperand(2).getReg(),
MI.getOperand(3).getReg());
14077 MI.eraseFromParent();
14090 F->insert(It, copy0MBB);
14091 F->insert(It, sinkMBB);
14099 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
14115 .
addImm(
MI.getOperand(4).getImm())
14116 .
addReg(
MI.getOperand(1).getReg())
14120 .
addReg(
MI.getOperand(1).getReg())
14130 .
addReg(
MI.getOperand(3).getReg())
14132 .
addReg(
MI.getOperand(2).getReg())
14134 MI.eraseFromParent();
14149 loop1MBB =
F->CreateMachineBasicBlock(LLVM_BB);
14150 loop2MBB =
F->CreateMachineBasicBlock(LLVM_BB);
14151 exitMBB =
F->CreateMachineBasicBlock(LLVM_BB);
14152 F->insert(It, loop1MBB);
14153 F->insert(It, loop2MBB);
14154 F->insert(It, exitMBB);
14189 bool is64bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
14191 unsigned LoadMnemonic = PPC::LDARX;
14192 unsigned StoreMnemonic = PPC::STDCX;
14193 switch (
MI.getOpcode()) {
14196 case PPC::ATOMIC_CMP_SWAP_I8:
14197 LoadMnemonic = PPC::LBARX;
14198 StoreMnemonic = PPC::STBCX;
14199 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14201 case PPC::ATOMIC_CMP_SWAP_I16:
14202 LoadMnemonic = PPC::LHARX;
14203 StoreMnemonic = PPC::STHCX;
14204 assert(Subtarget.hasPartwordAtomics() &&
"No support partword atomics.");
14206 case PPC::ATOMIC_CMP_SWAP_I32:
14207 LoadMnemonic = PPC::LWARX;
14208 StoreMnemonic = PPC::STWCX;
14210 case PPC::ATOMIC_CMP_SWAP_I64:
14211 LoadMnemonic = PPC::LDARX;
14212 StoreMnemonic = PPC::STDCX;
14220 Register oldval =
MI.getOperand(3).getReg();
14221 Register newval =
MI.getOperand(4).getReg();
14235 BuildMI(BB, dl,
TII->get(is64bit ? PPC::CMPD : PPC::CMPW), CrReg)
14303 bool is64bit = Subtarget.isPPC64();
14305 bool is8bit =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8;
14310 Register oldval =
MI.getOperand(3).getReg();
14311 Register newval =
MI.getOperand(4).getReg();
14319 is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
14324 return RegInfo.createVirtualRegister(RC);
14328 Register Shift1Reg = createVReg(GPRC);
14329 Register ShiftReg = isLittleEndian ? Shift1Reg : createVReg(GPRC);
14330 Register NewVal2Reg = createVReg(GPRC);
14331 Register NewVal3Reg = createVReg(GPRC);
14332 Register OldVal2Reg = createVReg(GPRC);
14333 Register OldVal3Reg = createVReg(GPRC);
14334 Register MaskReg = createVReg(GPRC);
14335 Register Mask2Reg = createVReg(GPRC);
14336 Register Mask3Reg = createVReg(GPRC);
14337 Register Tmp2Reg = createVReg(GPRC);
14338 Register Tmp4Reg = createVReg(GPRC);
14339 Register TmpDestReg = createVReg(GPRC);
14340 Register TmpReg = createVReg(GPRC);
14341 Register ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
14342 Register CrReg = createVReg(&PPC::CRRCRegClass);
14346 if (ptrA != ZeroReg) {
14347 Ptr1Reg = createVReg(RC);
14348 BuildMI(BB, dl,
TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
14355 BuildMI(BB, dl,
TII->get(PPC::RLWINM), Shift1Reg)
14356 .
addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
14359 .
addImm(is8bit ? 28 : 27);
14360 if (!isLittleEndian)
14361 BuildMI(BB, dl,
TII->get(PPC::XORI), ShiftReg)
14363 .
addImm(is8bit ? 24 : 16);
14365 BuildMI(BB, dl,
TII->get(PPC::RLDICR), PtrReg)
14370 BuildMI(BB, dl,
TII->get(PPC::RLWINM), PtrReg)
14377 BuildMI(BB, dl,
TII->get(PPC::SLW), NewVal2Reg)
14380 BuildMI(BB, dl,
TII->get(PPC::SLW), OldVal2Reg)
14387 BuildMI(BB, dl,
TII->get(PPC::ORI), Mask2Reg)
14391 BuildMI(BB, dl,
TII->get(PPC::SLW), MaskReg)
14394 BuildMI(BB, dl,
TII->get(PPC::AND), NewVal3Reg)
14397 BuildMI(BB, dl,
TII->get(PPC::AND), OldVal3Reg)
14407 BuildMI(BB, dl,
TII->get(PPC::LWARX), TmpDestReg)
14428 BuildMI(BB, dl,
TII->get(PPC::ANDC), Tmp2Reg)
14473 switch (
MI.getOpcode()) {
14474 case TargetOpcode::STACKMAP:
14476 case TargetOpcode::PATCHPOINT:
14482 if (Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls())
14486 case PPC::EH_SjLj_SetJmp32:
14487 case PPC::EH_SjLj_SetJmp64:
14490 case PPC::EH_SjLj_LongJmp32:
14491 case PPC::EH_SjLj_LongJmp64:
14494 case PPC::ReadTB: {
14510 F->insert(It, readMBB);
14511 F->insert(It, sinkMBB);
14522 Register ReadAgainReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
14530 Register CmpReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14532 BuildMI(BB, dl,
TII->get(PPC::CMPW), CmpReg)
14544 case PPC::ATOMIC_LOAD_ADD_NOWP:
14547 case PPC::ATOMIC_LOAD_ADD:
14550 case PPC::ATOMIC_LOAD_ADD_I64:
14553 case PPC::ATOMIC_LOAD_AND_NOWP:
14556 case PPC::ATOMIC_LOAD_AND:
14559 case PPC::ATOMIC_LOAD_AND_I64:
14562 case PPC::ATOMIC_LOAD_OR_NOWP:
14565 case PPC::ATOMIC_LOAD_OR:
14568 case PPC::ATOMIC_LOAD_OR_I64:
14571 case PPC::ATOMIC_LOAD_XOR_NOWP:
14574 case PPC::ATOMIC_LOAD_XOR:
14577 case PPC::ATOMIC_LOAD_XOR_I64:
14580 case PPC::ATOMIC_LOAD_NAND_NOWP:
14583 case PPC::ATOMIC_LOAD_NAND:
14586 case PPC::ATOMIC_LOAD_NAND_I64:
14589 case PPC::ATOMIC_LOAD_SUB_NOWP:
14592 case PPC::ATOMIC_LOAD_SUB:
14595 case PPC::ATOMIC_LOAD_SUB_I64:
14598 case PPC::ATOMIC_LOAD_MIN_NOWP:
14601 case PPC::ATOMIC_LOAD_MIN:
14604 case PPC::ATOMIC_LOAD_MIN_I64:
14607 case PPC::ATOMIC_LOAD_MAX_NOWP:
14610 case PPC::ATOMIC_LOAD_MAX:
14613 case PPC::ATOMIC_LOAD_MAX_I64:
14616 case PPC::ATOMIC_LOAD_UMIN_NOWP:
14619 case PPC::ATOMIC_LOAD_UMIN:
14622 case PPC::ATOMIC_LOAD_UMIN_I64:
14625 case PPC::ATOMIC_LOAD_UMAX_NOWP:
14628 case PPC::ATOMIC_LOAD_UMAX:
14631 case PPC::ATOMIC_LOAD_UMAX_I64:
14634 case PPC::ATOMIC_SWAP_NOWP:
14637 case PPC::ATOMIC_SWAP:
14638 case PPC::ATOMIC_SWAP_I64:
14641 case PPC::ATOMIC_CMP_SWAP_I32:
14642 case PPC::ATOMIC_CMP_SWAP_I64:
14643 case PPC::ATOMIC_CMP_SWAP_I8:
14644 case PPC::ATOMIC_CMP_SWAP_I16: {
14646 bool useHardware =
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
14647 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64 ||
14648 (Subtarget.hasPartwordAtomics() &&
14649 (
MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 ||
14650 MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16));
14658 case PPC::FADDrtz: {
14668 Register MFFSReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14683 auto MIB =
BuildMI(*BB,
MI, dl,
TII->get(PPC::FADD), Dest)
14693 case PPC::ANDI_rec_1_EQ_BIT:
14694 case PPC::ANDI_rec_1_GT_BIT:
14695 case PPC::ANDI_rec_1_EQ_BIT8:
14696 case PPC::ANDI_rec_1_GT_BIT8: {
14697 unsigned Opcode = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
14698 MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8)
14701 bool IsEQ = (
MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
14702 MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8);
14705 Register Dest = RegInfo.createVirtualRegister(
14706 Opcode == PPC::ANDI_rec ? &PPC::GPRCRegClass : &PPC::G8RCRegClass);
14710 .
addReg(
MI.getOperand(1).getReg())
14713 MI.getOperand(0).getReg())
14714 .
addReg(IsEQ ? PPC::CR0EQ : PPC::CR0GT);
14717 case PPC::TCHECK_RET: {
14720 Register CRReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
14723 MI.getOperand(0).getReg())
14727 case PPC::TBEGIN_RET: {
14729 unsigned Imm =
MI.getOperand(1).getImm();
14732 MI.getOperand(0).getReg())
14736 case PPC::SETRNDi: {
14738 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14742 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14744 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14755 unsigned Mode =
MI.getOperand(1).getImm();
14756 BuildMI(*BB,
MI, dl,
TII->get((Mode & 1) ? PPC::MTFSB1 : PPC::MTFSB0))
14760 BuildMI(*BB,
MI, dl,
TII->get((Mode & 2) ? PPC::MTFSB1 : PPC::MTFSB0))
14765 case PPC::SETRND: {
14773 auto copyRegFromG8RCOrF8RC = [&] (
unsigned DestReg,
unsigned SrcReg) {
14774 if (Subtarget.hasDirectMove()) {
14775 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::COPY), DestReg)
14779 unsigned StoreOp = PPC::STD, LoadOp = PPC::LFD;
14782 if (RC == &PPC::F8RCRegClass) {
14784 assert((RegInfo.getRegClass(DestReg) == &PPC::G8RCRegClass) &&
14785 "Unsupported RegClass.");
14787 StoreOp = PPC::STFD;
14791 assert((RegInfo.getRegClass(SrcReg) == &PPC::G8RCRegClass) &&
14792 (RegInfo.getRegClass(DestReg) == &PPC::F8RCRegClass) &&
14793 "Unsupported RegClass.");
14826 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14829 BuildMI(*BB,
MI, dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14841 Register OldFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14843 copyRegFromG8RCOrF8RC(OldFPSCRTmpReg, OldFPSCRReg);
14845 Register ImDefReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14846 Register ExtSrcReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14851 BuildMI(*BB,
MI, dl,
TII->get(TargetOpcode::IMPLICIT_DEF), ImDefReg);
14852 BuildMI(*BB,
MI, dl,
TII->get(PPC::INSERT_SUBREG), ExtSrcReg)
14857 Register NewFPSCRTmpReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
14858 BuildMI(*BB,
MI, dl,
TII->get(PPC::RLDIMI), NewFPSCRTmpReg)
14864 Register NewFPSCRReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass);
14865 copyRegFromG8RCOrF8RC(NewFPSCRReg, NewFPSCRTmpReg);
14876 case PPC::SETFLM: {
14880 Register OldFPSCRReg =
MI.getOperand(0).getReg();
14882 BuildMI(*BB,
MI, Dl,
TII->get(TargetOpcode::IMPLICIT_DEF), OldFPSCRReg);
14884 BuildMI(*BB,
MI, Dl,
TII->get(PPC::MFFS), OldFPSCRReg);
14887 Register NewFPSCRReg =
MI.getOperand(1).getReg();
14895 case PPC::PROBED_ALLOCA_32:
14896 case PPC::PROBED_ALLOCA_64:
14899 case PPC::SPLIT_QUADWORD: {
14906 .
addUse(Src, {}, PPC::sub_gp8_x1);
14909 .
addUse(Src, {}, PPC::sub_gp8_x0);
14912 case PPC::LQX_PSEUDO:
14913 case PPC::STQX_PSEUDO: {
14919 F->getRegInfo().createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass);
14925 MI.getOpcode() == PPC::LQX_PSEUDO ?
TII->get(PPC::LQ)
14926 :
TII->get(PPC::STQ))
14936 MI.eraseFromParent();
14949 int RefinementSteps = Subtarget.hasRecipPrec() ? 1 : 3;
14952 return RefinementSteps;
14959 EVT VT =
Op.getValueType();
14962 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX())))
14986PPCTargetLowering::getSqrtResultForDenormInput(
SDValue Op,
14989 EVT VT =
Op.getValueType();
14990 if (VT != MVT::f64 &&
14991 ((VT != MVT::v2f64 && VT != MVT::v4f32) || !Subtarget.hasVSX()))
14994 return DAG.
getNode(PPCISD::FSQRT, SDLoc(
Op), VT,
Op);
14998 int Enabled,
int &RefinementSteps,
14999 bool &UseOneConstNR,
15000 bool Reciprocal)
const {
15002 if ((VT == MVT::f32 && Subtarget.hasFRSQRTES()) ||
15003 (VT == MVT::f64 && Subtarget.hasFRSQRTE()) ||
15004 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
15005 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
15011 UseOneConstNR = !Subtarget.needsTwoConstNR();
15012 return DAG.
getNode(PPCISD::FRSQRTE, SDLoc(Operand), VT, Operand);
15019 int &RefinementSteps)
const {
15021 if ((VT == MVT::f32 && Subtarget.hasFRES()) ||
15022 (VT == MVT::f64 && Subtarget.hasFRE()) ||
15023 (VT == MVT::v4f32 && Subtarget.hasAltivec()) ||
15024 (VT == MVT::v2f64 && Subtarget.hasVSX())) {
15027 return DAG.
getNode(PPCISD::FRE, SDLoc(Operand), VT, Operand);
15043 switch (Subtarget.getCPUDirective()) {
15070 unsigned Bytes,
int Dist,
15084 if (FS != BFS || FS != (
int)Bytes)
return false;
15089 int64_t Offset1 = 0, Offset2 = 0;
15092 if (Base1 == Base2 && Offset1 == (Offset2 + Dist * Bytes))
15102 if (isGA1 && isGA2 && GV1 == GV2)
15103 return Offset1 == (Offset2 + Dist*Bytes);
15110 unsigned Bytes,
int Dist,
15113 EVT VT = LS->getMemoryVT();
15120 switch (
N->getConstantOperandVal(1)) {
15121 default:
return false;
15122 case Intrinsic::ppc_altivec_lvx:
15123 case Intrinsic::ppc_altivec_lvxl:
15124 case Intrinsic::ppc_vsx_lxvw4x:
15125 case Intrinsic::ppc_vsx_lxvw4x_be:
15128 case Intrinsic::ppc_vsx_lxvd2x:
15129 case Intrinsic::ppc_vsx_lxvd2x_be:
15132 case Intrinsic::ppc_altivec_lvebx:
15135 case Intrinsic::ppc_altivec_lvehx:
15138 case Intrinsic::ppc_altivec_lvewx:
15148 switch (
N->getConstantOperandVal(1)) {
15149 default:
return false;
15150 case Intrinsic::ppc_altivec_stvx:
15151 case Intrinsic::ppc_altivec_stvxl:
15152 case Intrinsic::ppc_vsx_stxvw4x:
15155 case Intrinsic::ppc_vsx_stxvd2x:
15158 case Intrinsic::ppc_vsx_stxvw4x_be:
15161 case Intrinsic::ppc_vsx_stxvd2x_be:
15164 case Intrinsic::ppc_altivec_stvebx:
15167 case Intrinsic::ppc_altivec_stvehx:
15170 case Intrinsic::ppc_altivec_stvewx:
15187 SDValue Chain = LD->getChain();
15188 EVT VT = LD->getMemoryVT();
15197 while (!Queue.empty()) {
15198 SDNode *ChainNext = Queue.pop_back_val();
15199 if (!Visited.
insert(ChainNext).second)
15206 if (!Visited.
count(ChainLD->getChain().getNode()))
15207 Queue.push_back(ChainLD->getChain().getNode());
15209 for (
const SDUse &O : ChainNext->
ops())
15210 if (!Visited.
count(O.getNode()))
15211 Queue.push_back(O.getNode());
15213 LoadRoots.
insert(ChainNext);
15224 for (
SDNode *
I : LoadRoots) {
15225 Queue.push_back(
I);
15227 while (!Queue.empty()) {
15228 SDNode *LoadRoot = Queue.pop_back_val();
15229 if (!Visited.
insert(LoadRoot).second)
15241 Queue.push_back(U);
15274 auto Final = Shifted;
15285 DAGCombinerInfo &DCI)
const {
15288 SelectionDAG &DAG = DCI.DAG;
15293 if (!DCI.isAfterLegalizeDAG())
15298 for (
const SDNode *U :
N->users())
15303 auto OpSize =
N->getOperand(0).getValueSizeInBits();
15307 if (OpSize <
Size) {
15325 DAGCombinerInfo &DCI)
const {
15326 SelectionDAG &DAG = DCI.DAG;
15329 assert(Subtarget.useCRBits() &&
"Expecting to be tracking CR bits");
15340 N->getValueType(0) != MVT::i1)
15343 if (
N->getOperand(0).getValueType() != MVT::i32 &&
15344 N->getOperand(0).getValueType() != MVT::i64)
15354 unsigned OpBits =
N->getOperand(0).getValueSizeInBits();
15365 return (
N->getOpcode() ==
ISD::SETCC ? ConvertSETCCToSubtract(
N, DCI)
15388 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15389 N->getOperand(0).getOpcode() !=
ISD::OR &&
15390 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15400 N->getOperand(1).getOpcode() !=
ISD::AND &&
15401 N->getOperand(1).getOpcode() !=
ISD::OR &&
15402 N->getOperand(1).getOpcode() !=
ISD::XOR &&
15413 SmallPtrSet<SDNode *, 16> Visited;
15415 for (
unsigned i = 0; i < 2; ++i) {
15419 N->getOperand(i).getOperand(0).getValueType() == MVT::i1) ||
15431 while (!BinOps.
empty()) {
15439 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15473 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15477 for (
const SDNode *User : Inputs[i].
getNode()->
users()) {
15478 if (User !=
N && !Visited.
count(User))
15487 if (
User->getOperand(0) == Inputs[i])
15490 if (
User->getOperand(0) == Inputs[i] ||
15491 User->getOperand(1) == Inputs[i])
15497 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15498 for (
const SDNode *User : PromOps[i].
getNode()->
users()) {
15499 if (User !=
N && !Visited.
count(User))
15508 if (
User->getOperand(0) == PromOps[i])
15511 if (
User->getOperand(0) == PromOps[i] ||
15512 User->getOperand(1) == PromOps[i])
15519 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15528 std::list<HandleSDNode> PromOpHandles;
15529 for (
auto &PromOp : PromOps)
15530 PromOpHandles.emplace_back(PromOp);
15537 while (!PromOpHandles.empty()) {
15538 SDValue PromOp = PromOpHandles.back().getValue();
15539 PromOpHandles.pop_back();
15548 PromOpHandles.emplace_front(PromOp);
15562 default:
C = 0;
break;
15575 PromOpHandles.emplace_front(PromOp);
15582 for (
unsigned i = 0; i < 2; ++i)
15592 return N->getOperand(0);
15600 DAGCombinerInfo &DCI)
const {
15601 SelectionDAG &DAG = DCI.DAG;
15618 if (
N->getValueType(0) != MVT::i32 &&
15619 N->getValueType(0) != MVT::i64)
15622 if (!((
N->getOperand(0).getValueType() == MVT::i1 && Subtarget.useCRBits()) ||
15623 (
N->getOperand(0).getValueType() == MVT::i32 && Subtarget.isPPC64())))
15626 if (
N->getOperand(0).getOpcode() !=
ISD::AND &&
15627 N->getOperand(0).getOpcode() !=
ISD::OR &&
15628 N->getOperand(0).getOpcode() !=
ISD::XOR &&
15635 SmallPtrSet<SDNode *, 16> Visited;
15639 while (!BinOps.
empty()) {
15647 for (
unsigned i = 0, ie = BinOp.
getNumOperands(); i != ie; ++i) {
15673 DenseMap<SDNode *, EVT> SelectTruncOp[2];
15678 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15683 if (User !=
N && !Visited.
count(User))
15689 if (
User->getOperand(0) == Inputs[i])
15690 SelectTruncOp[0].
insert(std::make_pair(User,
15691 User->getOperand(0).getValueType()));
15693 if (
User->getOperand(0) == Inputs[i])
15694 SelectTruncOp[0].
insert(std::make_pair(User,
15695 User->getOperand(0).getValueType()));
15696 if (
User->getOperand(1) == Inputs[i])
15697 SelectTruncOp[1].
insert(std::make_pair(User,
15698 User->getOperand(1).getValueType()));
15703 for (
unsigned i = 0, ie = PromOps.
size(); i != ie; ++i) {
15705 if (User !=
N && !Visited.
count(User))
15711 if (
User->getOperand(0) == PromOps[i])
15712 SelectTruncOp[0].
insert(std::make_pair(User,
15713 User->getOperand(0).getValueType()));
15715 if (
User->getOperand(0) == PromOps[i])
15716 SelectTruncOp[0].
insert(std::make_pair(User,
15717 User->getOperand(0).getValueType()));
15718 if (
User->getOperand(1) == PromOps[i])
15719 SelectTruncOp[1].
insert(std::make_pair(User,
15720 User->getOperand(1).getValueType()));
15725 unsigned PromBits =
N->getOperand(0).getValueSizeInBits();
15726 bool ReallyNeedsExt =
false;
15730 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15735 Inputs[i].getOperand(0).getValueSizeInBits();
15736 assert(PromBits < OpBits &&
"Truncation not to a smaller bit count?");
15741 OpBits-PromBits))) ||
15744 (OpBits-(PromBits-1)))) {
15745 ReallyNeedsExt =
true;
15753 std::list<HandleSDNode> PromOpHandles;
15754 for (
auto &PromOp : PromOps)
15755 PromOpHandles.emplace_back(PromOp);
15759 for (
unsigned i = 0, ie = Inputs.
size(); i != ie; ++i) {
15766 SDValue InSrc = Inputs[i].getOperand(0);
15784 while (!PromOpHandles.empty()) {
15786 PromOpHandles.pop_back();
15790 default:
C = 0;
break;
15803 PromOpHandles.emplace_front(PromOp);
15813 (SelectTruncOp[1].count(PromOp.
getNode()) &&
15815 PromOpHandles.emplace_front(PromOp);
15823 for (
unsigned i = 0; i < 2; ++i) {
15841 auto SI0 = SelectTruncOp[0].
find(PromOp.
getNode());
15842 if (SI0 != SelectTruncOp[0].
end())
15844 auto SI1 = SelectTruncOp[1].
find(PromOp.
getNode());
15845 if (SI1 != SelectTruncOp[1].
end())
15854 if (!ReallyNeedsExt)
15855 return N->getOperand(0);
15862 N->getValueSizeInBits(0), PromBits),
15863 dl,
N->getValueType(0)));
15866 "Invalid extension type");
15869 DAG.
getConstant(
N->getValueSizeInBits(0) - PromBits, dl, ShiftAmountTy);
15879 auto isValidForConvert = [IsPPC64](
SDValue &Operand) {
15888 const APInt &Val =
C->getAPIntValue();
15894 if (IsPPC64 && Val.
ult(1ULL << 16))
15908 if (LoadNode->isVolatile())
15929 return (isValidForConvert(
LHS) && isValidForConvert(
RHS));
15939 "CC mus be ISD::SETNE or ISD::SETEQ");
15941 auto getV16i8Load = [&](
const SDValue &Operand) {
15959 LoadNode->getBasePtr(), NewMMO);
16000 SDValue LHSVec = getV16i8Load(
N->getOperand(0));
16001 SDValue RHSVec = getV16i8Load(
N->getOperand(1));
16004 DAG.
getConstant(Intrinsic::ppc_altivec_vcmpequb_p,
DL, MVT::i32);
16007 IntrID, CRSel, LHSVec, RHSVec);
16010 return DAG.
getSetCC(
DL,
N->getValueType(0), PredResult,
16028 auto IsAndWithOne = [](
SDValue &V) {
16039 auto IsCompareWithZero = [](
SDValue &V) {
16046 return (IsAndWithOne(
LHS) && IsCompareWithZero(
RHS)) ||
16047 (IsAndWithOne(
RHS) && IsCompareWithZero(
LHS));
16064 auto MakeXor1 = [&](
SDValue V) {
16065 EVT VT = V.getValueType();
16072 return MakeXor1(
LHS);
16075 return MakeXor1(
RHS);
16092 DAGCombinerInfo &DCI)
const {
16093 if (Subtarget.isISA3_1())
16096 EVT VT =
N->getValueType(0);
16097 if (VT != MVT::i32 && VT != MVT::i64)
16113 SelectionDAG &DAG = DCI.DAG;
16115 EVT XVT =
X.getValueType();
16117 if ((XVT == MVT::i64 || VT == MVT::i64) && !Subtarget.isPPC64())
16123 if (XVT != MVT::i64 && Subtarget.isPPC64())
16127 EVT OpVT = Subtarget.isPPC64() ? MVT::i64 : MVT::i32;
16135 Addc, Addc, Carry);
16138 if (OpVT == MVT::i64 && VT == MVT::i32)
16145 DAGCombinerInfo &DCI)
const {
16147 "Should be called with a SETCC node");
16169 SelectionDAG &DAG = DCI.DAG;
16170 EVT VT =
N->getValueType(0);
16171 EVT OpVT =
LHS.getValueType();
16189 if (Subtarget.hasAltivec() &&
16194 return DAGCombineTruncBoolExt(
N, DCI);
16201 Op.getValueType() == MVT::f64;
16213combineElementTruncationToVectorTruncation(
SDNode *
N,
16214 DAGCombinerInfo &DCI)
const {
16216 "Should be called with a BUILD_VECTOR node");
16218 SelectionDAG &DAG = DCI.DAG;
16221 SDValue FirstInput =
N->getOperand(0);
16223 "The input operand must be an fp-to-int conversion.");
16228 if (FirstConversion == PPCISD::FCTIDZ ||
16229 FirstConversion == PPCISD::FCTIDUZ ||
16230 FirstConversion == PPCISD::FCTIWZ ||
16231 FirstConversion == PPCISD::FCTIWUZ) {
16232 bool IsSplat =
true;
16233 bool Is32Bit = FirstConversion == PPCISD::FCTIWZ ||
16234 FirstConversion == PPCISD::FCTIWUZ;
16237 EVT TargetVT =
N->getValueType(0);
16238 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
16239 SDValue NextOp =
N->getOperand(i);
16240 if (NextOp.
getOpcode() != PPCISD::MFVSR)
16243 if (NextConversion != FirstConversion)
16251 if (
N->getOperand(i) != FirstInput)
16262 for (
int i = 0, e =
N->getNumOperands(); i < e; ++i) {
16263 SDValue In =
N->getOperand(i).getOperand(0);
16273 Ops.push_back(Trunc);
16276 Ops.push_back(
In.isUndef() ? DAG.
getUNDEF(SrcVT) :
In.getOperand(0));
16280 if (FirstConversion == PPCISD::FCTIDZ ||
16281 FirstConversion == PPCISD::FCTIWZ)
16286 EVT NewVT = TargetVT == MVT::v2i64 ? MVT::v2f64 : MVT::v4f32;
16288 return DAG.
getNode(Opcode, dl, TargetVT, BV);
16306 static const APInt BasePattern =
APInt(128, 0x8000000000000000ULL) << 64;
16310 if (FullVal == BasePattern)
16311 return std::make_tuple(Uim,
uint8_t{0});
16314 if (FullVal ==
APInt(128, 1))
16315 return std::make_tuple(Uim,
uint8_t{127});
16317 return std::nullopt;
16337 "Expected a BuildVectorSDNode in combineBVLoadsSpecialValue");
16341 EVT VT =
Op.getValueType();
16342 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
16356 for (
const SDValue &Operand :
Op.getNode()->op_values()) {
16366 for (
unsigned Index = 0;
Index < NumElems; ++
Index) {
16370 uint64_t ElemValue =
C->getZExtValue();
16374 ElemValue &= ((1ULL << ElemBits) - 1);
16378 (IsLittleEndian) ? (Index * ElemBits) : (128 - (
Index + 1) * ElemBits);
16381 APInt ElemAPInt(128, ElemValue);
16382 ElemAPInt <<= BitPos;
16385 FullVal |= ElemAPInt;
16392 const auto &[Uim, ShiftAmount] = *UIMOpt;
16396 if (ShiftAmount == 0) {
16401 <<
"combineBVLoadsSpecialValue: Instruction Emitted ";
16402 LxvkqInstr.
dump());
16406 assert(ShiftAmount == 127 &&
"Unexpected lxvkq shift amount value");
16418 DAG.
getMachineNode(PPC::VSRQ, Dl, VT, ShiftAmountVec, ShiftAmountVec),
16421 <<
"\n combineBVLoadsSpecialValue: Instruction Emitted ";
16437 "Should be called with a BUILD_VECTOR node");
16442 if (!
N->getValueType(0).getVectorElementType().isByteSized())
16445 bool InputsAreConsecutiveLoads =
true;
16446 bool InputsAreReverseConsecutive =
true;
16447 unsigned ElemSize =
N->getValueType(0).getScalarType().getStoreSize();
16448 SDValue FirstInput =
N->getOperand(0);
16449 bool IsRoundOfExtLoad =
false;
16459 N->getNumOperands() == 1)
16462 if (!IsRoundOfExtLoad)
16467 for (
int i = 1, e =
N->getNumOperands(); i < e; ++i) {
16469 if (IsRoundOfExtLoad &&
N->getOperand(i).getOpcode() !=
ISD::FP_ROUND)
16472 SDValue NextInput = IsRoundOfExtLoad ?
N->getOperand(i).getOperand(0) :
16478 IsRoundOfExtLoad ?
N->getOperand(i-1).getOperand(0) :
N->getOperand(i-1);
16489 InputsAreConsecutiveLoads =
false;
16491 InputsAreReverseConsecutive =
false;
16494 if (!InputsAreConsecutiveLoads && !InputsAreReverseConsecutive)
16499 assert(!(InputsAreConsecutiveLoads && InputsAreReverseConsecutive) &&
16500 "The loads cannot be both consecutive and reverse consecutive.");
16504 if (InputsAreConsecutiveLoads) {
16505 assert(FirstLoad &&
"Input needs to be a LoadSDNode.");
16509 ReturnSDVal = WideLoad;
16510 }
else if (InputsAreReverseConsecutive) {
16512 assert(LastLoad &&
"Input needs to be a LoadSDNode.");
16517 for (
int i =
N->getNumOperands() - 1; i >= 0; i--)
16525 for (
auto *LD : InputLoads)
16527 return ReturnSDVal;
16538 unsigned NumElems =
Input.getValueType().getVectorNumElements();
16544 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16546 ShuffleMask[CorrectElems & 0xF] = Elems & 0xF;
16548 ShuffleMask[(CorrectElems & 0xF0) >> 4] = (Elems & 0xF0) >> 4;
16549 CorrectElems = CorrectElems >> 8;
16550 Elems = Elems >> 8;
16557 EVT VT =
N->getValueType(0);
16561 Input.getValueType().getVectorElementType(),
16595 auto isSExtOfVecExtract = [&](
SDValue Op) ->
bool {
16621 Elems = Elems << 8;
16630 for (
unsigned i = 0; i <
N->getNumOperands(); i++) {
16631 if (!isSExtOfVecExtract(
N->getOperand(i))) {
16638 int TgtElemArrayIdx;
16639 int InputSize =
Input.getValueType().getScalarSizeInBits();
16640 int OutputSize =
N->getValueType(0).getScalarSizeInBits();
16641 if (InputSize + OutputSize == 40)
16642 TgtElemArrayIdx = 0;
16643 else if (InputSize + OutputSize == 72)
16644 TgtElemArrayIdx = 1;
16645 else if (InputSize + OutputSize == 48)
16646 TgtElemArrayIdx = 2;
16647 else if (InputSize + OutputSize == 80)
16648 TgtElemArrayIdx = 3;
16649 else if (InputSize + OutputSize == 96)
16650 TgtElemArrayIdx = 4;
16654 uint64_t CorrectElems = TargetElems[TgtElemArrayIdx];
16656 ? CorrectElems & 0x0F0F0F0F0F0F0F0F
16657 : CorrectElems & 0xF0F0F0F0F0F0F0F0;
16658 if (Elems != CorrectElems) {
16674 if (
N->getValueType(0) != MVT::v1i128)
16677 SDValue Operand =
N->getOperand(0);
16684 EVT MemoryType = LD->getMemoryVT();
16688 bool ValidLDType = MemoryType == MVT::i8 || MemoryType == MVT::i16 ||
16689 MemoryType == MVT::i32 || MemoryType == MVT::i64;
16692 if (!ValidLDType ||
16698 LD->getChain(), LD->getBasePtr(),
16702 DAG.
getVTList(MVT::v1i128, MVT::Other),
16703 LoadOps, MemoryType, LD->getMemOperand());
16707 DAGCombinerInfo &DCI)
const {
16709 "Should be called with a BUILD_VECTOR node");
16711 SelectionDAG &DAG = DCI.DAG;
16714 if (!Subtarget.hasVSX())
16721 if (FirstInput.
getOpcode() == PPCISD::MFVSR) {
16722 SDValue Reduced = combineElementTruncationToVectorTruncation(
N, DCI);
16737 if (Subtarget.hasP9Altivec() && !DCI.isBeforeLegalize()) {
16746 if (Subtarget.isISA3_1()) {
16752 if (
N->getValueType(0) != MVT::v2f64)
16763 if (FirstInput.
getOpcode() !=
N->getOperand(1).getOpcode())
16774 if (!Ext1Op || !Ext2Op)
16783 if (FirstElem == 0 && SecondElem == 1)
16784 SubvecIdx = Subtarget.isLittleEndian() ? 1 : 0;
16785 else if (FirstElem == 2 && SecondElem == 3)
16786 SubvecIdx = Subtarget.isLittleEndian() ? 0 : 1;
16792 PPCISD::SINT_VEC_TO_FP : PPCISD::UINT_VEC_TO_FP;
16793 return DAG.
getNode(NodeType, dl, MVT::v2f64,
16798 DAGCombinerInfo &DCI)
const {
16801 "Need an int -> FP conversion node here");
16806 SelectionDAG &DAG = DCI.DAG;
16812 if (
Op.getValueType() != MVT::f32 &&
Op.getValueType() != MVT::f64)
16814 if (!
Op.getOperand(0).getValueType().isSimple())
16816 if (
Op.getOperand(0).getValueType().getSimpleVT() <= MVT(MVT::i1) ||
16817 Op.getOperand(0).getValueType().getSimpleVT() > MVT(MVT::i64))
16820 SDValue FirstOperand(
Op.getOperand(0));
16821 bool SubWordLoad = FirstOperand.getOpcode() ==
ISD::LOAD &&
16822 (FirstOperand.getValueType() == MVT::i8 ||
16823 FirstOperand.getValueType() == MVT::i16);
16824 if (Subtarget.hasP9Vector() && Subtarget.hasP9Altivec() && SubWordLoad) {
16826 bool DstDouble =
Op.getValueType() == MVT::f64;
16827 unsigned ConvOp =
Signed ?
16828 (DstDouble ? PPCISD::FCFID : PPCISD::FCFIDS) :
16829 (DstDouble ? PPCISD::FCFIDU : PPCISD::FCFIDUS);
16834 SDValue Ops[] = { LDN->getChain(), LDN->getBasePtr(), WidthConst };
16837 Ops, MVT::i8, LDN->getMemOperand());
16842 SDValue ExtOps[] = { Ld, WidthConst };
16844 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ext);
16846 return DAG.
getNode(ConvOp, dl, DstDouble ? MVT::f64 : MVT::f32, Ld);
16854 if (
Op.getOperand(0).getValueType() == MVT::i32)
16858 "UINT_TO_FP is supported only with FPCVT");
16862 unsigned FCFOp = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16867 MVT FCFTy = (Subtarget.hasFPCVT() &&
Op.getValueType() == MVT::f32)
16874 Subtarget.hasFPCVT()) ||
16876 SDValue Src =
Op.getOperand(0).getOperand(0);
16877 if (Src.getValueType() == MVT::f32) {
16879 DCI.AddToWorklist(Src.getNode());
16880 }
else if (Src.getValueType() != MVT::f64) {
16892 if (
Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
16895 DCI.AddToWorklist(
FP.getNode());
16919 switch (
N->getOpcode()) {
16924 Chain = LD->getChain();
16925 Base = LD->getBasePtr();
16926 MMO = LD->getMemOperand();
16945 MVT VecTy =
N->getValueType(0).getSimpleVT();
16953 Chain = Load.getValue(1);
16955 PPCISD::XXSWAPD, dl, DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Load);
16959 if (VecTy != MVT::v2f64) {
16986 switch (
N->getOpcode()) {
16991 Chain = ST->getChain();
16992 Base = ST->getBasePtr();
16993 MMO = ST->getMemOperand();
17013 SDValue Src =
N->getOperand(SrcOpnd);
17014 MVT VecTy = Src.getValueType().getSimpleVT();
17017 if (VecTy != MVT::v2f64) {
17023 DAG.
getVTList(MVT::v2f64, MVT::Other), Chain, Src);
17029 StoreOps, VecTy, MMO);
17036 DAGCombinerInfo &DCI)
const {
17039 unsigned Opcode =
N->getOperand(1).getOpcode();
17041 bool Strict =
N->getOperand(1)->isStrictFPOpcode();
17045 &&
"Not a FP_TO_INT Instruction!");
17048 EVT Op1VT =
N->getOperand(1).getValueType();
17051 if (!Subtarget.hasVSX() || !Subtarget.hasFPCVT() || !
isTypeLegal(ResVT))
17055 bool ValidTypeForStoreFltAsInt =
17056 (Op1VT == MVT::i32 || (Op1VT == MVT::i64 && Subtarget.isPPC64()) ||
17057 (Subtarget.hasP9Vector() && (Op1VT == MVT::i16 || Op1VT == MVT::i8)));
17060 if (ResVT == MVT::ppcf128 || (ResVT == MVT::f128 && !Subtarget.hasP9Vector()))
17063 if ((Op1VT != MVT::i64 && !Subtarget.hasP8Vector()) ||
17071 SDValue Ops[] = {
N->getOperand(0), Val,
N->getOperand(2),
17086 bool PrevElemFromFirstVec = Mask[0] < NumElts;
17087 for (
int i = 1, e = Mask.size(); i < e; i++) {
17088 if (PrevElemFromFirstVec && Mask[i] < NumElts)
17090 if (!PrevElemFromFirstVec && Mask[i] >= NumElts)
17092 PrevElemFromFirstVec = !PrevElemFromFirstVec;
17103 for (
int i = 0, e =
Op.getNumOperands(); i < e; i++) {
17104 FirstOp =
Op.getOperand(i);
17110 for (
int i = 1, e =
Op.getNumOperands(); i < e; i++)
17111 if (
Op.getOperand(i) != FirstOp && !
Op.getOperand(i).isUndef())
17121 Op =
Op.getOperand(0);
17137 int RHSFirstElt,
int RHSLastElt,
int HalfVec,
unsigned LHSNumValidElts,
17138 unsigned RHSNumValidElts,
const PPCSubtarget &Subtarget) {
17140 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - LHSNumValidElts;
17142 Subtarget.
isLittleEndian() ? HalfVec : HalfVec - RHSNumValidElts;
17143 for (
int I = 0,
E = ShuffV.
size();
I <
E; ++
I) {
17144 int Idx = ShuffV[
I];
17145 if (Idx >= LHSFirstElt && Idx <= LHSLastElt)
17146 ShuffV[
I] += LHSEltFixup;
17147 else if (Idx >= RHSFirstElt && Idx <= RHSLastElt)
17148 ShuffV[
I] += RHSEltFixup;
17159 SDLoc dl(OrigSToV);
17162 "Expecting a SCALAR_TO_VECTOR here");
17175 "Cannot produce a permuted scalar_to_vector for one element vector");
17177 unsigned ResultInElt = NumElts / 2;
17183 return DAG.
getNode(PPCISD::SCALAR_TO_VECTOR_PERMUTED, dl, VT,
17188 int HalfVec,
int LHSLastElementDefined,
17189 int RHSLastElementDefined) {
17190 for (
int Index : ShuffV) {
17194 if ((LHSLastElementDefined >= 0) && (Index < HalfVec) &&
17195 (Index > LHSLastElementDefined))
17198 if ((RHSLastElementDefined >= 0) &&
17199 (Index > HalfVec + RHSLastElementDefined))
17206 int ScalarSize,
uint64_t ShuffleEltWidth,
unsigned &NumValidElts,
17207 int FirstElt,
int &LastElt,
SDValue VecShuffOperand,
SDValue SToVNode,
17223 LastElt = (
uint64_t)ScalarSize > ShuffleEltWidth
17224 ? ScalarSize / ShuffleEltWidth - 1 + FirstElt
17227 if (SToVPermuted.
getValueType() != VecShuffOperandType)
17228 SToVPermuted = DAG.
getBitcast(VecShuffOperandType, SToVPermuted);
17229 return SToVPermuted;
17249 int NumElts =
LHS.getValueType().getVectorNumElements();
17252 bool IsLittleEndian = Subtarget.isLittleEndian();
17259 if (!Subtarget.hasDirectMove())
17279 SmallVector<int, 16> ShuffV(Mask);
17282 if (SToVLHS || SToVRHS) {
17285 int ShuffleNumElts = ShuffV.
size();
17286 int HalfVec = ShuffleNumElts / 2;
17292 unsigned LHSNumValidElts = HalfVec;
17293 unsigned RHSNumValidElts = HalfVec;
17298 int LHSFirstElt = 0;
17299 int RHSFirstElt = ShuffleNumElts;
17300 int LHSLastElt = -1;
17301 int RHSLastElt = -1;
17309 int LHSScalarSize = 0;
17310 int RHSScalarSize = 0;
17313 if (!IsLittleEndian && LHSScalarSize >= 64)
17318 if (!IsLittleEndian && RHSScalarSize >= 64)
17321 if (LHSScalarSize != 0)
17323 LHSScalarSize, ShuffleEltWidth, LHSNumValidElts, LHSFirstElt,
17324 LHSLastElt,
LHS, SToVLHS, DAG, Subtarget);
17325 if (RHSScalarSize != 0)
17327 RHSScalarSize, ShuffleEltWidth, RHSNumValidElts, RHSFirstElt,
17328 RHSLastElt,
RHS, SToVRHS, DAG, Subtarget);
17339 ShuffV, LHSFirstElt, LHSLastElt, RHSFirstElt, RHSLastElt, HalfVec,
17340 LHSNumValidElts, RHSNumValidElts, Subtarget);
17366 if (IsLittleEndian) {
17369 if (Mask[0] < NumElts)
17370 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17374 ShuffV[i] = (ShuffV[i - 1] >= 0 ? ShuffV[i - 1] : 0) + NumElts;
17379 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17383 ShuffV[i] = (ShuffV[i + 1] >= 0 ? ShuffV[i + 1] : 0) + NumElts;
17388 if (Mask[0] < NumElts)
17389 for (
int i = 0, e =
Mask.size(); i < e; i += 2) {
17393 ShuffV[i] = ShuffV[i + 1] >= 0 ? ShuffV[i + 1] - NumElts : 0;
17398 for (
int i = 1, e =
Mask.size(); i < e; i += 2) {
17402 ShuffV[i] = ShuffV[i - 1] >= 0 ? ShuffV[i - 1] - NumElts : 0;
17412 if (IsLittleEndian)
17421 DAGCombinerInfo &DCI)
const {
17423 "Not a reverse memop pattern!");
17425 auto IsElementReverse = [](
const ShuffleVectorSDNode *SVN) ->
bool {
17428 auto I =
Mask.rbegin();
17429 auto E =
Mask.rend();
17431 for (;
I !=
E; ++
I) {
17439 SelectionDAG &DAG = DCI.DAG;
17442 if (!
isTypeLegal(VT) || !Subtarget.isLittleEndian() || !Subtarget.hasVSX())
17448 if (!Subtarget.hasP9Vector())
17451 if(!IsElementReverse(SVN))
17458 for (SDUse &Use : LSBase->
uses())
17459 if (
Use.getResNo() == 0 &&
17466 PPCISD::LOAD_VEC_BE, dl, DAG.
getVTList(VT, MVT::Other), LoadOps,
17481 PPCISD::STORE_VEC_BE, dl, DAG.
getVTList(MVT::Other), StoreOps,
17490 if (IntrinsicID == Intrinsic::ppc_stdcx)
17492 else if (IntrinsicID == Intrinsic::ppc_stwcx)
17494 else if (IntrinsicID == Intrinsic::ppc_sthcx)
17496 else if (IntrinsicID == Intrinsic::ppc_stbcx)
17505 if (
N->getOpcode() == PPCISD::ADDC &&
N->hasAnyUseOfValue(1)) {
17509 if (
LHS->getOpcode() == PPCISD::ADDE &&
17529 SDValue CmpLHS =
N->getOperand(0);
17530 SDValue CmpRHS =
N->getOperand(1);
17531 SDValue TrueVal =
N->getOperand(2);
17532 SDValue FalseVal =
N->getOperand(3);
17546 if (FalseVal.getOpcode() !=
ISD::SRL || !FalseVal.hasOneUse())
17549 SDValue ShiftVal = FalseVal.getOperand(0);
17550 SDValue ShiftAmt = FalseVal.getOperand(1);
17554 if (!ShiftConst || !ShiftConst->getAPIntValue().isMinSignedValue())
17581 if (CtlzArg != CmpLHS)
17589 DAG.
getNode(PPCISD::SRL,
DL, FalseVal.getValueType(), ShiftVal, ShiftAmt);
17636 auto isZeroOrOne = [=](
SDValue &V) {
17638 V.getConstantOperandVal(0) == Intrinsic::ppc_test_data_class)
17643 if (!isZeroOrOne(NonNullConstant))
17653 EVT VType =
N->getValueType(0);
17657 return NewNonNullConstant;
17676 EVT XorVT =
N->getValueType(0);
17677 if ((XorVT != MVT::i32 && XorVT != MVT::i64))
17685 if (!XorConst || !XorConst->
isOne()) {
17687 if (!XorConst || !XorConst->
isOne())
17694 if (!
LHS.hasOneUse())
17702 SelectNode =
LHS.getOperand(0);
17716 if (MachineOpc != PPC::SELECT_CC_I4 && MachineOpc != PPC::SELECT_CC_I8)
17726 if (!ConstOp1 || !ConstOp2)
17730 if (!((ConstOp1->
isOne() && ConstOp2->
isZero()) ||
17739 MachineOpc = (XorVT == MVT::i32) ? PPC::SELECT_CC_I4 : PPC::SELECT_CC_I8;
17741 bool ConstOp1IsOne = ConstOp1->
isOne();
17744 {SelectNode.getOperand(0),
17745 DAG.getConstant(ConstOp1IsOne ? 0 : 1, DL, XorVT),
17746 DAG.getConstant(ConstOp1IsOne ? 1 : 0, DL, XorVT),
17747 SelectNode.getOperand(3)}),
17755 switch (
N->getOpcode()) {
17758 return combineADD(
N, DCI);
17790 return combineSHL(
N, DCI);
17792 return combineSRA(
N, DCI);
17794 return combineSRL(
N, DCI);
17796 return combineMUL(
N, DCI);
17798 case PPCISD::FNMSUB:
17799 return combineFMALike(
N, DCI);
17802 return N->getOperand(0);
17806 return N->getOperand(0);
17812 return N->getOperand(0);
17816 if (
SDValue SECC = combineSignExtendSetCC(
N, DCI))
17824 return DAGCombineExtBoolTrunc(
N, DCI);
17826 return combineTRUNCATE(
N, DCI);
17828 if (
SDValue CSCC = combineSetCC(
N, DCI))
17834 return DAGCombineTruncBoolExt(
N, DCI);
17837 return combineFPToIntToFP(
N, DCI);
17846 EVT Op1VT =
N->getOperand(1).getValueType();
17847 unsigned Opcode =
N->getOperand(1).getOpcode();
17851 SDValue Val = combineStoreFPToInt(
N, DCI);
17865 N->getOperand(1).getNode()->hasOneUse() &&
17866 (Op1VT == MVT::i32 || Op1VT == MVT::i16 ||
17867 (Subtarget.hasLDBRX() && Subtarget.isPPC64() && Op1VT == MVT::i64))) {
17875 SDValue BSwapOp =
N->getOperand(1).getOperand(0);
17882 if (Op1VT.
bitsGT(mVT)) {
17887 if (Op1VT == MVT::i64)
17892 N->getOperand(0), BSwapOp,
N->getOperand(2), DAG.
getValueType(mVT)
17912 ST->getBasePtr(), ST->getOffset(), MemVT,
17913 ST->getMemOperand(), ST->getAddressingMode(),
17917 return ST->isUnindexed()
17926 if (Subtarget.needsSwapsForVSXMemOps() &&
17927 (StoreVT == MVT::v2f64 || StoreVT == MVT::v2i64 ||
17928 StoreVT == MVT::v4f32 || StoreVT == MVT::v4i32))
17935 EVT VT = LD->getValueType(0);
17941 if (Subtarget.needsSwapsForVSXMemOps() &&
17942 (LoadVT == MVT::v2f64 || LoadVT == MVT::v2i64 ||
17943 LoadVT == MVT::v4f32 || LoadVT == MVT::v4i32))
17954 auto ReplaceTwoFloatLoad = [&]() {
17955 if (VT != MVT::i64)
17970 if (!LD->hasNUsesOfValue(2, 0))
17973 auto UI = LD->user_begin();
17974 while (UI.getUse().getResNo() != 0) ++UI;
17976 while (UI.getUse().getResNo() != 0) ++UI;
17977 SDNode *RightShift = *UI;
17985 if (RightShift->getOpcode() !=
ISD::SRL ||
17987 RightShift->getConstantOperandVal(1) != 32 ||
17988 !RightShift->hasOneUse())
17991 SDNode *Trunc2 = *RightShift->user_begin();
18001 Bitcast->getValueType(0) != MVT::f32)
18007 if (Subtarget.isLittleEndian())
18013 SDValue BasePtr = LD->getBasePtr();
18014 if (LD->isIndexed()) {
18016 "Non-pre-inc AM on PPC?");
18024 SDValue FloatLoad = DAG.
getLoad(MVT::f32, dl, LD->getChain(), BasePtr,
18025 LD->getPointerInfo(), LD->getAlign(),
18026 MMOFlags, LD->getAAInfo());
18032 LD->getPointerInfo().getWithOffset(4),
18035 if (LD->isIndexed()) {
18049 if (ReplaceTwoFloatLoad())
18052 EVT MemVT = LD->getMemoryVT();
18055 if (LD->isUnindexed() && VT.
isVector() &&
18058 !Subtarget.hasP8Vector() &&
18059 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
18060 VT == MVT::v4f32))) &&
18061 LD->getAlign() < ABIAlignment) {
18063 SDValue Chain = LD->getChain();
18064 SDValue Ptr = LD->getBasePtr();
18065 bool isLittleEndian = Subtarget.isLittleEndian();
18092 MVT PermCntlTy, PermTy, LDTy;
18093 Intr = isLittleEndian ? Intrinsic::ppc_altivec_lvsr
18094 : Intrinsic::ppc_altivec_lvsl;
18095 IntrLD = Intrinsic::ppc_altivec_lvx;
18096 IntrPerm = Intrinsic::ppc_altivec_vperm;
18097 PermCntlTy = MVT::v16i8;
18098 PermTy = MVT::v4i32;
18117 SDValue BaseLoadOps[] = { Chain, LDXIntID, Ptr };
18121 BaseLoadOps, LDTy, BaseMMO);
18130 int IncValue = IncOffset;
18147 SDValue ExtraLoadOps[] = { Chain, LDXIntID, Ptr };
18151 ExtraLoadOps, LDTy, ExtraMMO);
18162 if (isLittleEndian)
18164 ExtraLoad, BaseLoad, PermCntl, DAG, dl);
18167 BaseLoad, ExtraLoad, PermCntl, DAG, dl);
18170 Perm = Subtarget.hasAltivec()
18185 bool isLittleEndian = Subtarget.isLittleEndian();
18186 unsigned IID =
N->getConstantOperandVal(0);
18187 Intrinsic::ID Intr = (isLittleEndian ? Intrinsic::ppc_altivec_lvsr
18188 : Intrinsic::ppc_altivec_lvsl);
18189 if (IID == Intr &&
N->getOperand(1)->getOpcode() ==
ISD::ADD) {
18196 .zext(
Add.getScalarValueSizeInBits()))) {
18197 SDNode *BasePtr =
Add->getOperand(0).getNode();
18198 for (
SDNode *U : BasePtr->users()) {
18200 U->getConstantOperandVal(0) == IID) {
18211 SDNode *BasePtr =
Add->getOperand(0).getNode();
18212 for (
SDNode *U : BasePtr->users()) {
18215 (
Add->getConstantOperandVal(1) - U->getConstantOperandVal(1)) %
18221 V->getConstantOperandVal(0) == IID) {
18233 (IID == Intrinsic::ppc_altivec_vmaxsw ||
18234 IID == Intrinsic::ppc_altivec_vmaxsh ||
18235 IID == Intrinsic::ppc_altivec_vmaxsb)) {
18238 if ((
V1.getSimpleValueType() == MVT::v4i32 ||
18239 V1.getSimpleValueType() == MVT::v8i16 ||
18240 V1.getSimpleValueType() == MVT::v16i8) &&
18245 V1.getOperand(1) == V2) {
18266 switch (
N->getConstantOperandVal(1)) {
18269 case Intrinsic::ppc_altivec_vsum4sbs:
18270 case Intrinsic::ppc_altivec_vsum4shs:
18271 case Intrinsic::ppc_altivec_vsum4ubs: {
18278 APInt APSplatBits, APSplatUndef;
18279 unsigned SplatBitSize;
18282 APSplatBits, APSplatUndef, SplatBitSize, HasAnyUndefs, 0,
18283 !Subtarget.isLittleEndian());
18285 if (BVNIsConstantSplat && APSplatBits == 0)
18290 case Intrinsic::ppc_vsx_lxvw4x:
18291 case Intrinsic::ppc_vsx_lxvd2x:
18294 if (Subtarget.needsSwapsForVSXMemOps())
18302 if (Subtarget.needsSwapsForVSXMemOps()) {
18303 switch (
N->getConstantOperandVal(1)) {
18306 case Intrinsic::ppc_vsx_stxvw4x:
18307 case Intrinsic::ppc_vsx_stxvd2x:
18316 bool Is64BitBswapOn64BitTgt =
18317 Subtarget.isPPC64() &&
N->getValueType(0) == MVT::i64;
18319 N->getOperand(0).hasOneUse();
18320 if (IsSingleUseNormalLd &&
18321 (
N->getValueType(0) == MVT::i32 ||
N->getValueType(0) == MVT::i16 ||
18322 (Subtarget.hasLDBRX() && Is64BitBswapOn64BitTgt))) {
18333 DAG.
getVTList(
N->getValueType(0) == MVT::i64 ?
18334 MVT::i64 : MVT::i32, MVT::Other),
18335 Ops, LD->getMemoryVT(), LD->getMemOperand());
18339 if (
N->getValueType(0) == MVT::i16)
18356 !IsSingleUseNormalLd)
18361 if (!LD->isSimple())
18363 SDValue BasePtr = LD->getBasePtr();
18365 LD->getPointerInfo(), LD->getAlign());
18370 LD->getMemOperand(), 4, 4);
18374 if (Subtarget.isLittleEndian())
18380 Hi.getOperand(0).getValue(1),
Lo.getOperand(0).getValue(1));
18389 if (!
N->getOperand(0).hasOneUse() &&
18390 !
N->getOperand(1).hasOneUse() &&
18391 !
N->getOperand(2).hasOneUse()) {
18394 SDNode *VCMPrecNode =
nullptr;
18396 SDNode *LHSN =
N->getOperand(0).getNode();
18398 if (
User->getOpcode() == PPCISD::VCMP_rec &&
18402 VCMPrecNode =
User;
18414 SDNode *FlagUser =
nullptr;
18416 FlagUser ==
nullptr; ++UI) {
18417 assert(UI != VCMPrecNode->
use_end() &&
"Didn't find user!");
18430 return SDValue(VCMPrecNode, 0);
18441 SDValue LHS =
N->getOperand(2), RHS =
N->getOperand(3);
18452 auto RHSAPInt = RHS->getAsAPIntVal();
18453 if (!RHSAPInt.isIntN(64))
18456 unsigned Val = RHSAPInt.getZExtValue();
18457 auto isImpossibleCompare = [&]() {
18460 if (Val != 0 && Val != 1) {
18462 return N->getOperand(0);
18465 N->getOperand(0),
N->getOperand(4));
18470 unsigned StoreWidth = 0;
18473 if (
SDValue Impossible = isImpossibleCompare())
18485 SDValue Ops[] = {LHS.getOperand(0), LHS.getOperand(2), LHS.getOperand(3),
18489 PPCISD::STORE_COND, dl,
18491 MemNode->getMemoryVT(), MemNode->getMemOperand());
18495 if (
N->getOperand(0) == LHS.getValue(1))
18506 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other, InChain,
18508 DAG.
getRegister(PPC::CR0, MVT::i32),
N->getOperand(4),
18514 assert(isDot &&
"Can't compare against a vector result!");
18516 if (
SDValue Impossible = isImpossibleCompare())
18519 bool BranchOnWhenPredTrue = (CC ==
ISD::SETEQ) ^ (Val == 0);
18526 EVT VTs[] = { LHS.getOperand(2).getValueType(), MVT::Glue };
18531 switch (LHS.getConstantOperandVal(1)) {
18547 return DAG.
getNode(PPCISD::COND_BRANCH, dl, MVT::Other,
N->getOperand(0),
18550 N->getOperand(4), CompNode.
getValue(1));
18555 return DAGCombineBuildVector(
N, DCI);
18560 return DAGCombineBitcast(
N, DCI);
18571 EVT VT =
N->getValueType(0);
18572 if (VT == MVT::i64 && !Subtarget.isPPC64())
18574 if ((VT != MVT::i32 && VT != MVT::i64) ||
18582 unsigned Lg2 = (IsNegPow2 ? -Divisor : Divisor).
countr_zero();
18602 const APInt &DemandedElts,
18604 unsigned Depth)
const {
18606 switch (
Op.getOpcode()) {
18608 case PPCISD::LBRX: {
18611 Known.
Zero = 0xFFFF0000;
18614 case PPCISD::ADDE: {
18615 if (
Op.getResNo() == 0) {
18620 Known.
Zero = ~1ULL;
18625 switch (
Op.getConstantOperandVal(0)) {
18627 case Intrinsic::ppc_altivec_vcmpbfp_p:
18628 case Intrinsic::ppc_altivec_vcmpeqfp_p:
18629 case Intrinsic::ppc_altivec_vcmpequb_p:
18630 case Intrinsic::ppc_altivec_vcmpequh_p:
18631 case Intrinsic::ppc_altivec_vcmpequw_p:
18632 case Intrinsic::ppc_altivec_vcmpequd_p:
18633 case Intrinsic::ppc_altivec_vcmpequq_p:
18634 case Intrinsic::ppc_altivec_vcmpgefp_p:
18635 case Intrinsic::ppc_altivec_vcmpgtfp_p:
18636 case Intrinsic::ppc_altivec_vcmpgtsb_p:
18637 case Intrinsic::ppc_altivec_vcmpgtsh_p:
18638 case Intrinsic::ppc_altivec_vcmpgtsw_p:
18639 case Intrinsic::ppc_altivec_vcmpgtsd_p:
18640 case Intrinsic::ppc_altivec_vcmpgtsq_p:
18641 case Intrinsic::ppc_altivec_vcmpgtub_p:
18642 case Intrinsic::ppc_altivec_vcmpgtuh_p:
18643 case Intrinsic::ppc_altivec_vcmpgtuw_p:
18644 case Intrinsic::ppc_altivec_vcmpgtud_p:
18645 case Intrinsic::ppc_altivec_vcmpgtuq_p:
18652 switch (
Op.getConstantOperandVal(1)) {
18655 case Intrinsic::ppc_load2r:
18657 Known.
Zero = 0xFFFF0000;
18666 switch (Subtarget.getCPUDirective()) {
18688 if (
ML->getLoopDepth() > 1 &&
ML->getSubLoops().empty())
18697 for (
auto I =
ML->block_begin(), IE =
ML->block_end();
I != IE; ++
I)
18699 LoopSize +=
TII->getInstSizeInBytes(J);
18704 if (LoopSize > 16 && LoopSize <= 32)
18718 if (Constraint.
size() == 1) {
18719 switch (Constraint[0]) {
18737 }
else if (Constraint ==
"wc") {
18739 }
else if (Constraint ==
"wa" || Constraint ==
"wd" ||
18740 Constraint ==
"wf" || Constraint ==
"ws" ||
18741 Constraint ==
"wi" || Constraint ==
"ww") {
18754 Value *CallOperandVal =
info.CallOperandVal;
18757 if (!CallOperandVal)
18764 else if ((
StringRef(constraint) ==
"wa" ||
18776 switch (*constraint) {
18806std::pair<unsigned, const TargetRegisterClass *>
18810 if (Constraint.
size() == 1) {
18812 switch (Constraint[0]) {
18814 if (VT == MVT::i64 && Subtarget.isPPC64())
18815 return std::make_pair(0U, &PPC::G8RC_NOX0RegClass);
18816 return std::make_pair(0U, &PPC::GPRC_NOR0RegClass);
18818 if (VT == MVT::i64 && Subtarget.isPPC64())
18819 return std::make_pair(0U, &PPC::G8RCRegClass);
18820 return std::make_pair(0U, &PPC::GPRCRegClass);
18826 if (Subtarget.hasSPE()) {
18827 if (VT == MVT::f32 || VT == MVT::i32)
18828 return std::make_pair(0U, &PPC::GPRCRegClass);
18829 if (VT == MVT::f64 || VT == MVT::i64)
18830 return std::make_pair(0U, &PPC::SPERCRegClass);
18832 if (VT == MVT::f32 || VT == MVT::i32)
18833 return std::make_pair(0U, &PPC::F4RCRegClass);
18834 if (VT == MVT::f64 || VT == MVT::i64)
18835 return std::make_pair(0U, &PPC::F8RCRegClass);
18839 if (Subtarget.hasAltivec() && VT.
isVector())
18840 return std::make_pair(0U, &PPC::VRRCRegClass);
18841 else if (Subtarget.hasVSX())
18843 return std::make_pair(0U, &PPC::VFRCRegClass);
18846 return std::make_pair(0U, &PPC::CRRCRegClass);
18848 }
else if (Constraint ==
"wc" && Subtarget.useCRBits()) {
18850 return std::make_pair(0U, &PPC::CRBITRCRegClass);
18851 }
else if ((Constraint ==
"wa" || Constraint ==
"wd" ||
18852 Constraint ==
"wf" || Constraint ==
"wi") &&
18853 Subtarget.hasVSX()) {
18857 return std::make_pair(0U, &PPC::VSRCRegClass);
18858 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18859 return std::make_pair(0U, &PPC::VSSRCRegClass);
18860 return std::make_pair(0U, &PPC::VSFRCRegClass);
18861 }
else if ((Constraint ==
"ws" || Constraint ==
"ww") && Subtarget.hasVSX()) {
18862 if (VT == MVT::f32 && Subtarget.hasP8Vector())
18863 return std::make_pair(0U, &PPC::VSSRCRegClass);
18865 return std::make_pair(0U, &PPC::VSFRCRegClass);
18866 }
else if (Constraint ==
"lr") {
18867 if (VT == MVT::i64)
18868 return std::make_pair(0U, &PPC::LR8RCRegClass);
18870 return std::make_pair(0U, &PPC::LRRCRegClass);
18875 if (Constraint[0] ==
'{' && Constraint[Constraint.
size() - 1] ==
'}') {
18879 if (Constraint.
size() > 3 && Constraint[1] ==
'v' && Constraint[2] ==
's') {
18880 int VSNum = atoi(Constraint.
data() + 3);
18881 assert(VSNum >= 0 && VSNum <= 63 &&
18882 "Attempted to access a vsr out of range");
18884 return std::make_pair(PPC::VSL0 + VSNum, &PPC::VSRCRegClass);
18885 return std::make_pair(PPC::V0 + VSNum - 32, &PPC::VSRCRegClass);
18890 if (Constraint.
size() > 3 && Constraint[1] ==
'f') {
18891 int RegNum = atoi(Constraint.
data() + 2);
18892 if (RegNum > 31 || RegNum < 0)
18894 if (VT == MVT::f32 || VT == MVT::i32)
18895 return Subtarget.hasSPE()
18896 ? std::make_pair(PPC::R0 + RegNum, &PPC::GPRCRegClass)
18897 : std::make_pair(PPC::F0 + RegNum, &PPC::F4RCRegClass);
18898 if (VT == MVT::f64 || VT == MVT::i64)
18899 return Subtarget.hasSPE()
18900 ? std::make_pair(PPC::S0 + RegNum, &PPC::SPERCRegClass)
18901 : std::make_pair(PPC::F0 + RegNum, &PPC::F8RCRegClass);
18905 std::pair<unsigned, const TargetRegisterClass *> R =
18914 if (R.first && VT == MVT::i64 && Subtarget.isPPC64() &&
18915 PPC::GPRCRegClass.contains(R.first))
18916 return std::make_pair(
TRI->getMatchingSuperReg(R.first,
18917 PPC::sub_32, &PPC::G8RCRegClass),
18918 &PPC::G8RCRegClass);
18921 if (!R.second &&
StringRef(
"{cc}").equals_insensitive(Constraint)) {
18922 R.first = PPC::CR0;
18923 R.second = &PPC::CRRCRegClass;
18927 if (Subtarget.isAIXABI() && !TM.getAIXExtendedAltivecABI()) {
18928 if (((R.first >= PPC::V20 && R.first <= PPC::V31) ||
18929 (R.first >= PPC::VF20 && R.first <= PPC::VF31)) &&
18930 (R.second == &PPC::VSRCRegClass || R.second == &PPC::VSFRCRegClass))
18931 errs() <<
"warning: vector registers 20 to 32 are reserved in the "
18932 "default AIX AltiVec ABI and cannot be used\n";
18942 std::vector<SDValue> &
Ops,
18947 if (Constraint.
size() > 1)
18950 char Letter = Constraint[0];
18965 EVT TCVT = MVT::i64;
19006 if (Result.getNode()) {
19007 Ops.push_back(Result);
19018 if (
I.getNumOperands() <= 1)
19022 auto IntrinsicID =
Ops[1].getNode()->getAsZExtVal();
19023 if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw &&
19024 IntrinsicID != Intrinsic::ppc_trapd && IntrinsicID != Intrinsic::ppc_trap)
19027 if (
MDNode *MDN =
I.getMetadata(LLVMContext::MD_annotation))
19043 if (Ty->isVectorTy() && AM.
BaseOffs != 0 && !Subtarget.hasP9Vector())
19055 switch (AM.
Scale) {
19083 unsigned Depth =
Op.getConstantOperandVal(0);
19107 SDValue RetAddrFI = getReturnAddrFrameIndex(DAG);
19115 unsigned Depth =
Op.getConstantOperandVal(0);
19122 bool isPPC64 = PtrVT == MVT::i64;
19128 FrameReg = isPPC64 ? PPC::X1 : PPC::R1;
19130 FrameReg = isPPC64 ? PPC::FP8 : PPC::FP;
19136 FrameAddr, MachinePointerInfo());
19140#define GET_REGISTER_MATCHER
19141#include "PPCGenAsmMatcher.inc"
19145 bool IsPPC64 = Subtarget.isPPC64();
19157 if ((IsPPC64 && Reg == PPC::R2) || Reg == PPC::R0)
19163 Reg = Reg.id() - PPC::R0 + PPC::X0;
19170 if (Subtarget.is32BitELFABI())
19175 if (Subtarget.isAIXABI())
19189 return Subtarget.isGVIndirectSymbol(
G->getGlobal());
19205 case Intrinsic::ppc_atomicrmw_xchg_i128:
19206 case Intrinsic::ppc_atomicrmw_add_i128:
19207 case Intrinsic::ppc_atomicrmw_sub_i128:
19208 case Intrinsic::ppc_atomicrmw_nand_i128:
19209 case Intrinsic::ppc_atomicrmw_and_i128:
19210 case Intrinsic::ppc_atomicrmw_or_i128:
19211 case Intrinsic::ppc_atomicrmw_xor_i128:
19212 case Intrinsic::ppc_cmpxchg_i128:
19214 Info.memVT = MVT::i128;
19215 Info.ptrVal =
I.getArgOperand(0);
19217 Info.align =
Align(16);
19222 case Intrinsic::ppc_atomic_load_i128:
19224 Info.memVT = MVT::i128;
19225 Info.ptrVal =
I.getArgOperand(0);
19227 Info.align =
Align(16);
19231 case Intrinsic::ppc_atomic_store_i128:
19233 Info.memVT = MVT::i128;
19234 Info.ptrVal =
I.getArgOperand(2);
19236 Info.align =
Align(16);
19240 case Intrinsic::ppc_altivec_lvx:
19241 case Intrinsic::ppc_altivec_lvxl:
19242 case Intrinsic::ppc_altivec_lvebx:
19243 case Intrinsic::ppc_altivec_lvehx:
19244 case Intrinsic::ppc_altivec_lvewx:
19245 case Intrinsic::ppc_vsx_lxvd2x:
19246 case Intrinsic::ppc_vsx_lxvw4x:
19247 case Intrinsic::ppc_vsx_lxvd2x_be:
19248 case Intrinsic::ppc_vsx_lxvw4x_be:
19249 case Intrinsic::ppc_vsx_lxvl:
19250 case Intrinsic::ppc_vsx_lxvll: {
19253 case Intrinsic::ppc_altivec_lvebx:
19256 case Intrinsic::ppc_altivec_lvehx:
19259 case Intrinsic::ppc_altivec_lvewx:
19262 case Intrinsic::ppc_vsx_lxvd2x:
19263 case Intrinsic::ppc_vsx_lxvd2x_be:
19273 Info.ptrVal =
I.getArgOperand(0);
19276 Info.align =
Align(1);
19281 case Intrinsic::ppc_altivec_stvx:
19282 case Intrinsic::ppc_altivec_stvxl:
19283 case Intrinsic::ppc_altivec_stvebx:
19284 case Intrinsic::ppc_altivec_stvehx:
19285 case Intrinsic::ppc_altivec_stvewx:
19286 case Intrinsic::ppc_vsx_stxvd2x:
19287 case Intrinsic::ppc_vsx_stxvw4x:
19288 case Intrinsic::ppc_vsx_stxvd2x_be:
19289 case Intrinsic::ppc_vsx_stxvw4x_be:
19290 case Intrinsic::ppc_vsx_stxvl:
19291 case Intrinsic::ppc_vsx_stxvll: {
19294 case Intrinsic::ppc_altivec_stvebx:
19297 case Intrinsic::ppc_altivec_stvehx:
19300 case Intrinsic::ppc_altivec_stvewx:
19303 case Intrinsic::ppc_vsx_stxvd2x:
19304 case Intrinsic::ppc_vsx_stxvd2x_be:
19314 Info.ptrVal =
I.getArgOperand(1);
19317 Info.align =
Align(1);
19322 case Intrinsic::ppc_stdcx:
19323 case Intrinsic::ppc_stwcx:
19324 case Intrinsic::ppc_sthcx:
19325 case Intrinsic::ppc_stbcx: {
19327 auto Alignment =
Align(8);
19329 case Intrinsic::ppc_stdcx:
19332 case Intrinsic::ppc_stwcx:
19334 Alignment =
Align(4);
19336 case Intrinsic::ppc_sthcx:
19338 Alignment =
Align(2);
19340 case Intrinsic::ppc_stbcx:
19342 Alignment =
Align(1);
19347 Info.ptrVal =
I.getArgOperand(0);
19349 Info.align = Alignment;
19363 const AttributeList &FuncAttributes)
const {
19367 if (Subtarget.hasAltivec() &&
Op.size() >= 16) {
19368 if (
Op.isMemset() && Subtarget.hasVSX()) {
19373 if (TailSize > 2 && TailSize <= 4) {
19378 if (
Op.isAligned(
Align(16)) || Subtarget.hasP8Vector())
19383 if (Subtarget.isPPC64()) {
19394 assert(Ty->isIntegerTy());
19396 unsigned BitSize = Ty->getPrimitiveSizeInBits();
19397 return !(BitSize == 0 || BitSize > 64);
19405 return NumBits1 == 64 && NumBits2 == 32;
19413 return NumBits1 == 64 && NumBits2 == 32;
19420 EVT MemVT = LD->getMemoryVT();
19421 if ((MemVT == MVT::i1 || MemVT == MVT::i8 || MemVT == MVT::i16 ||
19422 (Subtarget.isPPC64() && MemVT == MVT::i32)) &&
19438 "invalid fpext types");
19440 if (DestVT == MVT::f128)
19455 unsigned *
Fast)
const {
19469 !Subtarget.allowsUnalignedFPAccess())
19473 if (Subtarget.hasVSX()) {
19474 if (VT != MVT::v2f64 && VT != MVT::v2i64 &&
19475 VT != MVT::v4f32 && VT != MVT::v4i32)
19482 if (VT == MVT::ppcf128)
19497 if (!ConstNode->getAPIntValue().isSignedIntN(64))
19505 int64_t Imm = ConstNode->getSExtValue();
19526 if (Subtarget.hasSPE() || Subtarget.useSoftFloat())
19528 switch (Ty->getScalarType()->getTypeID()) {
19533 return Subtarget.hasP9Vector();
19541 if (!
I->hasOneUse())
19545 assert(
User &&
"A single use instruction with no uses.");
19547 switch (
I->getOpcode()) {
19548 case Instruction::FMul: {
19550 if (
User->getOpcode() != Instruction::FSub &&
19551 User->getOpcode() != Instruction::FAdd)
19558 bool AllowContract =
I->getFastMathFlags().allowContract() &&
19559 User->getFastMathFlags().allowContract();
19565 case Instruction::Load: {
19578 if (
User->getOpcode() != Instruction::Store)
19598 static const MCPhysReg ScratchRegs[] = {
19599 PPC::X12, PPC::LR8, PPC::CTR8, 0
19602 return ScratchRegs;
19606 const Constant *PersonalityFn)
const {
19607 return Subtarget.isPPC64() ? PPC::X3 : PPC::R3;
19611 const Constant *PersonalityFn)
const {
19612 return Subtarget.isPPC64() ? PPC::X4 : PPC::R4;
19617 EVT VT ,
unsigned DefinedValues)
const {
19618 if (VT == MVT::v2i64)
19619 return Subtarget.hasDirectMove();
19621 if (Subtarget.hasVSX())
19648 return PPCISD::FNMSUB;
19649 case PPCISD::FNMSUB:
19655 bool LegalOps,
bool OptForSize,
19657 unsigned Depth)
const {
19661 unsigned Opc =
Op.getOpcode();
19662 EVT VT =
Op.getValueType();
19666 case PPCISD::FNMSUB:
19686 if (Flags.hasNoSignedZeros()) {
19690 N0Cost,
Depth + 1);
19694 N1Cost,
Depth + 1);
19696 if (NegN0 && N0Cost <= N1Cost) {
19697 Cost = std::min(N0Cost, N2Cost);
19699 }
else if (NegN1) {
19700 Cost = std::min(N1Cost, N2Cost);
19720 if (M.getStackProtectorGuard() ==
"tls" || Subtarget.isTargetLinux())
19726 bool ForCodeSize)
const {
19727 if (!VT.
isSimple() || !Subtarget.hasVSX())
19737 if (Subtarget.hasPrefixInstrs() && Subtarget.hasP10Vector()) {
19742 APSInt IntResult(16,
false);
19747 if (IsExact && IntResult <= 15 && IntResult >= -16)
19749 return Imm.isZero();
19752 return Imm.isPosZero();
19764 unsigned Opcode =
N->getOpcode();
19784 if (Mask->getZExtValue() == OpSizeInBits - 1)
19791 DAGCombinerInfo &DCI)
const {
19792 EVT VT =
N->getValueType(0);
19795 unsigned Opc =
N->getOpcode();
19797 "Unexpected opcode.");
19804 if (EltTy != MVT::i64 && EltTy != MVT::i32)
19808 uint64_t SplatBits = 0;
19809 bool AddSplatCase =
false;
19813 AddSplatCase =
true;
19817 if (!AddSplatCase) {
19821 unsigned SplatBitSize;
19823 APInt APSplatBits, APSplatUndef;
19825 bool BVNIsConstantSplat =
19827 HasAnyUndefs, 0, !Subtarget.isLittleEndian());
19828 if (!BVNIsConstantSplat || SplatBitSize != EltBits)
19839 if (SplatBits == (EltBits - 1)) {
19843 NewOpc = PPCISD::SHL;
19846 NewOpc = PPCISD::SRL;
19849 NewOpc = PPCISD::SRA;
19853 return DCI.DAG.getNode(NewOpc,
DL, VT, N0, SplatOnes);
19861 if (EltTy != MVT::i64 || SplatBits != 1)
19864 return DCI.DAG.getNode(
ISD::ADD, SDLoc(
N), VT, N0, N0);
19867SDValue PPCTargetLowering::combineSHL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19871 if (
N->getValueType(0).isVector())
19872 return combineVectorShift(
N, DCI);
19876 if (!Subtarget.isISA3_0() || !Subtarget.isPPC64() ||
19879 N->getValueType(0) != MVT::i64)
19894 ShiftBy = DCI.DAG.getConstant(CN1->
getZExtValue(),
DL, MVT::i32);
19900SDValue PPCTargetLowering::combineSRA(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19904 if (
N->getValueType(0).isVector())
19905 return combineVectorShift(
N, DCI);
19910SDValue PPCTargetLowering::combineSRL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
19914 if (
N->getValueType(0).isVector())
19915 return combineVectorShift(
N, DCI);
19926 if (!Subtarget.isPPC64())
19932 auto isZextOfCompareWithConstant = [](
SDValue Op) {
19934 Op.getValueType() != MVT::i64)
19938 if (Cmp.getOpcode() !=
ISD::SETCC || !Cmp.hasOneUse() ||
19939 Cmp.getOperand(0).getValueType() != MVT::i64)
19943 int64_t NegConstant = 0 -
Constant->getSExtValue();
19952 bool LHSHasPattern = isZextOfCompareWithConstant(
LHS);
19953 bool RHSHasPattern = isZextOfCompareWithConstant(
RHS);
19956 if (LHSHasPattern && !RHSHasPattern)
19958 else if (!LHSHasPattern && !RHSHasPattern)
19962 EVT CarryType = Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
19965 SDValue Z = Cmp.getOperand(0);
19967 int64_t NegConstant = 0 -
Constant->getSExtValue();
19980 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
19998 SDValue AddOrZ = NegConstant != 0 ?
Add : Z;
20028 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
20031 if (
LHS.getOpcode() != PPCISD::MAT_PCREL_ADDR)
20039 if (!GSDN || !ConstNode)
20067 EVT VT =
N->getValueType(0);
20068 if (!Subtarget.hasVSX())
20072 if (!(VT == MVT::v8i16 || VT == MVT::v16i8 || VT == MVT::v4i32 ||
20084 unsigned NumOfEles =
RHS.getNumOperands();
20085 for (
unsigned i = 0; i < NumOfEles; ++i) {
20087 if (!CN || CN->getSExtValue() != 1)
20102SDValue PPCTargetLowering::combineADD(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20124 DAGCombinerInfo &DCI)
const {
20126 if (Subtarget.useCRBits()) {
20128 if (
SDValue CRTruncValue = DAGCombineTruncBoolExt(
N, DCI))
20129 return CRTruncValue;
20136 if (Op0.
getValueType() != MVT::i128 ||
N->getValueType(0) != MVT::i64)
20139 int EltToExtract = DCI.DAG.getDataLayout().isBigEndian() ? 1 : 0;
20149 EltToExtract = EltToExtract ? 0 : 1;
20159 return DCI.DAG.getNode(
20161 DCI.DAG.getTargetConstant(EltToExtract, dl, MVT::i32));
20166SDValue PPCTargetLowering::combineMUL(
SDNode *
N, DAGCombinerInfo &DCI)
const {
20167 SelectionDAG &DAG = DCI.DAG;
20170 if (!ConstOpOrElement)
20178 auto IsProfitable = [
this](
bool IsNeg,
bool IsAddOne, EVT VT) ->
bool {
20179 switch (this->Subtarget.getCPUDirective()) {
20202 return IsAddOne && IsNeg ? VT.
isVector() :
true;
20206 EVT VT =
N->getValueType(0);
20211 APInt MulAmtAbs = MulAmt.
abs();
20213 if ((MulAmtAbs - 1).isPowerOf2()) {
20217 if (!IsProfitable(IsNeg,
true, VT))
20230 }
else if ((MulAmtAbs + 1).isPowerOf2()) {
20234 if (!IsProfitable(IsNeg,
false, VT))
20255 DAGCombinerInfo &DCI)
const {
20259 SDNodeFlags
Flags =
N->getFlags();
20260 EVT VT =
N->getValueType(0);
20261 SelectionDAG &DAG = DCI.DAG;
20262 unsigned Opc =
N->getOpcode();
20264 bool LegalOps = !DCI.isBeforeLegalizeOps();
20272 if (!
Flags.hasNoSignedZeros())
20288bool PPCTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
20290 if (!Subtarget.is64BitELFABI())
20300 if (!TM.Options.GuaranteedTailCallOpt &&
DisableSCO)
20305 if (!Callee ||
Callee->isVarArg())
20318bool PPCTargetLowering::
20319isMaskAndCmp0FoldingBeneficial(
const Instruction &AndI)
const {
20324 if (CI->getBitWidth() > 64)
20326 int64_t ConstVal = CI->getZExtValue();
20328 (
isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF));
20337PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(
unsigned Flags)
const {
20343 if ((Flags & FlagSet) == FlagSet)
20346 if ((Flags & FlagSet) == FlagSet)
20349 if ((Flags & FlagSet) == FlagSet)
20352 if ((Flags & FlagSet) == FlagSet)
20373 if ((FrameIndexAlign % 4) != 0)
20374 FlagSet &=
~PPC::MOF_RPlusSImm16Mult4;
20375 if ((FrameIndexAlign % 16) != 0)
20376 FlagSet &=
~PPC::MOF_RPlusSImm16Mult16;
20380 if ((FrameIndexAlign % 4) == 0)
20382 if ((FrameIndexAlign % 16) == 0)
20395 auto SetAlignFlagsForImm = [&](
uint64_t Imm) {
20396 if ((Imm & 0x3) == 0)
20398 if ((Imm & 0xf) == 0)
20404 const APInt &ConstImm = CN->getAPIntValue();
20423 const APInt &ConstImm = CN->getAPIntValue();
20433 }
else if (
RHS.getOpcode() == PPCISD::Lo && !
RHS.getConstantOperandVal(1))
20444 return (
N.getOpcode() == PPCISD::MAT_PCREL_ADDR ||
20453unsigned PPCTargetLowering::computeMOFlags(
const SDNode *Parent,
SDValue N,
20458 if (!Subtarget.hasP9Vector())
20463 if (Subtarget.hasPrefixInstrs())
20466 if (Subtarget.hasSPE())
20475 unsigned ParentOp = Parent->
getOpcode();
20479 if ((
ID == Intrinsic::ppc_vsx_lxvp) || (
ID == Intrinsic::ppc_vsx_stxvp)) {
20480 SDValue IntrinOp = (
ID == Intrinsic::ppc_vsx_lxvp)
20492 if (LSB->isIndexed())
20498 assert(MN &&
"Parent should be a MemSDNode!");
20503 "Not expecting scalar integers larger than 16 bytes!");
20506 else if (
Size == 32)
20513 else if (
Size == 256) {
20514 assert(Subtarget.pairedVectorMemops() &&
20515 "256-bit vectors are only available when paired vector memops is "
20523 else if (MemVT == MVT::f128 || MemVT.
isVector())
20554 FlagSet &= ~PPC::MOF_NoExt;
20559 bool IsNonP1034BitConst =
20563 IsNonP1034BitConst)
20576 int16_t ForceXFormImm = 0;
20579 Disp =
N.getOperand(0);
20580 Base =
N.getOperand(1);
20591 !
N.getOperand(1).hasOneUse() || !
N.getOperand(0).hasOneUse())) {
20592 Disp =
N.getOperand(0);
20593 Base =
N.getOperand(1);
20598 Disp = DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20607 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
20613 if (PartVT == MVT::f64 &&
20614 (ValVT == MVT::i32 || ValVT == MVT::i16 || ValVT == MVT::i8)) {
20623SDValue PPCTargetLowering::lowerToLibCall(
const char *LibCallName,
SDValue Op,
20627 EVT RetVT =
Op.getValueType();
20634 EVT ArgVT =
N.getValueType();
20638 Entry.IsZExt = !Entry.IsSExt;
20639 Args.push_back(Entry);
20647 (RetTy ==
F.getReturnType() ||
F.getReturnType()->isVoidTy());
20660SDValue PPCTargetLowering::lowerLibCallBasedOnType(
20661 const char *LibCallFloatName,
const char *LibCallDoubleName,
SDValue Op,
20663 if (
Op.getValueType() == MVT::f32)
20664 return lowerToLibCall(LibCallFloatName,
Op, DAG);
20666 if (
Op.getValueType() == MVT::f64)
20667 return lowerToLibCall(LibCallDoubleName,
Op, DAG);
20672bool PPCTargetLowering::isLowringToMASSFiniteSafe(
SDValue Op)
const {
20673 SDNodeFlags
Flags =
Op.getNode()->getFlags();
20674 return isLowringToMASSSafe(
Op) &&
Flags.hasNoSignedZeros() &&
20678bool PPCTargetLowering::isLowringToMASSSafe(
SDValue Op)
const {
20679 return Op.getNode()->getFlags().hasApproximateFuncs();
20682bool PPCTargetLowering::isScalarMASSConversionEnabled()
const {
20686SDValue PPCTargetLowering::lowerLibCallBase(
const char *LibCallDoubleName,
20687 const char *LibCallFloatName,
20688 const char *LibCallDoubleNameFinite,
20689 const char *LibCallFloatNameFinite,
20692 if (!isScalarMASSConversionEnabled() || !isLowringToMASSSafe(
Op))
20695 if (!isLowringToMASSFiniteSafe(
Op))
20696 return lowerLibCallBasedOnType(LibCallFloatName, LibCallDoubleName,
Op,
20699 return lowerLibCallBasedOnType(LibCallFloatNameFinite,
20700 LibCallDoubleNameFinite,
Op, DAG);
20704 return lowerLibCallBase(
"__xl_pow",
"__xl_powf",
"__xl_pow_finite",
20705 "__xl_powf_finite",
Op, DAG);
20709 return lowerLibCallBase(
"__xl_sin",
"__xl_sinf",
"__xl_sin_finite",
20710 "__xl_sinf_finite",
Op, DAG);
20714 return lowerLibCallBase(
"__xl_cos",
"__xl_cosf",
"__xl_cos_finite",
20715 "__xl_cosf_finite",
Op, DAG);
20719 return lowerLibCallBase(
"__xl_log",
"__xl_logf",
"__xl_log_finite",
20720 "__xl_logf_finite",
Op, DAG);
20724 return lowerLibCallBase(
"__xl_log10",
"__xl_log10f",
"__xl_log10_finite",
20725 "__xl_log10f_finite",
Op, DAG);
20729 return lowerLibCallBase(
"__xl_exp",
"__xl_expf",
"__xl_exp_finite",
20730 "__xl_expf_finite",
Op, DAG);
20755 unsigned Flags = computeMOFlags(Parent,
N, DAG);
20766 assert(Subtarget.isUsingPCRelativeCalls() &&
20767 "Must be using PC-Relative calls when a valid PC-Relative node is "
20797 Disp =
N.getOperand(1).getOperand(0);
20802 Base =
N.getOperand(0);
20810 EVT CNType = CN->getValueType(0);
20811 uint64_t CNImm = CN->getZExtValue();
20822 if ((CNType == MVT::i32 ||
isInt<32>(CNImm)) &&
20824 int32_t Addr = (int32_t)CNImm;
20829 uint32_t LIS = CNType == MVT::i32 ? PPC::LIS : PPC::LIS8;
20845 unsigned Opcode =
N.getOpcode();
20853 Base =
N.getOperand(0);
20872 Base = FI ?
N :
N.getOperand(1);
20873 Disp = FI ? DAG.
getRegister(Subtarget.isPPC64() ? PPC::ZERO8 : PPC::ZERO,
20884 bool IsVarArg)
const {
20894 return Subtarget.isPPC64() && Subtarget.hasQuadwordAtomics();
20931 return Intrinsic::ppc_atomicrmw_xchg_i128;
20933 return Intrinsic::ppc_atomicrmw_add_i128;
20935 return Intrinsic::ppc_atomicrmw_sub_i128;
20937 return Intrinsic::ppc_atomicrmw_and_i128;
20939 return Intrinsic::ppc_atomicrmw_or_i128;
20941 return Intrinsic::ppc_atomicrmw_xor_i128;
20943 return Intrinsic::ppc_atomicrmw_nand_i128;
20951 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
20955 Value *IncrLo = Builder.CreateTrunc(Incr, Int64Ty,
"incr_lo");
20957 Builder.CreateTrunc(Builder.CreateLShr(Incr, 64), Int64Ty,
"incr_hi");
20958 Value *LoHi = Builder.CreateIntrinsic(
20960 {AlignedAddr, IncrLo, IncrHi});
20961 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
20962 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
20963 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
20964 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
20965 return Builder.CreateOr(
20966 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
20973 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
20979 Value *CmpLo = Builder.CreateTrunc(CmpVal, Int64Ty,
"cmp_lo");
20981 Builder.CreateTrunc(Builder.CreateLShr(CmpVal, 64), Int64Ty,
"cmp_hi");
20982 Value *NewLo = Builder.CreateTrunc(NewVal, Int64Ty,
"new_lo");
20984 Builder.CreateTrunc(Builder.CreateLShr(NewVal, 64), Int64Ty,
"new_hi");
20987 Builder.CreateCall(IntCmpXchg, {AlignedAddr, CmpLo, CmpHi, NewLo, NewHi});
20989 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
20990 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
20991 Lo = Builder.CreateZExt(
Lo, ValTy,
"lo64");
20992 Hi = Builder.CreateZExt(
Hi, ValTy,
"hi64");
20993 return Builder.CreateOr(
20994 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValTy, 64)),
"val64");
20998 return Subtarget.useCRBits();
21003bool PPCTargetLowering::isShuffleMaskLegal(
ArrayRef<int> Mask,
EVT VT)
const {
21014 DAGCombinerInfo &DCI)
const {
21019 EVT ResVT =
N->getValueType(0);
21021 EVT SrcVT = Src.getValueType();
21026 if (ResVT != MVT::i16 && ResVT != MVT::i8)
21029 GenerateVBPERM(DAG, dl, Src, SrcVT, TruncResVT, IsLittleEndian);
21042 bool IsV16i8 = (ResVT == MVT::v16i1 && SrcVT == MVT::v16i8);
21043 bool IsV8i16 = (ResVT == MVT::v8i1 && SrcVT == MVT::v8i16);
21044 bool IsV8i8 = (ResVT == MVT::v8i1 && SrcVT == MVT::v8i8);
21046 if (!IsV16i8 && !IsV8i16 && !IsV8i8)
21054 SmallVector<int, 16> BitIndices(16, 128);
21058 BitIndices[Idx] = EltSize * (NumElts - Idx) - 1;
21059 if (IsV8i8 && IsLE)
21060 BitIndices[Idx] += 64;
21063 std::reverse(BitIndices.begin(), BitIndices.end());
21065 for (
auto Idx : BitIndices)
21070 DAG.
getConstant(Intrinsic::ppc_altivec_vbpermq, dl, MVT::i32),
21078 bool BVNIsConstantSplat,
21079 unsigned SplatBitSize)
const {
21081 if (!BVNIsConstantSplat || !Subtarget.hasVSX() || !Subtarget.hasP8Vector() ||
21082 Subtarget.hasP10Vector())
21085 EVT VT =
Op->getValueType(0);
21086 if (!((SplatBitSize == 64 && VT == MVT::v2f64) ||
21087 (SplatBitSize == 32 && VT == MVT::v4f32)))
21094 APFloat APFloatVal = CN->getValueAPF();
21096 APSInt IntResult(16,
false);
21099 if (!(IsExact && IntResult <= 15 && IntResult >= -16 && !APFloatVal.
isZero()))
21102 int64_t
IntVal = IntResult.getSExtValue();
21107 if (SplatBitSize == 64)
21110 DAG.
getConstant(Intrinsic::ppc_vsx_xvcvsxwdp, dl, MVT::i32), IntSplat);
21112 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.
static Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
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 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 void getMaxByValAlign(Type *Ty, Align &MaxAlign, Align MaxMaxAlign)
getMaxByValAlign - Helper for getByValTypeAlignment to determine the desired ByVal argument alignment...
static bool isConsecutiveLS(SDNode *N, LSBaseSDNode *Base, unsigned Bytes, int Dist, SelectionDAG &DAG)
static bool isVMerge(ShuffleVectorSDNode *N, unsigned UnitSize, unsigned LHSStart, unsigned RHSStart)
isVMerge - Common function, used to match vmrg* shuffles.
static void getLabelAccessInfo(bool IsPIC, const PPCSubtarget &Subtarget, unsigned &HiOpFlags, unsigned &LoOpFlags, const GlobalValue *GV=nullptr)
Return true if we should reference labels using a PICBase, set the HiOpFlags and LoOpFlags to the tar...
cl::opt< bool > DisableAutoPairedVecSt("disable-auto-paired-vec-st", cl::desc("disable automatically generated 32byte paired vector stores"), cl::init(true), cl::Hidden)
static void buildCallOperands(SmallVectorImpl< SDValue > &Ops, PPCTargetLowering::CallFlags CFlags, const SDLoc &dl, SelectionDAG &DAG, SmallVector< std::pair< unsigned, SDValue >, 8 > &RegsToPass, SDValue Glue, SDValue Chain, SDValue &Callee, int SPDiff, const PPCSubtarget &Subtarget)
static cl::opt< bool > DisableInnermostLoopAlign32("disable-ppc-innermost-loop-align32", cl::desc("don't always align innermost loop to 32 bytes on ppc"), cl::Hidden)
static bool usePartialVectorLoads(SDNode *N, const PPCSubtarget &ST)
Returns true if we should use a direct load into vector instruction (such as lxsd or lfd),...
static SDValue getDataClassTest(SDValue Op, FPClassTest Mask, const SDLoc &Dl, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
static void fixupShuffleMaskForPermutedSToV(SmallVectorImpl< int > &ShuffV, int LHSFirstElt, int LHSLastElt, int RHSFirstElt, int RHSLastElt, int HalfVec, unsigned LHSNumValidElts, unsigned RHSNumValidElts, const PPCSubtarget &Subtarget)
static SDValue AdjustLength(SDValue Val, unsigned Bits, bool Left, SelectionDAG &DAG)
static cl::opt< bool > DisableSCO("disable-ppc-sco", cl::desc("disable sibling call optimization on ppc"), cl::Hidden)
static std::optional< LXVKQPattern > getPatternInfo(const APInt &FullVal)
static void fixupFuncForFI(SelectionDAG &DAG, int FrameIdx, EVT VT)
static cl::opt< bool > DisablePPCPreinc("disable-ppc-preinc", cl::desc("disable preincrement load/store generation on PPC"), cl::Hidden)
static SDValue ConvertSETCCToXori(SDNode *N, SelectionDAG &DAG)
static Intrinsic::ID getIntrinsicForAtomicRMWBinOp128(AtomicRMWInst::BinOp BinOp)
static SDValue convertFPToInt(SDValue Op, SelectionDAG &DAG, const PPCSubtarget &Subtarget)
static unsigned CalculateStackSlotSize(EVT ArgVT, ISD::ArgFlagsTy Flags, unsigned PtrByteSize)
CalculateStackSlotSize - Calculates the size reserved for this argument on the stack.
static int CalculateTailCallSPDiff(SelectionDAG &DAG, bool isTailCall, unsigned ParamSize)
CalculateTailCallSPDiff - Get the amount the stack pointer has to be adjusted to accommodate the argu...
static Instruction * callIntrinsic(IRBuilderBase &Builder, Intrinsic::ID Id)
static void prepareIndirectCall(SelectionDAG &DAG, SDValue &Callee, SDValue &Glue, SDValue &Chain, const SDLoc &dl)
static SDValue 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 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 BranchProbability getOne()
static BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, unsigned MinSplatBits=0, bool isBigEndian=false) const
Check if this is a constant splat, and if so, find the smallest element size that splats the vector.
CCState - This class holds information needed while lowering arguments and return values.
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool isStrictFP() const
Determine if the call requires strict floating point semantics.
CallingConv::ID getCallingConv() const
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getCalledOperand() const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
This class represents a function call, abstracting a target machine's calling convention.
ConstantFP - Floating Point Values [float, double].
const Constant * getConstVal() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
bool isLittleEndian() const
Layout endianness...
LLVM_ABI unsigned getLargestLegalIntTypeSizeInBits() const
Returns the size of largest legal integer type size, or 0 if none are set.
LLVM_ABI IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
int64_t getOffset() const
unsigned getTargetFlags() const
const GlobalValue * getGlobal() const
LLVM_ABI const GlobalObject * getAliaseeObject() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
void setThreadLocalMode(ThreadLocalMode Val)
bool hasHiddenVisibility() const
LLVM_ABI StringRef getSection() const
Module * getParent()
Get the module that this global value is contained inside of...
bool isStrongDefinitionForLinker() const
Returns true if this global's definition will be the one chosen by the linker.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Type * getValueType() const
bool hasProtectedVisibility() const
Common base class shared among various IRBuilders.
LLVM_ABI bool hasAtomicLoad() const LLVM_READONLY
Return true if this atomic instruction loads from memory.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
This is an important class for using LLVM in a threaded context.
Base class for LoadSDNode and StoreSDNode.
Tracks which library functions to use for a particular subtarget.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
TypeSize getValue() const
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
Wrapper class representing physical registers. Should be passed by value.
MCSymbolXCOFF * getQualNameSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
@ INVALID_SIMPLE_VALUE_TYPE
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasVAStart() const
Returns true if the function calls the llvm.va_start intrinsic.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
MCSymbol * getPICBaseSymbol() const
getPICBaseSymbol - Return a function-local symbol to represent the PIC base.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
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.
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...
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 ...
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT)
Convert Op, which must be of integer type, to the integer type VT, by using an extension appropriate ...
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue getMCSymbol(MCSymbol *Sym, EVT VT)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getValue() const
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
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
static bool isIndirectCall(const MachineInstr &MI)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool checkConvertToNonDenormSingle(APFloat &ArgAPFloat)
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
bool isIntS16Immediate(SDNode *N, int16_t &Imm)
isIntS16Immediate - This method tests to see if the node is either a 32-bit or 64-bit immediate,...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
static bool isRunOfOnes64(uint64_t Val, unsigned &MB, unsigned &ME)
bool isa_and_nonnull(const Y &Val)
bool RetCC_PPC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool CC_PPC64_ELF(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool convertToNonDenormSingle(APInt &ArgAPInt)
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
bool CC_PPC32_SVR4_ByVal(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool CC_PPC32_SVR4(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr 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.
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.
static const unsigned PerfectShuffleTable[6561+1]
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This is used by foldLoadsRecursive() to capture a Root Load node which is of type or(load,...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Represent subnormal handling kind for floating point instruction inputs and outputs.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
LLVM_ABI std::string getEVTString() const
This function returns value type as a string, e.g. "i32".
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isExtended() const
Test if the given EVT is extended (as opposed to being simple).
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
unsigned getByValSize() const
void setByValSize(unsigned S)
Align getNonZeroByValAlign() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
bool isConstant() const
Returns true if we know the value of all bits.
void resetAll()
Resets the known state of all bits.
const APInt & getConstant() const
Returns the value when all bits have a known value.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Structure that collects some common arguments that get passed around between the functions for call l...
const CallingConv::ID CallConv
These are IR-level optimization flags that may be propagated to SDNodes.
void setNoFPExcept(bool b)
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setIsPostTypeLegalization(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setTailCall(bool Value=true)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
bool isBeforeLegalizeOps() const
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.