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;
753 canIgnoreDenormalInput(Den, CtxI)) {
764 return emitRsqF64(Builder, Den, SqrtFMF, DivFMF, CtxI, IsNegative);
778 Value *Den, FastMathFlags FMF,
779 const Instruction *CtxI)
const {
786 bool IsNegative =
false;
790 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
811 return emitRcpIEEE1ULP(Builder, Src, IsNegative);
820 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
825 Value *Recip = emitRcpIEEE1ULP(Builder, Den,
false);
839Value *AMDGPUCodeGenPrepareImpl::optimizeWithFDivFast(
842 if (ReqdAccuracy < 2.5f)
848 bool NumIsOne =
false;
850 if (CNum->isOne() || CNum->isMinusOne())
858 if (!HasFP32DenormalFlush && !NumIsOne)
861 return Builder.
CreateIntrinsic(Intrinsic::amdgcn_fdiv_fast, {Num, Den});
864Value *AMDGPUCodeGenPrepareImpl::visitFDivElement(
866 FastMathFlags SqrtFMF,
Value *RsqOp,
const Instruction *FDivInst,
867 float ReqdDivAccuracy)
const {
870 optimizeWithRsq(Builder, Num, RsqOp, DivFMF, SqrtFMF, FDivInst);
878 Value *Rcp = optimizeWithRcp(Builder, Num, Den, DivFMF, FDivInst);
886 Value *FDivFast = optimizeWithFDivFast(Builder, Num, Den, ReqdDivAccuracy);
890 return emitFrexpDiv(Builder, Num, Den, DivFMF);
908bool AMDGPUCodeGenPrepareImpl::visitFDiv(BinaryOperator &FDiv) {
909 if (DisableFDivExpand)
924 FastMathFlags SqrtFMF;
929 Value *RsqOp =
nullptr;
931 if (DenII && DenII->getIntrinsicID() == Intrinsic::sqrt &&
932 DenII->hasOneUse()) {
934 SqrtFMF = SqrtOp->getFastMathFlags();
935 if (canOptimizeWithRsq(DivFMF, SqrtFMF))
936 RsqOp = SqrtOp->getOperand(0);
940 if (!IsFloat && !RsqOp)
952 const bool AllowInaccurateRcp = DivFMF.
approxFunc();
953 if (!RsqOp && AllowInaccurateRcp)
957 if (IsFloat && ReqdAccuracy < 1.0f)
964 SmallVector<Value *, 4> NumVals;
965 SmallVector<Value *, 4> DenVals;
966 SmallVector<Value *, 4> RsqDenVals;
973 SmallVector<Value *, 4> ResultVals(NumVals.
size());
974 for (
int I = 0,
E = NumVals.
size();
I !=
E; ++
I) {
975 Value *NumElt = NumVals[
I];
976 Value *DenElt = DenVals[
I];
977 Value *RsqDenElt = RsqOp ? RsqDenVals[
I] :
nullptr;
980 visitFDivElement(Builder, NumElt, DenElt, DivFMF, SqrtFMF, RsqDenElt,
989 NewEltInst->copyMetadata(FDiv);
992 ResultVals[
I] = NewElt;
1000 DeadVals.push_back(&FDiv);
1011 Value *LHS_EXT64 = Builder.CreateZExt(
LHS, I64Ty);
1012 Value *RHS_EXT64 = Builder.CreateZExt(
RHS, I64Ty);
1013 Value *MUL64 = Builder.CreateMul(LHS_EXT64, RHS_EXT64);
1014 Value *
Lo = Builder.CreateTrunc(MUL64, I32Ty);
1015 Value *
Hi = Builder.CreateLShr(MUL64, Builder.getInt64(32));
1016 Hi = Builder.CreateTrunc(
Hi, I32Ty);
1017 return std::pair(
Lo,
Hi);
1028unsigned AMDGPUCodeGenPrepareImpl::getDivNumBits(BinaryOperator &
I,
Value *Num,
1030 unsigned MaxDivBits,
1031 bool IsSigned)
const {
1038 unsigned DivBits = SSBits - RHSSignBits + 1;
1039 if (DivBits > MaxDivBits)
1044 unsigned SignBits = std::min(LHSSignBits, RHSSignBits);
1045 DivBits = SSBits - SignBits + 1;
1052 unsigned RHSBits =
Known.countMaxActiveBits();
1053 if (RHSBits > MaxDivBits)
1057 unsigned LHSBits =
Known.countMaxActiveBits();
1059 unsigned DivBits = std::max(LHSBits, RHSBits);
1067 bool IsSigned)
const {
1068 unsigned DivBits = getDivNumBits(
I, Num, Den, 23, IsSigned);
1070 if (DivBits > (IsSigned ? 23 : 22))
1072 return expandDivRemToFloatImpl(Builder,
I, Num, Den, DivBits, IsDiv,
1076Value *AMDGPUCodeGenPrepareImpl::expandDivRemToFloatImpl(
1078 unsigned DivBits,
bool IsDiv,
bool IsSigned)
const {
1092 assert(0 < DivBits && DivBits <= (IsSigned ? 23 : 22) &&
1093 "abs(Num) must be <= 0x400000 for expandDivRemToFloatImpl to work "
1101 ConstantInt *One = Builder.
getInt32(1);
1159bool AMDGPUCodeGenPrepareImpl::divHasSpecialOptimization(BinaryOperator &
I,
1165 if (
C->getType()->getScalarSizeInBits() <= 32)
1181 if (BinOpDen->getOpcode() == Instruction::Shl &&
1195 if (
Known.isNegative())
1197 if (
Known.isNonNegative())
1199 return Builder.CreateAShr(V, Builder.getInt32(31));
1206 assert(
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1207 Opc == Instruction::SRem ||
Opc == Instruction::SDiv);
1213 if (divHasSpecialOptimization(
I,
X,
Y))
1216 bool IsDiv =
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv;
1217 bool IsSigned =
Opc == Instruction::SRem ||
Opc == Instruction::SDiv;
1219 Type *Ty =
X->getType();
1233 if (
Value *Res = expandDivRemToFloat(Builder,
I,
X,
Y, IsDiv, IsSigned)) {
1239 ConstantInt *One = Builder.
getInt32(1);
1241 Value *Sign =
nullptr;
1246 Sign = IsDiv ? Builder.
CreateXor(SignX, SignY) : SignX;
1327 BinaryOperator &
I,
Value *Num,
1329 if (!ExpandDiv64InIR && divHasSpecialOptimization(
I, Num, Den))
1334 bool IsDiv =
Opc == Instruction::SDiv ||
Opc == Instruction::UDiv;
1335 bool IsSigned =
Opc == Instruction::SDiv ||
Opc == Instruction::SRem;
1337 unsigned NumDivBits = getDivNumBits(
I, Num, Den, 32, IsSigned);
1338 if (NumDivBits > 32)
1341 Value *Narrowed =
nullptr;
1342 if (NumDivBits <= (IsSigned ? 23 : 22)) {
1343 Narrowed = expandDivRemToFloatImpl(Builder,
I, Num, Den, NumDivBits, IsDiv,
1345 }
else if (NumDivBits <= (IsSigned ? 31 : 32)) {
1350 Narrowed = expandDivRem32(Builder,
I, Num, Den);
1361void AMDGPUCodeGenPrepareImpl::expandDivRem64(BinaryOperator &
I)
const {
1364 if (
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv) {
1369 if (
Opc == Instruction::URem ||
Opc == Instruction::SRem) {
1389bool AMDGPUCodeGenPrepareImpl::tryNarrowMathIfNoOverflow(Instruction *
I) {
1390 unsigned Opc =
I->getOpcode();
1391 Type *OldType =
I->getType();
1393 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1398 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1400 "Instruction::Mul.");
1404 MaxBitsNeeded = std::max<unsigned>(
bit_ceil(MaxBitsNeeded), 8);
1405 Type *NewType =
DL.getSmallestLegalIntType(
I->getContext(), MaxBitsNeeded);
1409 if (NewBit >= OrigBit)
1420 int NumOfNonConstOps = 2;
1423 NumOfNonConstOps = 1;
1433 if (NewCost >= OldCost)
1444 DeadVals.push_back(
I);
1448bool AMDGPUCodeGenPrepareImpl::visitBinaryOperator(BinaryOperator &
I) {
1449 if (foldBinOpIntoSelect(
I))
1452 if (UseMul24Intrin && replaceMulWithMul24(
I))
1454 if (tryNarrowMathIfNoOverflow(&
I))
1459 Type *Ty =
I.getType();
1460 Value *NewDiv =
nullptr;
1465 if ((
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1466 Opc == Instruction::SRem ||
Opc == Instruction::SDiv) &&
1468 !DisableIDivExpand) {
1469 Value *Num =
I.getOperand(0);
1470 Value *Den =
I.getOperand(1);
1477 for (
unsigned N = 0,
E = VT->getNumElements();
N !=
E; ++
N) {
1482 if (ScalarSize <= 32) {
1483 NewElt = expandDivRem32(Builder,
I, NumEltN, DenEltN);
1489 NewElt = shrinkDivRem64(Builder,
I, NumEltN, DenEltN);
1503 NewEltI->copyIRFlags(&
I);
1508 if (ScalarSize <= 32)
1509 NewDiv = expandDivRem32(Builder,
I, Num, Den);
1511 NewDiv = shrinkDivRem64(Builder,
I, Num, Den);
1518 I.replaceAllUsesWith(NewDiv);
1519 DeadVals.push_back(&
I);
1524 if (ExpandDiv64InIR) {
1526 for (BinaryOperator *Div : Div64ToExpand) {
1527 expandDivRem64(*Div);
1536bool AMDGPUCodeGenPrepareImpl::visitLoadInst(LoadInst &
I) {
1542 canWidenScalarExtLoad(
I)) {
1553 if (
auto *
Range =
I.getMetadata(LLVMContext::MD_range)) {
1556 if (!
Lower->isNullValue()) {
1563 WidenLoad->setMetadata(LLVMContext::MD_range,
1568 int TySize =
DL.getTypeSizeInBits(
I.getType());
1573 DeadVals.push_back(&
I);
1580bool AMDGPUCodeGenPrepareImpl::visitSelectInst(SelectInst &
I) {
1586 Value *Fract =
nullptr;
1595 Value *FractSrc = matchFractPatImpl(*
X, *
C);
1600 Fract = applyFractPat(Builder, FractSrc);
1610 CmpPredicate IsNanPred;
1619 if (IsNanPred == FCmpInst::FCMP_UNO && TrueVal == CmpVal &&
1620 CmpVal == matchFractPatNanAvoidant(*FalseVal)) {
1622 Fract = applyFractPat(Builder, CmpVal);
1623 }
else if (IsNanPred == FCmpInst::FCMP_ORD && FalseVal == CmpVal) {
1624 if (CmpVal == matchFractPatNanAvoidant(*TrueVal)) {
1626 Fract = applyFractPat(Builder, CmpVal);
1630 CmpPredicate PredInf;
1636 PredInf != FCmpInst::FCMP_UNE ||
1637 CmpVal != matchFractPatNanAvoidant(*IfNotInf))
1647 Value *NewFract = applyFractPat(Builder, CmpVal);
1651 DeadVals.push_back(ClampInfSelect->
getOperand(1));
1655 Fract = ClampInfSelect;
1662 I.replaceAllUsesWith(Fract);
1663 DeadVals.push_back(&
I);
1670 return IA && IB && IA->getParent() == IB->getParent();
1680 const Value *CurVal = V;
1683 BitVector EltsCovered(FVT->getNumElements());
1690 if (!Idx || Idx->getZExtValue() >= FVT->getNumElements())
1693 const auto *VecSrc = IE->getOperand(0);
1702 EltsCovered.
set(Idx->getZExtValue());
1705 if (EltsCovered.
all())
1732 const auto [It, Inserted] = SeenPHIs.
insert(&
I);
1736 for (
const Value *Inc :
I.incoming_values()) {
1741 for (
const User *U :
I.users()) {
1747bool AMDGPUCodeGenPrepareImpl::canBreakPHINode(
const PHINode &
I) {
1749 if (
const auto It = BreakPhiNodesCache.find(&
I);
1750 It != BreakPhiNodesCache.end())
1759 SmallPtrSet<const PHINode *, 8> WorkList;
1765 for (
const PHINode *WLP : WorkList) {
1766 assert(BreakPhiNodesCache.count(WLP) == 0);
1781 const auto Threshold = (
alignTo(WorkList.size() * 2, 3) / 3);
1782 unsigned NumBreakablePHIs = 0;
1783 bool CanBreak =
false;
1784 for (
const PHINode *Cur : WorkList) {
1792 if (++NumBreakablePHIs >= Threshold) {
1799 for (
const PHINode *Cur : WorkList)
1800 BreakPhiNodesCache[Cur] = CanBreak;
1849 Value *&Res = SlicedVals[{BB, Inc}];
1855 B.SetCurrentDebugLocation(IncInst->getDebugLoc());
1861 Res =
B.CreateShuffleVector(Inc, Mask, NewValName);
1863 Res =
B.CreateExtractElement(Inc,
Idx, NewValName);
1872bool AMDGPUCodeGenPrepareImpl::visitPHINode(PHINode &
I) {
1884 cl::boolOrDefault::BOU_TRUE)
1889 DL.getTypeSizeInBits(FVT) <= BreakLargePHIsThreshold)
1892 if (!ForceBreakLargePHIs && !canBreakPHINode(
I))
1895 std::vector<VectorSlice> Slices;
1902 const unsigned EltSize =
DL.getTypeSizeInBits(EltTy);
1904 if (EltSize == 8 || EltSize == 16) {
1905 const unsigned SubVecSize = (32 / EltSize);
1907 for (
unsigned End =
alignDown(NumElts, SubVecSize); Idx < End;
1909 Slices.emplace_back(SubVecTy, Idx, SubVecSize);
1913 for (; Idx < NumElts; ++Idx)
1914 Slices.emplace_back(EltTy, Idx, 1);
1917 assert(Slices.size() > 1);
1923 B.SetCurrentDebugLocation(
I.getDebugLoc());
1925 unsigned IncNameSuffix = 0;
1926 for (VectorSlice &S : Slices) {
1929 B.SetInsertPoint(
I.getParent()->getFirstNonPHIIt());
1930 S.NewPHI =
B.CreatePHI(S.Ty,
I.getNumIncomingValues());
1932 for (
const auto &[Idx, BB] :
enumerate(
I.blocks())) {
1933 S.NewPHI->addIncoming(S.getSlicedVal(BB,
I.getIncomingValue(Idx),
1934 "largephi.extractslice" +
1935 std::to_string(IncNameSuffix++)),
1942 unsigned NameSuffix = 0;
1943 for (VectorSlice &S : Slices) {
1944 const auto ValName =
"largephi.insertslice" + std::to_string(NameSuffix++);
1946 Vec =
B.CreateInsertVector(FVT, Vec, S.NewPHI, S.Idx, ValName);
1948 Vec =
B.CreateInsertElement(Vec, S.NewPHI, S.Idx, ValName);
1951 I.replaceAllUsesWith(Vec);
1952 DeadVals.push_back(&
I);
1975 Load &&
Load->hasMetadata(LLVMContext::MD_nonnull))
1994 assert(SrcPtrKB.getBitWidth() ==
DL.getPointerSizeInBits(AS));
1995 assert((NullVal == 0 || NullVal == -1) &&
1996 "don't know how to check for this null value!");
1997 return NullVal ? !SrcPtrKB.getMaxValue().isAllOnes() : SrcPtrKB.isNonZero();
2000bool AMDGPUCodeGenPrepareImpl::visitAddrSpaceCastInst(AddrSpaceCastInst &
I) {
2004 if (
I.getType()->isVectorTy())
2009 const unsigned SrcAS =
I.getSrcAddressSpace();
2010 const unsigned DstAS =
I.getDestAddressSpace();
2012 bool CanLower =
false;
2030 auto *Intrin =
B.CreateIntrinsic(
2031 I.getType(), Intrinsic::amdgcn_addrspacecast_nonnull, {I.getOperand(0)});
2032 I.replaceAllUsesWith(Intrin);
2033 DeadVals.push_back(&
I);
2037bool AMDGPUCodeGenPrepareImpl::visitIntrinsicInst(IntrinsicInst &
I) {
2040 case Intrinsic::minnum:
2041 case Intrinsic::minimumnum:
2042 case Intrinsic::minimum:
2043 return visitFMinLike(
I);
2044 case Intrinsic::sqrt:
2045 return visitSqrt(
I);
2046 case Intrinsic::log:
2047 case Intrinsic::log10:
2049 case Intrinsic::log2:
2052 case Intrinsic::amdgcn_mbcnt_lo:
2053 return visitMbcntLo(
I);
2054 case Intrinsic::amdgcn_mbcnt_hi:
2055 return visitMbcntHi(
I);
2056 case Intrinsic::vector_reduce_add:
2057 return visitVectorReduceAdd(
I);
2058 case Intrinsic::uadd_sat:
2059 case Intrinsic::sadd_sat:
2060 return visitSaturatingAdd(
I);
2068Value *AMDGPUCodeGenPrepareImpl::matchFractPatImpl(
Value &FractSrc,
2069 const APFloat &
C)
const {
2078 OneNextDown.
next(
true);
2081 if (OneNextDown !=
C)
2101Value *AMDGPUCodeGenPrepareImpl::matchFractPatNanAvoidant(
Value &V) {
2113 return matchFractPatImpl(*Arg0, *
C);
2118 SmallVector<Value *, 4> FractVals;
2121 SmallVector<Value *, 4> ResultVals(FractVals.
size());
2124 for (
unsigned I = 0,
E = FractVals.
size();
I !=
E; ++
I) {
2132bool AMDGPUCodeGenPrepareImpl::visitFMinLike(IntrinsicInst &
I) {
2140 FractArg = matchFractPatImpl(*
X, *
C);
2145 FractArg = matchFractPatNanAvoidant(
I);
2157 FastMathFlags FMF =
I.getFastMathFlags();
2161 Value *Fract = applyFractPat(Builder, FractArg);
2163 I.replaceAllUsesWith(Fract);
2164 DeadVals.push_back(&
I);
2169bool AMDGPUCodeGenPrepareImpl::visitSqrt(IntrinsicInst &Sqrt) {
2185 if (ReqdAccuracy < 1.0f)
2189 bool CanTreatAsDAZ = canIgnoreDenormalInput(SrcVal, &Sqrt);
2193 if (!CanTreatAsDAZ && ReqdAccuracy < 2.0f)
2197 SmallVector<Value *, 4> SrcVals;
2200 SmallVector<Value *, 4> ResultVals(SrcVals.
size());
2201 for (
int I = 0,
E = SrcVals.
size();
I !=
E; ++
I) {
2203 ResultVals[
I] = Builder.
CreateCall(getSqrtF32(), SrcVals[
I]);
2205 ResultVals[
I] = emitSqrtIEEE2ULP(Builder, SrcVals[
I], SqrtFMF);
2211 DeadVals.push_back(&Sqrt);
2216bool AMDGPUCodeGenPrepareImpl::visitLog(FPMathOperator &Log,
2222 FastMathFlags FMF =
Log.getFastMathFlags();
2229 if (
Log.getFPAccuracy() < 1.80f)
2240 double Log2BaseInverted =
2247 Log.replaceAllUsesWith(
Mul);
2248 DeadVals.push_back(&Log);
2252bool AMDGPUCodeGenPrepare::runOnFunction(
Function &
F) {
2253 if (skipFunction(
F))
2256 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
2260 const AMDGPUTargetMachine &TM = TPC->getTM<AMDGPUTargetMachine>();
2261 const TargetTransformInfo &
TTI =
2262 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
2263 const TargetLibraryInfo *TLI =
2264 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2265 AssumptionCache *AC =
2266 &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
2267 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
2268 const DominatorTree *DT = DTWP ? &DTWP->getDomTree() :
nullptr;
2270 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
2271 return AMDGPUCodeGenPrepareImpl(
F, TM,
TTI, TLI, AC, DT, UA).run();
2282 AMDGPUCodeGenPrepareImpl Impl(
F, ATM,
TTI, TLI, AC, DT, UA);
2286 if (!Impl.FlowChanged)
2292 "AMDGPU IR optimizations",
false,
false)
2303 B.CreateIntrinsicWithoutFolding(Intrinsic::amdgcn_workitem_id_x, {});
2304 ST.makeLIDRangeMetadata(Tid);
2309void AMDGPUCodeGenPrepareImpl::replaceWithWorkitemIdX(Instruction &
I)
const {
2311 CallInst *Tid = createWorkitemIdX(
B);
2317void AMDGPUCodeGenPrepareImpl::replaceWithMaskedWorkitemIdX(
2318 Instruction &
I,
unsigned WaveSize)
const {
2320 CallInst *Tid = createWorkitemIdX(
B);
2322 Value *AndInst =
B.CreateAnd(Tid, Mask);
2330bool AMDGPUCodeGenPrepareImpl::tryReplaceWithWorkitemId(Instruction &
I,
2331 unsigned Wave)
const {
2338 if (*MaybeX == Wave) {
2339 replaceWithWorkitemIdX(
I);
2346 replaceWithMaskedWorkitemIdX(
I, Wave);
2354bool AMDGPUCodeGenPrepareImpl::visitMbcntLo(IntrinsicInst &
I)
const {
2370bool AMDGPUCodeGenPrepareImpl::visitMbcntHi(IntrinsicInst &
I)
const {
2383 if (*MaybeX == Wave) {
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)
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
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