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);
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 {
2394 using namespace PatternMatch;
2402 return tryReplaceWithWorkitemId(
I, Wave);
2428 Value *ExtSrc0, *ExtSrc1;
2448bool AMDGPUCodeGenPrepareImpl::visitVectorReduceAdd(IntrinsicInst &
I) {
2450 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2453 Value *
A =
nullptr, *
B =
nullptr;
2456 bool IsSigned =
false;
2463 LLVMContext &Ctx =
I.getContext();
2464 Type *I32Ty = Type::getInt32Ty(Ctx);
2472 Value *Acc = ConstantInt::get(I32Ty, 0);
2476 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2481 I.replaceAllUsesWith(Dot);
2482 DeadVals.push_back(&
I);
2490bool AMDGPUCodeGenPrepareImpl::visitSaturatingAdd(IntrinsicInst &
I) {
2492 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2496 bool IsSigned = (IID == Intrinsic::sadd_sat);
2499 Value *Op0 =
I.getArgOperand(0);
2500 Value *Op1 =
I.getArgOperand(1);
2501 Value *MulOp =
nullptr;
2502 Value *Accum =
nullptr;
2503 IntrinsicInst *ReduceInst =
nullptr;
2508 }
else if (
match(Op1,
2516 Value *
A =
nullptr, *
B =
nullptr;
2521 LLVMContext &Ctx =
I.getContext();
2522 Type *I32Ty = Type::getInt32Ty(Ctx);
2533 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2538 I.replaceAllUsesWith(Dot);
2539 DeadVals.push_back(&
I);
2542 DeadVals.push_back(ReduceInst);
2547char AMDGPUCodeGenPrepare::ID = 0;
2550 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)
SmallVector< MachineOperand, 4 > Cond
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
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
unsigned getWavefrontSize() const
bool hasWavefrontsEvenlySplittingXDim(const Function &F, bool RequiresUniformYZ=false) 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.
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.
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
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.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
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.
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...
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=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 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.
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=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.
LLVM_ABI unsigned ComputeMaxSignificantBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Get the upper bound on bit size for this Value Op as a signed integer.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL, bool OrZero=false, AssumptionCache *AC=nullptr, const Instruction *CtxI=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.
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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...
LLVM_ABI CGPassBuilderOption getCGPassBuilderOption(const TargetMachine &TM)
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.
FunctionPass * createAMDGPUCodeGenPreparePass()
To bit_cast(const From &from) noexcept
DWARFExpression::Operation Op
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...
unsigned Log2(Align A)
Returns the log2 of the alignment.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
@ End
Run the machine verifier once, at the end of the pipeline.
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...
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()
SimplifyQuery getWithInstruction(const Instruction *I) const