29#include "llvm/IR/IntrinsicsAMDGPU.h"
39#define DEBUG_TYPE "amdgpu-codegenprepare"
47 "amdgpu-codegenprepare-widen-constant-loads",
48 cl::desc(
"Widen sub-dword constant address space loads in AMDGPUCodeGenPrepare"),
53 BreakLargePHIs(
"amdgpu-codegenprepare-break-large-phis",
54 cl::desc(
"Break large PHI nodes for DAGISel"),
58 ForceBreakLargePHIs(
"amdgpu-codegenprepare-force-break-large-phis",
59 cl::desc(
"For testing purposes, always break large "
60 "PHIs even if it isn't profitable."),
64 "amdgpu-codegenprepare-break-large-phis-threshold",
65 cl::desc(
"Minimum type size in bits for breaking large PHI nodes"),
69 "amdgpu-codegenprepare-mul24",
70 cl::desc(
"Introduce mul24 intrinsics in AMDGPUCodeGenPrepare"),
76 "amdgpu-codegenprepare-expand-div64",
77 cl::desc(
"Expand 64-bit division in AMDGPUCodeGenPrepare"),
84 "amdgpu-codegenprepare-disable-idiv-expansion",
85 cl::desc(
"Prevent expanding integer division in AMDGPUCodeGenPrepare"),
91 "amdgpu-codegenprepare-disable-fdiv-expansion",
92 cl::desc(
"Prevent expanding floating point division in AMDGPUCodeGenPrepare"),
96class AMDGPUCodeGenPrepareImpl
97 :
public InstVisitor<AMDGPUCodeGenPrepareImpl, bool> {
107 const bool HasFP32DenormalFlush;
108 bool FlowChanged =
false;
109 mutable Function *SqrtF32 =
nullptr;
110 mutable Function *LdexpF32 =
nullptr;
120 UA(UA),
DL(
F.getDataLayout()), SQ(
DL, TLI, DT, AC),
130 F.getParent(), Intrinsic::amdgcn_sqrt, {Type::getFloatTy(Ctx)});
140 F.getParent(), Intrinsic::ldexp,
141 {Type::getFloatTy(Ctx), Type::getInt32Ty(Ctx)});
145 bool canBreakPHINode(
const PHINode &
I);
148 bool isLegalFloatingTy(
const Type *
T)
const;
157 bool canIgnoreDenormalInput(
const Value *V,
const Instruction *CtxI)
const {
158 return HasFP32DenormalFlush ||
183 unsigned MaxDivBits,
bool Signed)
const;
189 bool IsSigned)
const;
193 bool IsDiv,
bool IsSigned)
const;
211 bool canWidenScalarExtLoad(
LoadInst &
I)
const;
226 float ReqdAccuracy)
const;
231 float ReqdAccuracy)
const;
233 std::pair<Value *, Value *> getFrexpResults(
IRBuilder<> &Builder,
237 bool IsNegative)
const;
244 bool IsNegative)
const;
248 void replaceWithMaskedWorkitemIdX(
Instruction &
I,
unsigned WaveSize)
const;
249 bool tryReplaceWithWorkitemId(
Instruction &
I,
unsigned Wave)
const;
285 if (!ExpandDiv64InIR)
289 StringRef getPassName()
const override {
return "AMDGPU IR optimizations"; }
294bool AMDGPUCodeGenPrepareImpl::run() {
295 BreakPhiNodesCache.clear();
296 bool MadeChange =
false;
308 while (!DeadVals.empty()) {
316bool AMDGPUCodeGenPrepareImpl::isLegalFloatingTy(
const Type *Ty)
const {
318 (Ty->
isHalfTy() && ST.has16BitInsts());
321bool AMDGPUCodeGenPrepareImpl::canWidenScalarExtLoad(LoadInst &
I)
const {
322 Type *Ty =
I.getType();
323 int TySize =
DL.getTypeSizeInBits(Ty);
326 return I.isSimple() && TySize < 32 && Alignment >= 4 && UA.
isUniformAtDef(&
I);
330AMDGPUCodeGenPrepareImpl::numBitsUnsigned(
Value *
Op,
331 const Instruction *CtxI)
const {
336AMDGPUCodeGenPrepareImpl::numBitsSigned(
Value *
Op,
337 const Instruction *CtxI)
const {
349 for (
int I = 0,
E = VT->getNumElements();
I !=
E; ++
I)
350 Values.push_back(Builder.CreateExtractElement(V,
I));
356 if (!Ty->isVectorTy()) {
363 NewVal = Builder.CreateInsertElement(NewVal,
Values[
I],
I);
368bool AMDGPUCodeGenPrepareImpl::replaceMulWithMul24(BinaryOperator &
I)
const {
369 if (
I.getOpcode() != Instruction::Mul)
372 Type *Ty =
I.getType();
374 if (
Size <= 16 && ST.has16BitInsts())
384 Builder.SetCurrentDebugLocation(
I.getDebugLoc());
386 unsigned LHSBits = 0, RHSBits = 0;
387 bool IsSigned =
false;
389 if (ST.
hasMulU24() && (LHSBits = numBitsUnsigned(
LHS, &
I)) <= 24 &&
390 (RHSBits = numBitsUnsigned(
RHS, &
I)) <= 24) {
393 }
else if (ST.
hasMulI24() && (LHSBits = numBitsSigned(
LHS, &
I)) <= 24 &&
394 (RHSBits = numBitsSigned(
RHS, &
I)) <= 24) {
400 SmallVector<Value *, 4> LHSVals;
401 SmallVector<Value *, 4> RHSVals;
402 SmallVector<Value *, 4> ResultVals;
406 IntegerType *I32Ty = Builder.getInt32Ty();
407 IntegerType *IntrinTy =
Size > 32 ? Builder.getInt64Ty() : I32Ty;
408 Type *DstTy = LHSVals[0]->getType();
410 for (
int I = 0,
E = LHSVals.
size();
I !=
E; ++
I) {
411 Value *
LHS = IsSigned ? Builder.CreateSExtOrTrunc(LHSVals[
I], I32Ty)
412 : Builder.CreateZExtOrTrunc(LHSVals[
I], I32Ty);
413 Value *
RHS = IsSigned ? Builder.CreateSExtOrTrunc(RHSVals[
I], I32Ty)
414 : Builder.CreateZExtOrTrunc(RHSVals[
I], I32Ty);
416 IsSigned ? Intrinsic::amdgcn_mul_i24 : Intrinsic::amdgcn_mul_u24;
418 Result = IsSigned ? Builder.CreateSExtOrTrunc(Result, DstTy)
419 : Builder.CreateZExtOrTrunc(Result, DstTy);
425 I.replaceAllUsesWith(NewVal);
426 DeadVals.push_back(&
I);
446bool AMDGPUCodeGenPrepareImpl::foldBinOpIntoSelect(BinaryOperator &BO)
const {
467 if (!CBO || !CT || !CF)
494 Builder.setFastMathFlags(FPOp->getFastMathFlags());
500 DeadVals.push_back(&BO);
502 DeadVals.push_back(CastOp);
503 DeadVals.push_back(Sel);
507std::pair<Value *, Value *>
508AMDGPUCodeGenPrepareImpl::getFrexpResults(
IRBuilder<> &Builder,
510 Type *Ty = Src->getType();
523 : Builder.CreateExtractValue(Frexp, {1});
524 return {FrexpMant, FrexpExp};
530 bool IsNegative)
const {
545 auto [FrexpMant, FrexpExp] = getFrexpResults(Builder, Src);
548 return Builder.
CreateCall(getLdexpF32(), {Rcp, ScaleFactor});
554 FastMathFlags FMF)
const {
558 if (HasFP32DenormalFlush && ST.
hasFractBug() && !ST.hasFastFMAF32() &&
564 auto [FrexpMantRHS, FrexpExpRHS] = getFrexpResults(Builder,
RHS);
569 auto [FrexpMantLHS, FrexpExpLHS] = getFrexpResults(Builder,
LHS);
581 FastMathFlags FMF)
const {
582 Type *Ty = Src->getType();
586 Builder.
CreateFCmpOLT(Src, ConstantFP::get(Ty, SmallestNormal));
589 Value *InputScaleFactor =
596 Value *OutputScaleFactor =
598 return Builder.
CreateCall(getLdexpF32(), {Sqrt, OutputScaleFactor});
609 Type *Ty = Src->getType();
613 Builder.CreateFCmpOLT(Src, ConstantFP::get(Ty, SmallestNormal));
614 Constant *One = ConstantFP::get(Ty, 1.0);
615 Constant *InputScale = ConstantFP::get(Ty, 0x1.0p+24);
617 ConstantFP::get(Ty, IsNegative ? -0x1.0p+12 : 0x1.0p+12);
619 Value *InputScaleFactor = Builder.CreateSelect(NeedScale, InputScale, One);
621 Value *ScaledInput = Builder.CreateFMul(Src, InputScaleFactor);
622 Value *Rsq = Builder.CreateUnaryIntrinsic(Intrinsic::amdgcn_rsq, ScaledInput);
623 Value *OutputScaleFactor = Builder.CreateSelect(
624 NeedScale, OutputScale, IsNegative ? ConstantFP::get(Ty, -1.0) : One);
626 return Builder.CreateFMul(Rsq, OutputScaleFactor);
632 FastMathFlags SqrtFMF,
633 FastMathFlags DivFMF,
634 const Instruction *CtxI,
635 bool IsNegative)
const {
657 bool MaybePosInf = !SqrtFMF.
noInfs() && !DivFMF.
noInfs();
658 bool MaybeZero = !DivFMF.
noInfs();
660 DenormalMode DenormMode;
667 if (Interested !=
fcNone) {
672 DenormMode =
F.getDenormalMode(
X->getType()->getFltSemantics());
678 if (MaybeZero || MaybePosInf) {
680 if (MaybePosInf && MaybeZero) {
681 if (DenormMode.
Input != DenormalMode::DenormalModeKind::Dynamic) {
696 }
else if (MaybeZero) {
709 Value *
E = Builder.
CreateFMA(NegXY0, Y0, ConstantFP::get(
X->getType(), 1.0));
714 ConstantFP::get(
X->getType(), 0.5));
716 return Builder.
CreateFMA(Y0E, EFMA, IsNegative ? NegY0 : Y0);
719bool AMDGPUCodeGenPrepareImpl::canOptimizeWithRsq(FastMathFlags DivFMF,
720 FastMathFlags SqrtFMF)
const {
726Value *AMDGPUCodeGenPrepareImpl::optimizeWithRsq(
728 const FastMathFlags SqrtFMF,
const Instruction *CtxI)
const {
739 bool IsNegative =
false;
745 IRBuilder<>::FastMathFlagGuard Guard(Builder);
746 FastMathFlags NewFMF = DivFMF | SqrtFMF;
754 canIgnoreDenormalInput(Den, CtxI)) {
765 return emitRsqF64(Builder, Den, SqrtFMF, DivFMF, CtxI, IsNegative);
779 Value *Den, FastMathFlags FMF,
780 const Instruction *CtxI)
const {
787 bool IsNegative =
false;
791 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
812 return emitRcpIEEE1ULP(Builder, Src, IsNegative);
821 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
826 Value *Recip = emitRcpIEEE1ULP(Builder, Den,
false);
840Value *AMDGPUCodeGenPrepareImpl::optimizeWithFDivFast(
843 if (ReqdAccuracy < 2.5f)
849 bool NumIsOne =
false;
851 if (CNum->isOne() || CNum->isMinusOne())
859 if (!HasFP32DenormalFlush && !NumIsOne)
862 return Builder.
CreateIntrinsic(Intrinsic::amdgcn_fdiv_fast, {Num, Den});
865Value *AMDGPUCodeGenPrepareImpl::visitFDivElement(
867 FastMathFlags SqrtFMF,
Value *RsqOp,
const Instruction *FDivInst,
868 float ReqdDivAccuracy)
const {
871 optimizeWithRsq(Builder, Num, RsqOp, DivFMF, SqrtFMF, FDivInst);
879 Value *Rcp = optimizeWithRcp(Builder, Num, Den, DivFMF, FDivInst);
887 Value *FDivFast = optimizeWithFDivFast(Builder, Num, Den, ReqdDivAccuracy);
891 return emitFrexpDiv(Builder, Num, Den, DivFMF);
909bool AMDGPUCodeGenPrepareImpl::visitFDiv(BinaryOperator &FDiv) {
910 if (DisableFDivExpand)
925 FastMathFlags SqrtFMF;
930 Value *RsqOp =
nullptr;
932 if (DenII && DenII->getIntrinsicID() == Intrinsic::sqrt &&
933 DenII->hasOneUse()) {
935 SqrtFMF = SqrtOp->getFastMathFlags();
936 if (canOptimizeWithRsq(DivFMF, SqrtFMF))
937 RsqOp = SqrtOp->getOperand(0);
941 if (!IsFloat && !RsqOp)
953 const bool AllowInaccurateRcp = DivFMF.
approxFunc();
954 if (!RsqOp && AllowInaccurateRcp)
958 if (IsFloat && ReqdAccuracy < 1.0f)
965 SmallVector<Value *, 4> NumVals;
966 SmallVector<Value *, 4> DenVals;
967 SmallVector<Value *, 4> RsqDenVals;
974 SmallVector<Value *, 4> ResultVals(NumVals.
size());
975 for (
int I = 0,
E = NumVals.
size();
I !=
E; ++
I) {
976 Value *NumElt = NumVals[
I];
977 Value *DenElt = DenVals[
I];
978 Value *RsqDenElt = RsqOp ? RsqDenVals[
I] :
nullptr;
981 visitFDivElement(Builder, NumElt, DenElt, DivFMF, SqrtFMF, RsqDenElt,
990 NewEltInst->copyMetadata(FDiv);
993 ResultVals[
I] = NewElt;
1001 DeadVals.push_back(&FDiv);
1012 Value *LHS_EXT64 = Builder.CreateZExt(
LHS, I64Ty);
1013 Value *RHS_EXT64 = Builder.CreateZExt(
RHS, I64Ty);
1014 Value *MUL64 = Builder.CreateMul(LHS_EXT64, RHS_EXT64);
1015 Value *
Lo = Builder.CreateTrunc(MUL64, I32Ty);
1016 Value *
Hi = Builder.CreateLShr(MUL64, Builder.getInt64(32));
1017 Hi = Builder.CreateTrunc(
Hi, I32Ty);
1018 return std::pair(
Lo,
Hi);
1029unsigned AMDGPUCodeGenPrepareImpl::getDivNumBits(BinaryOperator &
I,
Value *Num,
1031 unsigned MaxDivBits,
1032 bool IsSigned)
const {
1039 unsigned DivBits = SSBits - RHSSignBits + 1;
1040 if (DivBits > MaxDivBits)
1045 unsigned SignBits = std::min(LHSSignBits, RHSSignBits);
1046 DivBits = SSBits - SignBits + 1;
1053 unsigned RHSBits =
Known.countMaxActiveBits();
1054 if (RHSBits > MaxDivBits)
1058 unsigned LHSBits =
Known.countMaxActiveBits();
1060 unsigned DivBits = std::max(LHSBits, RHSBits);
1068 bool IsSigned)
const {
1069 unsigned DivBits = getDivNumBits(
I, Num, Den, 23, IsSigned);
1071 if (DivBits > (IsSigned ? 23 : 22))
1073 return expandDivRemToFloatImpl(Builder,
I, Num, Den, DivBits, IsDiv,
1077Value *AMDGPUCodeGenPrepareImpl::expandDivRemToFloatImpl(
1079 unsigned DivBits,
bool IsDiv,
bool IsSigned)
const {
1093 assert(0 < DivBits && DivBits <= (IsSigned ? 23 : 22) &&
1094 "abs(Num) must be <= 0x400000 for expandDivRemToFloatImpl to work "
1102 ConstantInt *One = Builder.
getInt32(1);
1160bool AMDGPUCodeGenPrepareImpl::divHasSpecialOptimization(BinaryOperator &
I,
1166 if (
C->getType()->getScalarSizeInBits() <= 32)
1182 if (BinOpDen->getOpcode() == Instruction::Shl &&
1196 if (
Known.isNegative())
1198 if (
Known.isNonNegative())
1200 return Builder.CreateAShr(V, Builder.getInt32(31));
1207 assert(
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1208 Opc == Instruction::SRem ||
Opc == Instruction::SDiv);
1214 if (divHasSpecialOptimization(
I,
X,
Y))
1217 bool IsDiv =
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv;
1218 bool IsSigned =
Opc == Instruction::SRem ||
Opc == Instruction::SDiv;
1220 Type *Ty =
X->getType();
1234 if (
Value *Res = expandDivRemToFloat(Builder,
I,
X,
Y, IsDiv, IsSigned)) {
1240 ConstantInt *One = Builder.
getInt32(1);
1242 Value *Sign =
nullptr;
1247 Sign = IsDiv ? Builder.
CreateXor(SignX, SignY) : SignX;
1328 BinaryOperator &
I,
Value *Num,
1330 if (!ExpandDiv64InIR && divHasSpecialOptimization(
I, Num, Den))
1335 bool IsDiv =
Opc == Instruction::SDiv ||
Opc == Instruction::UDiv;
1336 bool IsSigned =
Opc == Instruction::SDiv ||
Opc == Instruction::SRem;
1338 unsigned NumDivBits = getDivNumBits(
I, Num, Den, 32, IsSigned);
1339 if (NumDivBits > 32)
1342 Value *Narrowed =
nullptr;
1343 if (NumDivBits <= (IsSigned ? 23 : 22)) {
1344 Narrowed = expandDivRemToFloatImpl(Builder,
I, Num, Den, NumDivBits, IsDiv,
1346 }
else if (NumDivBits <= (IsSigned ? 31 : 32)) {
1351 Narrowed = expandDivRem32(Builder,
I, Num, Den);
1362void AMDGPUCodeGenPrepareImpl::expandDivRem64(BinaryOperator &
I)
const {
1365 if (
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv) {
1370 if (
Opc == Instruction::URem ||
Opc == Instruction::SRem) {
1390bool AMDGPUCodeGenPrepareImpl::tryNarrowMathIfNoOverflow(Instruction *
I) {
1391 unsigned Opc =
I->getOpcode();
1392 Type *OldType =
I->getType();
1394 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1399 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1401 "Instruction::Mul.");
1405 MaxBitsNeeded = std::max<unsigned>(
bit_ceil(MaxBitsNeeded), 8);
1406 Type *NewType =
DL.getSmallestLegalIntType(
I->getContext(), MaxBitsNeeded);
1410 if (NewBit >= OrigBit)
1421 int NumOfNonConstOps = 2;
1424 NumOfNonConstOps = 1;
1434 if (NewCost >= OldCost)
1445 DeadVals.push_back(
I);
1449bool AMDGPUCodeGenPrepareImpl::visitBinaryOperator(BinaryOperator &
I) {
1450 if (foldBinOpIntoSelect(
I))
1453 if (UseMul24Intrin && replaceMulWithMul24(
I))
1455 if (tryNarrowMathIfNoOverflow(&
I))
1460 Type *Ty =
I.getType();
1461 Value *NewDiv =
nullptr;
1466 if ((
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1467 Opc == Instruction::SRem ||
Opc == Instruction::SDiv) &&
1469 !DisableIDivExpand) {
1470 Value *Num =
I.getOperand(0);
1471 Value *Den =
I.getOperand(1);
1478 for (
unsigned N = 0,
E = VT->getNumElements();
N !=
E; ++
N) {
1483 if (ScalarSize <= 32) {
1484 NewElt = expandDivRem32(Builder,
I, NumEltN, DenEltN);
1490 NewElt = shrinkDivRem64(Builder,
I, NumEltN, DenEltN);
1504 NewEltI->copyIRFlags(&
I);
1509 if (ScalarSize <= 32)
1510 NewDiv = expandDivRem32(Builder,
I, Num, Den);
1512 NewDiv = shrinkDivRem64(Builder,
I, Num, Den);
1519 I.replaceAllUsesWith(NewDiv);
1520 DeadVals.push_back(&
I);
1525 if (ExpandDiv64InIR) {
1527 for (BinaryOperator *Div : Div64ToExpand) {
1528 expandDivRem64(*Div);
1537bool AMDGPUCodeGenPrepareImpl::visitLoadInst(LoadInst &
I) {
1543 canWidenScalarExtLoad(
I)) {
1554 if (
auto *
Range =
I.getMetadata(LLVMContext::MD_range)) {
1557 if (!
Lower->isNullValue()) {
1564 WidenLoad->setMetadata(LLVMContext::MD_range,
1569 int TySize =
DL.getTypeSizeInBits(
I.getType());
1574 DeadVals.push_back(&
I);
1581bool AMDGPUCodeGenPrepareImpl::visitSelectInst(SelectInst &
I) {
1587 Value *Fract =
nullptr;
1596 Value *FractSrc = matchFractPatImpl(*
X, *
C);
1601 Fract = applyFractPat(Builder, FractSrc);
1611 CmpPredicate IsNanPred;
1620 if (IsNanPred == FCmpInst::FCMP_UNO && TrueVal == CmpVal &&
1621 CmpVal == matchFractPatNanAvoidant(*FalseVal)) {
1623 Fract = applyFractPat(Builder, CmpVal);
1624 }
else if (IsNanPred == FCmpInst::FCMP_ORD && FalseVal == CmpVal) {
1625 if (CmpVal == matchFractPatNanAvoidant(*TrueVal)) {
1627 Fract = applyFractPat(Builder, CmpVal);
1631 CmpPredicate PredInf;
1637 PredInf != FCmpInst::FCMP_UNE ||
1638 CmpVal != matchFractPatNanAvoidant(*IfNotInf))
1648 Value *NewFract = applyFractPat(Builder, CmpVal);
1652 DeadVals.push_back(ClampInfSelect->
getOperand(1));
1656 Fract = ClampInfSelect;
1663 I.replaceAllUsesWith(Fract);
1664 DeadVals.push_back(&
I);
1671 return IA && IB && IA->getParent() == IB->getParent();
1681 const Value *CurVal = V;
1684 BitVector EltsCovered(FVT->getNumElements());
1691 if (!Idx || Idx->getZExtValue() >= FVT->getNumElements())
1694 const auto *VecSrc = IE->getOperand(0);
1703 EltsCovered.
set(Idx->getZExtValue());
1706 if (EltsCovered.
all())
1733 const auto [It, Inserted] = SeenPHIs.
insert(&
I);
1737 for (
const Value *Inc :
I.incoming_values()) {
1742 for (
const User *U :
I.users()) {
1748bool AMDGPUCodeGenPrepareImpl::canBreakPHINode(
const PHINode &
I) {
1750 if (
const auto It = BreakPhiNodesCache.find(&
I);
1751 It != BreakPhiNodesCache.end())
1760 SmallPtrSet<const PHINode *, 8> WorkList;
1766 for (
const PHINode *WLP : WorkList) {
1767 assert(BreakPhiNodesCache.count(WLP) == 0);
1782 const auto Threshold = (
alignTo(WorkList.size() * 2, 3) / 3);
1783 unsigned NumBreakablePHIs = 0;
1784 bool CanBreak =
false;
1785 for (
const PHINode *Cur : WorkList) {
1793 if (++NumBreakablePHIs >= Threshold) {
1800 for (
const PHINode *Cur : WorkList)
1801 BreakPhiNodesCache[Cur] = CanBreak;
1850 Value *&Res = SlicedVals[{BB, Inc}];
1856 B.SetCurrentDebugLocation(IncInst->getDebugLoc());
1862 Res =
B.CreateShuffleVector(Inc, Mask, NewValName);
1864 Res =
B.CreateExtractElement(Inc,
Idx, NewValName);
1873bool AMDGPUCodeGenPrepareImpl::visitPHINode(PHINode &
I) {
1885 cl::boolOrDefault::BOU_TRUE)
1890 DL.getTypeSizeInBits(FVT) <= BreakLargePHIsThreshold)
1893 if (!ForceBreakLargePHIs && !canBreakPHINode(
I))
1896 std::vector<VectorSlice> Slices;
1903 const unsigned EltSize =
DL.getTypeSizeInBits(EltTy);
1905 if (EltSize == 8 || EltSize == 16) {
1906 const unsigned SubVecSize = (32 / EltSize);
1908 for (
unsigned End =
alignDown(NumElts, SubVecSize); Idx < End;
1910 Slices.emplace_back(SubVecTy, Idx, SubVecSize);
1914 for (; Idx < NumElts; ++Idx)
1915 Slices.emplace_back(EltTy, Idx, 1);
1918 assert(Slices.size() > 1);
1924 B.SetCurrentDebugLocation(
I.getDebugLoc());
1926 unsigned IncNameSuffix = 0;
1927 for (VectorSlice &S : Slices) {
1930 B.SetInsertPoint(
I.getParent()->getFirstNonPHIIt());
1931 S.NewPHI =
B.CreatePHI(S.Ty,
I.getNumIncomingValues());
1933 for (
const auto &[Idx, BB] :
enumerate(
I.blocks())) {
1934 S.NewPHI->addIncoming(S.getSlicedVal(BB,
I.getIncomingValue(Idx),
1935 "largephi.extractslice" +
1936 std::to_string(IncNameSuffix++)),
1943 unsigned NameSuffix = 0;
1944 for (VectorSlice &S : Slices) {
1945 const auto ValName =
"largephi.insertslice" + std::to_string(NameSuffix++);
1947 Vec =
B.CreateInsertVector(FVT, Vec, S.NewPHI, S.Idx, ValName);
1949 Vec =
B.CreateInsertElement(Vec, S.NewPHI, S.Idx, ValName);
1952 I.replaceAllUsesWith(Vec);
1953 DeadVals.push_back(&
I);
1976 Load &&
Load->hasMetadata(LLVMContext::MD_nonnull))
1995 assert(SrcPtrKB.getBitWidth() ==
DL.getPointerSizeInBits(AS));
1996 assert((NullVal == 0 || NullVal == -1) &&
1997 "don't know how to check for this null value!");
1998 return NullVal ? !SrcPtrKB.getMaxValue().isAllOnes() : SrcPtrKB.isNonZero();
2001bool AMDGPUCodeGenPrepareImpl::visitAddrSpaceCastInst(AddrSpaceCastInst &
I) {
2014 if (
I.getType()->isVectorTy())
2019 const unsigned SrcAS =
I.getSrcAddressSpace();
2020 const unsigned DstAS =
I.getDestAddressSpace();
2022 bool CanLower =
false;
2043bool AMDGPUCodeGenPrepareImpl::visitIntrinsicInst(IntrinsicInst &
I) {
2046 case Intrinsic::minnum:
2047 case Intrinsic::minimumnum:
2048 case Intrinsic::minimum:
2049 return visitFMinLike(
I);
2050 case Intrinsic::sqrt:
2051 return visitSqrt(
I);
2052 case Intrinsic::log:
2053 case Intrinsic::log10:
2055 case Intrinsic::log2:
2058 case Intrinsic::amdgcn_mbcnt_lo:
2059 return visitMbcntLo(
I);
2060 case Intrinsic::amdgcn_mbcnt_hi:
2061 return visitMbcntHi(
I);
2062 case Intrinsic::vector_reduce_add:
2063 return visitVectorReduceAdd(
I);
2064 case Intrinsic::uadd_sat:
2065 case Intrinsic::sadd_sat:
2066 return visitSaturatingAdd(
I);
2074Value *AMDGPUCodeGenPrepareImpl::matchFractPatImpl(
Value &FractSrc,
2075 const APFloat &
C)
const {
2084 OneNextDown.
next(
true);
2087 if (OneNextDown !=
C)
2107Value *AMDGPUCodeGenPrepareImpl::matchFractPatNanAvoidant(
Value &V) {
2119 return matchFractPatImpl(*Arg0, *
C);
2124 SmallVector<Value *, 4> FractVals;
2127 SmallVector<Value *, 4> ResultVals(FractVals.
size());
2130 for (
unsigned I = 0,
E = FractVals.
size();
I !=
E; ++
I) {
2138bool AMDGPUCodeGenPrepareImpl::visitFMinLike(IntrinsicInst &
I) {
2146 FractArg = matchFractPatImpl(*
X, *
C);
2151 FractArg = matchFractPatNanAvoidant(
I);
2163 FastMathFlags FMF =
I.getFastMathFlags();
2167 Value *Fract = applyFractPat(Builder, FractArg);
2169 I.replaceAllUsesWith(Fract);
2170 DeadVals.push_back(&
I);
2175bool AMDGPUCodeGenPrepareImpl::visitSqrt(IntrinsicInst &Sqrt) {
2191 if (ReqdAccuracy < 1.0f)
2195 bool CanTreatAsDAZ = canIgnoreDenormalInput(SrcVal, &Sqrt);
2199 if (!CanTreatAsDAZ && ReqdAccuracy < 2.0f)
2203 SmallVector<Value *, 4> SrcVals;
2206 SmallVector<Value *, 4> ResultVals(SrcVals.
size());
2207 for (
int I = 0,
E = SrcVals.
size();
I !=
E; ++
I) {
2209 ResultVals[
I] = Builder.
CreateCall(getSqrtF32(), SrcVals[
I]);
2211 ResultVals[
I] = emitSqrtIEEE2ULP(Builder, SrcVals[
I], SqrtFMF);
2217 DeadVals.push_back(&Sqrt);
2222bool AMDGPUCodeGenPrepareImpl::visitLog(FPMathOperator &Log,
2228 FastMathFlags FMF =
Log.getFastMathFlags();
2235 if (
Log.getFPAccuracy() < 1.80f)
2246 double Log2BaseInverted =
2253 Log.replaceAllUsesWith(
Mul);
2254 DeadVals.push_back(&Log);
2258bool AMDGPUCodeGenPrepare::runOnFunction(
Function &
F) {
2259 if (skipFunction(
F))
2262 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
2266 const AMDGPUTargetMachine &TM = TPC->getTM<AMDGPUTargetMachine>();
2267 const TargetTransformInfo &
TTI =
2268 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
2269 const TargetLibraryInfo *TLI =
2270 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2271 AssumptionCache *AC =
2272 &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
2273 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
2274 const DominatorTree *DT = DTWP ? &DTWP->getDomTree() :
nullptr;
2276 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
2277 return AMDGPUCodeGenPrepareImpl(
F, TM,
TTI, TLI, AC, DT, UA).run();
2288 AMDGPUCodeGenPrepareImpl Impl(
F, ATM,
TTI, TLI, AC, DT, UA);
2292 if (!Impl.FlowChanged)
2298 "AMDGPU IR optimizations",
false,
false)
2309 B.CreateIntrinsicWithoutFolding(Intrinsic::amdgcn_workitem_id_x, {});
2310 ST.makeLIDRangeMetadata(Tid);
2315void AMDGPUCodeGenPrepareImpl::replaceWithWorkitemIdX(Instruction &
I)
const {
2317 CallInst *Tid = createWorkitemIdX(
B);
2323void AMDGPUCodeGenPrepareImpl::replaceWithMaskedWorkitemIdX(
2324 Instruction &
I,
unsigned WaveSize)
const {
2326 CallInst *Tid = createWorkitemIdX(
B);
2328 Value *AndInst =
B.CreateAnd(Tid, Mask);
2336bool AMDGPUCodeGenPrepareImpl::tryReplaceWithWorkitemId(Instruction &
I,
2337 unsigned Wave)
const {
2344 if (*MaybeX == Wave) {
2345 replaceWithWorkitemIdX(
I);
2352 replaceWithMaskedWorkitemIdX(
I, Wave);
2360bool AMDGPUCodeGenPrepareImpl::visitMbcntLo(IntrinsicInst &
I)
const {
2376bool AMDGPUCodeGenPrepareImpl::visitMbcntHi(IntrinsicInst &
I)
const {
2389 if (*MaybeX == Wave) {
2400 using namespace PatternMatch;
2408 return tryReplaceWithWorkitemId(
I, Wave);
2434 Value *ExtSrc0, *ExtSrc1;
2454bool AMDGPUCodeGenPrepareImpl::visitVectorReduceAdd(IntrinsicInst &
I) {
2456 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2459 Value *
A =
nullptr, *
B =
nullptr;
2462 bool IsSigned =
false;
2469 LLVMContext &Ctx =
I.getContext();
2470 Type *I32Ty = Type::getInt32Ty(Ctx);
2478 Value *Acc = ConstantInt::get(I32Ty, 0);
2482 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2487 I.replaceAllUsesWith(Dot);
2488 DeadVals.push_back(&
I);
2496bool AMDGPUCodeGenPrepareImpl::visitSaturatingAdd(IntrinsicInst &
I) {
2498 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2502 bool IsSigned = (IID == Intrinsic::sadd_sat);
2505 Value *Op0 =
I.getArgOperand(0);
2506 Value *Op1 =
I.getArgOperand(1);
2507 Value *MulOp =
nullptr;
2508 Value *Accum =
nullptr;
2509 IntrinsicInst *ReduceInst =
nullptr;
2514 }
else if (
match(Op1,
2522 Value *
A =
nullptr, *
B =
nullptr;
2527 LLVMContext &Ctx =
I.getContext();
2528 Type *I32Ty = Type::getInt32Ty(Ctx);
2539 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2544 I.replaceAllUsesWith(Dot);
2545 DeadVals.push_back(&
I);
2548 DeadVals.push_back(ReduceInst);
2553char AMDGPUCodeGenPrepare::ID = 0;
2556 return new AMDGPUCodeGenPrepare();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Value * insertValues(IRBuilder<> &Builder, Type *Ty, SmallVectorImpl< Value * > &Values)
static void extractValues(IRBuilder<> &Builder, SmallVectorImpl< Value * > &Values, Value *V)
static Value * getMulHu(IRBuilder<> &Builder, Value *LHS, Value *RHS)
static bool isInterestingPHIIncomingValue(const Value *V)
static SelectInst * findSelectThroughCast(Value *V, CastInst *&Cast)
static bool matchDot4Pattern(Value *MulOp, Value *&A, Value *&B, bool IsSigned)
Helper to match the dot4 pattern: mul(zext/sext <4 x i8>, zext/sext <4 x i8>) Returns true if pattern...
static bool isV4I8(Type *Ty)
Check if type is <4 x i8>.
static std::pair< Value *, Value * > getMul64(IRBuilder<> &Builder, Value *LHS, Value *RHS)
static Value * emitRsqIEEE1ULP(IRBuilder<> &Builder, Value *Src, bool IsNegative)
Emit an expansion of 1.0 / sqrt(Src) good for 1ulp that supports denormals.
static Value * getSign32(Value *V, IRBuilder<> &Builder, const DataLayout DL)
static void collectPHINodes(const PHINode &I, SmallPtrSet< const PHINode *, 8 > &SeenPHIs)
static bool isPtrKnownNeverNull(const Value *V, const DataLayout &DL, const AMDGPUTargetMachine &TM, unsigned AS)
static bool areInSameBB(const Value *A, const Value *B)
static cl::opt< bool > WidenLoads("amdgpu-late-codegenprepare-widen-constant-loads", cl::desc("Widen sub-dword constant address space loads in " "AMDGPULateCodeGenPrepare"), cl::ReallyHidden, cl::init(true))
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool runOnFunction(Function &F, bool PostInlining)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static cl::opt< cl::boolOrDefault > EnableGlobalISelOption("global-isel", cl::Hidden, cl::desc("Enable the \"global\" instruction selector"))
Target-Independent Code Generator Pass Configuration Options pass.
VectorSlice(Type *Ty, unsigned Idx, unsigned NumElts)
Value * getSlicedVal(BasicBlock *BB, Value *Inc, StringRef NewValName)
Slice Inc according to the information contained within this slice.
PreservedAnalyses run(Function &, FunctionAnalysisManager &)
std::optional< unsigned > getReqdWorkGroupSize(const Function &F, unsigned Dim) const
bool hasWavefrontsEvenlySplittingXDim(const Function &F, bool REquiresUniformYZ=false) const
unsigned getWavefrontSize() const
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
opStatus next(bool nextDown)
This class represents a conversion between pointers from one address space to another.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BinaryOps getOpcode() const
BitVector & set()
Set all bits in the bitvector.
bool all() const
Returns true if all bits are set.
Represents analyses that only rely on functions' control flow.
This class represents a function call, abstracting a target machine's calling convention.
This is the base class for all instructions that perform data casts.
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
bool isOne() const
Returns true if this value is exactly +1.0.
static LLVM_ABI ConstantFP * getInfinity(Type *Ty, bool Negative=false)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Utility class for floating point operations which can have information about relaxed accuracy require...
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
LLVM_ABI float getFPAccuracy() const
Get the maximum error permitted by this operation in ULPs.
Convenience struct for specifying and reasoning about fast-math flags.
void setFast(bool B=true)
bool noSignedZeros() const
static FastMathFlags intersectValue(FastMathFlags LHS, FastMathFlags RHS)
Intersect value flags.
bool allowReciprocal() const
void setNoSignedZeros(bool B=true)
void setNoNaNs(bool B=true)
void setNoInfs(bool B=true)
bool allowContract() const
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
bool isWaveSizeKnown() const
Returns if the wavesize of this subtarget is known reliable.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateFDiv(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateFPToUI(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateUIToFP(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false, MDNode *FPMathTag=nullptr)
void setFastMathFlags(FastMathFlags NewFMF)
Set the fast-math flags to be used with generated fp-math operators.
Value * CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)
LLVM_ABI Value * createIsFPClass(Value *FPNum, unsigned Test)
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateFMA(Value *Factor1, Value *Factor2, Value *Summand, FMFSource FMFSource={}, const Twine &Name="")
Create call to the fma intrinsic.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Type * getFloatTy()
Fetch the type representing a 32-bit floating point value.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateSIToFP(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateFMul(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateFNeg(Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Value * CreateSExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a SExt or Trunc from the integer value V to DestTy.
Value * CreateFMulFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI Value * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *Op, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 1 operand which is mangled on its type.
Value * CreateFPToSI(Value *V, Type *DestTy, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
This class represents the LLVM 'select' instruction.
const Value * getFalseValue() const
const Value * getCondition() const
const Value * getTrueValue() const
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.
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
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 unsigned getIntegerBitWidth() const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI const fltSemantics & getFltSemantics() const
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) 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.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Type * getElementType() const
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ PRIVATE_ADDRESS
Address space for private memory.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
void copyMetadataForWidenedLoad(LoadInst &Dest, const LoadInst &Source)
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.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
auto m_PosZeroFP()
Matches a floating-point positive zero.
AllOnesConstantMatch m_AllOnes()
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
CmpClass_match< LHS, RHS, FCmpInst > m_FCmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FSub > m_FSub(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_deferred< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
ap_match< APFloat > m_APFloatAllowPoison(const APFloat *&Res)
Match APFloat while allowing poison in splat vector constants.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
FMaxMin_match< LHS, RHS, ufmin_pred_ty > m_UnordFMin(const LHS &L, const RHS &R)
Match an 'unordered' floating point minimum function.
auto m_FMinimum(const Opnd0 &Op0, const Opnd1 &Op1)
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
cstfp_pred_ty< is_nonnan > m_NonNaN()
Match a non-NaN FP constant.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
auto m_FMinNum_or_FMinimumNum(const Opnd0 &Op0, const Opnd1 &Op1)
cstfp_pred_ty< is_signed_inf< false > > m_PosInf()
Match a positive infinity FP constant.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_FAbs(const Opnd0 &Op0)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool expandRemainderUpTo64Bits(BinaryOperator *Rem)
Generate code to calculate the remainder of two integers, replacing Rem with the generated code.
@ Load
The value being inserted comes from a load (InsertElement only).
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
LLVM_ABI void ReplaceInstWithValue(BasicBlock::iterator &BI, Value *V)
Replace all uses of an instruction (specified by BI) with a value, then remove and delete the origina...
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
auto reverse(ContainerTy &&C)
LLVM_ABI bool expandDivisionUpTo64Bits(BinaryOperator *Div)
Generate code to divide two integers, replacing Div with the generated code.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
LLVM_ABI Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)
Attempt to constant fold a cast with the specified operand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
LLVM_ABI Constant * ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL)
Attempt to constant fold a binary operation with the specified operands.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
FunctionPass * createAMDGPUCodeGenPreparePass()
To bit_cast(const From &from) noexcept
DWARFExpression::Operation Op
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return the number of times the sign bit of the register is replicated into the other bits.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isKnownNeverNaN(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the floating-point scalar value is not a NaN or if the floating-point vector value has...
LLVM_ABI unsigned ComputeMaxSignificantBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Get the upper bound on bit size for this Value Op as a signed integer.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI bool isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL, bool OrZero=false, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return true if the given value is known to have exactly one bit set when defined.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
LLVM_ABI CGPassBuilderOption getCGPassBuilderOption()
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
constexpr bool inputsAreZero() const
Return true if input denormals must be implicitly treated as 0.
static constexpr DenormalMode getPreserveSign()
bool isKnownNeverSubnormal() const
Return true if it's known this can never be a subnormal.
LLVM_ABI bool isKnownNeverLogicalZero(DenormalMode Mode) const
Return true if it's known this can never be interpreted as a zero.
bool isKnownNeverPosInfinity() const
Return true if it's known this can never be +infinity.
SimplifyQuery getWithInstruction(const Instruction *I) const