30#include "llvm/IR/IntrinsicsAMDGPU.h"
41#define DEBUG_TYPE "amdgpu-codegenprepare"
49 "amdgpu-codegenprepare-widen-constant-loads",
50 cl::desc(
"Widen sub-dword constant address space loads in AMDGPUCodeGenPrepare"),
55 BreakLargePHIs(
"amdgpu-codegenprepare-break-large-phis",
56 cl::desc(
"Break large PHI nodes for DAGISel"),
60 ForceBreakLargePHIs(
"amdgpu-codegenprepare-force-break-large-phis",
61 cl::desc(
"For testing purposes, always break large "
62 "PHIs even if it isn't profitable."),
66 "amdgpu-codegenprepare-break-large-phis-threshold",
67 cl::desc(
"Minimum type size in bits for breaking large PHI nodes"),
71 "amdgpu-codegenprepare-mul24",
72 cl::desc(
"Introduce mul24 intrinsics in AMDGPUCodeGenPrepare"),
78 "amdgpu-codegenprepare-expand-div64",
79 cl::desc(
"Expand 64-bit division in AMDGPUCodeGenPrepare"),
86 "amdgpu-codegenprepare-disable-idiv-expansion",
87 cl::desc(
"Prevent expanding integer division in AMDGPUCodeGenPrepare"),
93 "amdgpu-codegenprepare-disable-fdiv-expansion",
94 cl::desc(
"Prevent expanding floating point division in AMDGPUCodeGenPrepare"),
98class AMDGPUCodeGenPrepareImpl
99 :
public InstVisitor<AMDGPUCodeGenPrepareImpl, bool> {
109 const bool HasFP32DenormalFlush;
110 bool FlowChanged =
false;
111 mutable Function *SqrtF32 =
nullptr;
112 mutable Function *LdexpF32 =
nullptr;
122 UA(UA),
DL(
F.getDataLayout()), SQ(
DL, TLI, DT, AC),
132 F.getParent(), Intrinsic::amdgcn_sqrt, {Type::getFloatTy(Ctx)});
142 F.getParent(), Intrinsic::ldexp,
143 {Type::getFloatTy(Ctx), Type::getInt32Ty(Ctx)});
147 bool canBreakPHINode(
const PHINode &
I);
150 bool isLegalFloatingTy(
const Type *
T)
const;
159 bool canIgnoreDenormalInput(
const Value *V,
const Instruction *CtxI)
const {
160 return HasFP32DenormalFlush ||
185 unsigned MaxDivBits,
bool Signed)
const;
191 bool IsSigned)
const;
195 bool IsDiv,
bool IsSigned)
const;
213 bool canWidenScalarExtLoad(
LoadInst &
I)
const;
228 float ReqdAccuracy)
const;
233 float ReqdAccuracy)
const;
235 std::pair<Value *, Value *> getFrexpResults(
IRBuilder<> &Builder,
239 bool IsNegative)
const;
246 bool IsNegative)
const;
250 void replaceWithMaskedWorkitemIdX(
Instruction &
I,
unsigned WaveSize)
const;
251 bool tryReplaceWithWorkitemId(
Instruction &
I,
unsigned Wave)
const;
287 if (!ExpandDiv64InIR)
291 StringRef getPassName()
const override {
return "AMDGPU IR optimizations"; }
296bool AMDGPUCodeGenPrepareImpl::run() {
297 BreakPhiNodesCache.clear();
298 bool MadeChange =
false;
310 while (!DeadVals.empty()) {
318bool AMDGPUCodeGenPrepareImpl::isLegalFloatingTy(
const Type *Ty)
const {
320 (Ty->
isHalfTy() && ST.has16BitInsts());
323bool AMDGPUCodeGenPrepareImpl::canWidenScalarExtLoad(LoadInst &
I)
const {
324 Type *Ty =
I.getType();
325 int TySize =
DL.getTypeSizeInBits(Ty);
326 Align Alignment =
DL.getValueOrABITypeAlignment(
I.getAlign(), Ty);
328 return I.isSimple() && TySize < 32 && Alignment >= 4 && UA.
isUniformAtDef(&
I);
332AMDGPUCodeGenPrepareImpl::numBitsUnsigned(
Value *
Op,
333 const Instruction *CtxI)
const {
338AMDGPUCodeGenPrepareImpl::numBitsSigned(
Value *
Op,
339 const Instruction *CtxI)
const {
351 for (
int I = 0,
E = VT->getNumElements();
I !=
E; ++
I)
352 Values.push_back(Builder.CreateExtractElement(V,
I));
358 if (!Ty->isVectorTy()) {
365 NewVal = Builder.CreateInsertElement(NewVal,
Values[
I],
I);
370bool AMDGPUCodeGenPrepareImpl::replaceMulWithMul24(BinaryOperator &
I)
const {
371 if (
I.getOpcode() != Instruction::Mul)
374 Type *Ty =
I.getType();
376 if (
Size <= 16 && ST.has16BitInsts())
386 Builder.SetCurrentDebugLocation(
I.getDebugLoc());
388 unsigned LHSBits = 0, RHSBits = 0;
389 bool IsSigned =
false;
391 if (ST.
hasMulU24() && (LHSBits = numBitsUnsigned(
LHS, &
I)) <= 24 &&
392 (RHSBits = numBitsUnsigned(
RHS, &
I)) <= 24) {
395 }
else if (ST.
hasMulI24() && (LHSBits = numBitsSigned(
LHS, &
I)) <= 24 &&
396 (RHSBits = numBitsSigned(
RHS, &
I)) <= 24) {
402 SmallVector<Value *, 4> LHSVals;
403 SmallVector<Value *, 4> RHSVals;
404 SmallVector<Value *, 4> ResultVals;
408 IntegerType *I32Ty = Builder.getInt32Ty();
409 IntegerType *IntrinTy =
Size > 32 ? Builder.getInt64Ty() : I32Ty;
410 Type *DstTy = LHSVals[0]->getType();
412 for (
int I = 0,
E = LHSVals.
size();
I !=
E; ++
I) {
413 Value *
LHS = IsSigned ? Builder.CreateSExtOrTrunc(LHSVals[
I], I32Ty)
414 : Builder.CreateZExtOrTrunc(LHSVals[
I], I32Ty);
415 Value *
RHS = IsSigned ? Builder.CreateSExtOrTrunc(RHSVals[
I], I32Ty)
416 : Builder.CreateZExtOrTrunc(RHSVals[
I], I32Ty);
418 IsSigned ? Intrinsic::amdgcn_mul_i24 : Intrinsic::amdgcn_mul_u24;
420 Result = IsSigned ? Builder.CreateSExtOrTrunc(Result, DstTy)
421 : Builder.CreateZExtOrTrunc(Result, DstTy);
427 I.replaceAllUsesWith(NewVal);
428 DeadVals.push_back(&
I);
448bool AMDGPUCodeGenPrepareImpl::foldBinOpIntoSelect(BinaryOperator &BO)
const {
469 if (!CBO || !CT || !CF)
496 Builder.setFastMathFlags(FPOp->getFastMathFlags());
502 DeadVals.push_back(&BO);
504 DeadVals.push_back(CastOp);
505 DeadVals.push_back(Sel);
509std::pair<Value *, Value *>
510AMDGPUCodeGenPrepareImpl::getFrexpResults(
IRBuilder<> &Builder,
512 Type *Ty = Src->getType();
525 : Builder.CreateExtractValue(Frexp, {1});
526 return {FrexpMant, FrexpExp};
532 bool IsNegative)
const {
547 auto [FrexpMant, FrexpExp] = getFrexpResults(Builder, Src);
550 return Builder.
CreateCall(getLdexpF32(), {Rcp, ScaleFactor});
556 FastMathFlags FMF)
const {
560 if (HasFP32DenormalFlush && ST.
hasFractBug() && !ST.hasFastFMAF32() &&
566 auto [FrexpMantRHS, FrexpExpRHS] = getFrexpResults(Builder,
RHS);
571 auto [FrexpMantLHS, FrexpExpLHS] = getFrexpResults(Builder,
LHS);
583 FastMathFlags FMF)
const {
584 Type *Ty = Src->getType();
588 Builder.
CreateFCmpOLT(Src, ConstantFP::get(Ty, SmallestNormal));
591 Value *InputScaleFactor =
598 Value *OutputScaleFactor =
600 return Builder.
CreateCall(getLdexpF32(), {Sqrt, OutputScaleFactor});
611 Type *Ty = Src->getType();
615 Builder.CreateFCmpOLT(Src, ConstantFP::get(Ty, SmallestNormal));
616 Constant *One = ConstantFP::get(Ty, 1.0);
617 Constant *InputScale = ConstantFP::get(Ty, 0x1.0p+24);
619 ConstantFP::get(Ty, IsNegative ? -0x1.0p+12 : 0x1.0p+12);
621 Value *InputScaleFactor = Builder.CreateSelect(NeedScale, InputScale, One);
623 Value *ScaledInput = Builder.CreateFMul(Src, InputScaleFactor);
624 Value *Rsq = Builder.CreateUnaryIntrinsic(Intrinsic::amdgcn_rsq, ScaledInput);
625 Value *OutputScaleFactor = Builder.CreateSelect(
626 NeedScale, OutputScale, IsNegative ? ConstantFP::get(Ty, -1.0) : One);
628 return Builder.CreateFMul(Rsq, OutputScaleFactor);
634 FastMathFlags SqrtFMF,
635 FastMathFlags DivFMF,
636 const Instruction *CtxI,
637 bool IsNegative)
const {
659 bool MaybePosInf = !SqrtFMF.
noInfs() && !DivFMF.
noInfs();
660 bool MaybeZero = !DivFMF.
noInfs();
662 DenormalMode DenormMode;
669 if (Interested !=
fcNone) {
674 DenormMode =
F.getDenormalMode(
X->getType()->getFltSemantics());
680 if (MaybeZero || MaybePosInf) {
682 if (MaybePosInf && MaybeZero) {
683 if (DenormMode.
Input != DenormalMode::DenormalModeKind::Dynamic) {
698 }
else if (MaybeZero) {
711 Value *
E = Builder.
CreateFMA(NegXY0, Y0, ConstantFP::get(
X->getType(), 1.0));
716 ConstantFP::get(
X->getType(), 0.5));
718 return Builder.
CreateFMA(Y0E, EFMA, IsNegative ? NegY0 : Y0);
721bool AMDGPUCodeGenPrepareImpl::canOptimizeWithRsq(FastMathFlags DivFMF,
722 FastMathFlags SqrtFMF)
const {
728Value *AMDGPUCodeGenPrepareImpl::optimizeWithRsq(
730 const FastMathFlags SqrtFMF,
const Instruction *CtxI)
const {
741 bool IsNegative =
false;
746 IRBuilder<>::FastMathFlagGuard Guard(Builder);
751 canIgnoreDenormalInput(Den, CtxI)) {
762 return emitRsqF64(Builder, Den, SqrtFMF, DivFMF, CtxI, IsNegative);
776 Value *Den, FastMathFlags FMF,
777 const Instruction *CtxI)
const {
784 bool IsNegative =
false;
788 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
809 return emitRcpIEEE1ULP(Builder, Src, IsNegative);
818 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
823 Value *Recip = emitRcpIEEE1ULP(Builder, Den,
false);
837Value *AMDGPUCodeGenPrepareImpl::optimizeWithFDivFast(
840 if (ReqdAccuracy < 2.5f)
846 bool NumIsOne =
false;
848 if (CNum->isOne() || CNum->isMinusOne())
856 if (!HasFP32DenormalFlush && !NumIsOne)
859 return Builder.
CreateIntrinsic(Intrinsic::amdgcn_fdiv_fast, {Num, Den});
862Value *AMDGPUCodeGenPrepareImpl::visitFDivElement(
864 FastMathFlags SqrtFMF,
Value *RsqOp,
const Instruction *FDivInst,
865 float ReqdDivAccuracy)
const {
868 optimizeWithRsq(Builder, Num, RsqOp, DivFMF, SqrtFMF, FDivInst);
876 Value *Rcp = optimizeWithRcp(Builder, Num, Den, DivFMF, FDivInst);
884 Value *FDivFast = optimizeWithFDivFast(Builder, Num, Den, ReqdDivAccuracy);
888 return emitFrexpDiv(Builder, Num, Den, DivFMF);
906bool AMDGPUCodeGenPrepareImpl::visitFDiv(BinaryOperator &FDiv) {
907 if (DisableFDivExpand)
922 FastMathFlags SqrtFMF;
927 Value *RsqOp =
nullptr;
929 if (DenII && DenII->getIntrinsicID() == Intrinsic::sqrt &&
930 DenII->hasOneUse()) {
932 SqrtFMF = SqrtOp->getFastMathFlags();
933 if (canOptimizeWithRsq(DivFMF, SqrtFMF))
934 RsqOp = SqrtOp->getOperand(0);
938 if (!IsFloat && !RsqOp)
950 const bool AllowInaccurateRcp = DivFMF.
approxFunc();
951 if (!RsqOp && AllowInaccurateRcp)
955 if (IsFloat && ReqdAccuracy < 1.0f)
962 SmallVector<Value *, 4> NumVals;
963 SmallVector<Value *, 4> DenVals;
964 SmallVector<Value *, 4> RsqDenVals;
971 SmallVector<Value *, 4> ResultVals(NumVals.
size());
972 for (
int I = 0,
E = NumVals.
size();
I !=
E; ++
I) {
973 Value *NumElt = NumVals[
I];
974 Value *DenElt = DenVals[
I];
975 Value *RsqDenElt = RsqOp ? RsqDenVals[
I] :
nullptr;
978 visitFDivElement(Builder, NumElt, DenElt, DivFMF, SqrtFMF, RsqDenElt,
987 NewEltInst->copyMetadata(FDiv);
990 ResultVals[
I] = NewElt;
998 DeadVals.push_back(&FDiv);
1009 Value *LHS_EXT64 = Builder.CreateZExt(
LHS, I64Ty);
1010 Value *RHS_EXT64 = Builder.CreateZExt(
RHS, I64Ty);
1011 Value *MUL64 = Builder.CreateMul(LHS_EXT64, RHS_EXT64);
1012 Value *
Lo = Builder.CreateTrunc(MUL64, I32Ty);
1013 Value *
Hi = Builder.CreateLShr(MUL64, Builder.getInt64(32));
1014 Hi = Builder.CreateTrunc(
Hi, I32Ty);
1015 return std::pair(
Lo,
Hi);
1026unsigned AMDGPUCodeGenPrepareImpl::getDivNumBits(BinaryOperator &
I,
Value *Num,
1028 unsigned MaxDivBits,
1029 bool IsSigned)
const {
1036 unsigned DivBits = SSBits - RHSSignBits + 1;
1037 if (DivBits > MaxDivBits)
1042 unsigned SignBits = std::min(LHSSignBits, RHSSignBits);
1043 DivBits = SSBits - SignBits + 1;
1050 unsigned RHSBits =
Known.countMaxActiveBits();
1051 if (RHSBits > MaxDivBits)
1055 unsigned LHSBits =
Known.countMaxActiveBits();
1057 unsigned DivBits = std::max(LHSBits, RHSBits);
1065 bool IsSigned)
const {
1066 unsigned DivBits = getDivNumBits(
I, Num, Den, 23, IsSigned);
1068 if (DivBits > (IsSigned ? 23 : 22))
1070 return expandDivRemToFloatImpl(Builder,
I, Num, Den, DivBits, IsDiv,
1074Value *AMDGPUCodeGenPrepareImpl::expandDivRemToFloatImpl(
1076 unsigned DivBits,
bool IsDiv,
bool IsSigned)
const {
1090 assert(0 < DivBits && DivBits <= (IsSigned ? 23 : 22) &&
1091 "abs(Num) must be <= 0x400000 for expandDivRemToFloatImpl to work "
1099 ConstantInt *One = Builder.
getInt32(1);
1157bool AMDGPUCodeGenPrepareImpl::divHasSpecialOptimization(BinaryOperator &
I,
1163 if (
C->getType()->getScalarSizeInBits() <= 32)
1179 if (BinOpDen->getOpcode() == Instruction::Shl &&
1193 if (
Known.isNegative())
1195 if (
Known.isNonNegative())
1197 return Builder.CreateAShr(V, Builder.getInt32(31));
1204 assert(
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1205 Opc == Instruction::SRem ||
Opc == Instruction::SDiv);
1211 if (divHasSpecialOptimization(
I,
X,
Y))
1214 bool IsDiv =
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv;
1215 bool IsSigned =
Opc == Instruction::SRem ||
Opc == Instruction::SDiv;
1217 Type *Ty =
X->getType();
1231 if (
Value *Res = expandDivRemToFloat(Builder,
I,
X,
Y, IsDiv, IsSigned)) {
1237 ConstantInt *One = Builder.
getInt32(1);
1239 Value *Sign =
nullptr;
1244 Sign = IsDiv ? Builder.
CreateXor(SignX, SignY) : SignX;
1325 BinaryOperator &
I,
Value *Num,
1327 if (!ExpandDiv64InIR && divHasSpecialOptimization(
I, Num, Den))
1332 bool IsDiv =
Opc == Instruction::SDiv ||
Opc == Instruction::UDiv;
1333 bool IsSigned =
Opc == Instruction::SDiv ||
Opc == Instruction::SRem;
1335 unsigned NumDivBits = getDivNumBits(
I, Num, Den, 32, IsSigned);
1336 if (NumDivBits > 32)
1339 Value *Narrowed =
nullptr;
1340 if (NumDivBits <= (IsSigned ? 23 : 22)) {
1341 Narrowed = expandDivRemToFloatImpl(Builder,
I, Num, Den, NumDivBits, IsDiv,
1343 }
else if (NumDivBits <= (IsSigned ? 31 : 32)) {
1348 Narrowed = expandDivRem32(Builder,
I, Num, Den);
1359void AMDGPUCodeGenPrepareImpl::expandDivRem64(BinaryOperator &
I)
const {
1362 if (
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv) {
1367 if (
Opc == Instruction::URem ||
Opc == Instruction::SRem) {
1387bool AMDGPUCodeGenPrepareImpl::tryNarrowMathIfNoOverflow(Instruction *
I) {
1388 unsigned Opc =
I->getOpcode();
1389 Type *OldType =
I->getType();
1391 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1396 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1398 "Instruction::Mul.");
1402 MaxBitsNeeded = std::max<unsigned>(
bit_ceil(MaxBitsNeeded), 8);
1403 Type *NewType =
DL.getSmallestLegalIntType(
I->getContext(), MaxBitsNeeded);
1407 if (NewBit >= OrigBit)
1418 int NumOfNonConstOps = 2;
1421 NumOfNonConstOps = 1;
1431 if (NewCost >= OldCost)
1442 DeadVals.push_back(
I);
1446bool AMDGPUCodeGenPrepareImpl::visitBinaryOperator(BinaryOperator &
I) {
1447 if (foldBinOpIntoSelect(
I))
1450 if (UseMul24Intrin && replaceMulWithMul24(
I))
1452 if (tryNarrowMathIfNoOverflow(&
I))
1457 Type *Ty =
I.getType();
1458 Value *NewDiv =
nullptr;
1463 if ((
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1464 Opc == Instruction::SRem ||
Opc == Instruction::SDiv) &&
1466 !DisableIDivExpand) {
1467 Value *Num =
I.getOperand(0);
1468 Value *Den =
I.getOperand(1);
1475 for (
unsigned N = 0,
E = VT->getNumElements();
N !=
E; ++
N) {
1480 if (ScalarSize <= 32) {
1481 NewElt = expandDivRem32(Builder,
I, NumEltN, DenEltN);
1487 NewElt = shrinkDivRem64(Builder,
I, NumEltN, DenEltN);
1501 NewEltI->copyIRFlags(&
I);
1506 if (ScalarSize <= 32)
1507 NewDiv = expandDivRem32(Builder,
I, Num, Den);
1509 NewDiv = shrinkDivRem64(Builder,
I, Num, Den);
1516 I.replaceAllUsesWith(NewDiv);
1517 DeadVals.push_back(&
I);
1522 if (ExpandDiv64InIR) {
1524 for (BinaryOperator *Div : Div64ToExpand) {
1525 expandDivRem64(*Div);
1534bool AMDGPUCodeGenPrepareImpl::visitLoadInst(LoadInst &
I) {
1540 canWidenScalarExtLoad(
I)) {
1551 if (
auto *
Range =
I.getMetadata(LLVMContext::MD_range)) {
1554 if (!
Lower->isNullValue()) {
1561 WidenLoad->setMetadata(LLVMContext::MD_range,
1566 int TySize =
DL.getTypeSizeInBits(
I.getType());
1571 DeadVals.push_back(&
I);
1578bool AMDGPUCodeGenPrepareImpl::visitSelectInst(SelectInst &
I) {
1584 Value *Fract =
nullptr;
1593 Value *FractSrc = matchFractPatImpl(*
X, *
C);
1598 Fract = applyFractPat(Builder, FractSrc);
1608 CmpPredicate IsNanPred;
1617 if (IsNanPred == FCmpInst::FCMP_UNO && TrueVal == CmpVal &&
1618 CmpVal == matchFractPatNanAvoidant(*FalseVal)) {
1620 Fract = applyFractPat(Builder, CmpVal);
1621 }
else if (IsNanPred == FCmpInst::FCMP_ORD && FalseVal == CmpVal) {
1622 if (CmpVal == matchFractPatNanAvoidant(*TrueVal)) {
1624 Fract = applyFractPat(Builder, CmpVal);
1628 CmpPredicate PredInf;
1634 PredInf != FCmpInst::FCMP_UNE ||
1635 CmpVal != matchFractPatNanAvoidant(*IfNotInf))
1645 Value *NewFract = applyFractPat(Builder, CmpVal);
1649 DeadVals.push_back(ClampInfSelect->
getOperand(1));
1653 Fract = ClampInfSelect;
1660 I.replaceAllUsesWith(Fract);
1661 DeadVals.push_back(&
I);
1668 return IA && IB && IA->getParent() == IB->getParent();
1678 const Value *CurVal = V;
1681 BitVector EltsCovered(FVT->getNumElements());
1688 if (!Idx || Idx->getZExtValue() >= FVT->getNumElements())
1691 const auto *VecSrc = IE->getOperand(0);
1700 EltsCovered.
set(Idx->getZExtValue());
1703 if (EltsCovered.
all())
1730 const auto [It, Inserted] = SeenPHIs.
insert(&
I);
1734 for (
const Value *Inc :
I.incoming_values()) {
1739 for (
const User *U :
I.users()) {
1745bool AMDGPUCodeGenPrepareImpl::canBreakPHINode(
const PHINode &
I) {
1747 if (
const auto It = BreakPhiNodesCache.find(&
I);
1748 It != BreakPhiNodesCache.end())
1757 SmallPtrSet<const PHINode *, 8> WorkList;
1763 for (
const PHINode *WLP : WorkList) {
1764 assert(BreakPhiNodesCache.count(WLP) == 0);
1779 const auto Threshold = (
alignTo(WorkList.size() * 2, 3) / 3);
1780 unsigned NumBreakablePHIs = 0;
1781 bool CanBreak =
false;
1782 for (
const PHINode *Cur : WorkList) {
1790 if (++NumBreakablePHIs >= Threshold) {
1797 for (
const PHINode *Cur : WorkList)
1798 BreakPhiNodesCache[Cur] = CanBreak;
1847 Value *&Res = SlicedVals[{BB, Inc}];
1853 B.SetCurrentDebugLocation(IncInst->getDebugLoc());
1859 Res =
B.CreateShuffleVector(Inc, Mask, NewValName);
1861 Res =
B.CreateExtractElement(Inc,
Idx, NewValName);
1870bool AMDGPUCodeGenPrepareImpl::visitPHINode(PHINode &
I) {
1882 cl::boolOrDefault::BOU_TRUE)
1887 DL.getTypeSizeInBits(FVT) <= BreakLargePHIsThreshold)
1890 if (!ForceBreakLargePHIs && !canBreakPHINode(
I))
1893 std::vector<VectorSlice> Slices;
1900 const unsigned EltSize =
DL.getTypeSizeInBits(EltTy);
1902 if (EltSize == 8 || EltSize == 16) {
1903 const unsigned SubVecSize = (32 / EltSize);
1905 for (
unsigned End =
alignDown(NumElts, SubVecSize); Idx < End;
1907 Slices.emplace_back(SubVecTy, Idx, SubVecSize);
1911 for (; Idx < NumElts; ++Idx)
1912 Slices.emplace_back(EltTy, Idx, 1);
1915 assert(Slices.size() > 1);
1921 B.SetCurrentDebugLocation(
I.getDebugLoc());
1923 unsigned IncNameSuffix = 0;
1924 for (VectorSlice &S : Slices) {
1927 B.SetInsertPoint(
I.getParent()->getFirstNonPHIIt());
1928 S.NewPHI =
B.CreatePHI(S.Ty,
I.getNumIncomingValues());
1930 for (
const auto &[Idx, BB] :
enumerate(
I.blocks())) {
1931 S.NewPHI->addIncoming(S.getSlicedVal(BB,
I.getIncomingValue(Idx),
1932 "largephi.extractslice" +
1933 std::to_string(IncNameSuffix++)),
1940 unsigned NameSuffix = 0;
1941 for (VectorSlice &S : Slices) {
1942 const auto ValName =
"largephi.insertslice" + std::to_string(NameSuffix++);
1944 Vec =
B.CreateInsertVector(FVT, Vec, S.NewPHI, S.Idx, ValName);
1946 Vec =
B.CreateInsertElement(Vec, S.NewPHI, S.Idx, ValName);
1949 I.replaceAllUsesWith(Vec);
1950 DeadVals.push_back(&
I);
1973 Load &&
Load->hasMetadata(LLVMContext::MD_nonnull))
1992 assert(SrcPtrKB.getBitWidth() ==
DL.getPointerSizeInBits(AS));
1993 assert((NullVal == 0 || NullVal == -1) &&
1994 "don't know how to check for this null value!");
1995 return NullVal ? !SrcPtrKB.getMaxValue().isAllOnes() : SrcPtrKB.isNonZero();
1998bool AMDGPUCodeGenPrepareImpl::visitAddrSpaceCastInst(AddrSpaceCastInst &
I) {
2002 if (
I.getType()->isVectorTy())
2007 const unsigned SrcAS =
I.getSrcAddressSpace();
2008 const unsigned DstAS =
I.getDestAddressSpace();
2010 bool CanLower =
false;
2028 auto *Intrin =
B.CreateIntrinsic(
2029 I.getType(), Intrinsic::amdgcn_addrspacecast_nonnull, {I.getOperand(0)});
2030 I.replaceAllUsesWith(Intrin);
2031 DeadVals.push_back(&
I);
2035bool AMDGPUCodeGenPrepareImpl::visitIntrinsicInst(IntrinsicInst &
I) {
2038 case Intrinsic::minnum:
2039 case Intrinsic::minimumnum:
2040 case Intrinsic::minimum:
2041 return visitFMinLike(
I);
2042 case Intrinsic::sqrt:
2043 return visitSqrt(
I);
2044 case Intrinsic::log:
2045 case Intrinsic::log10:
2047 case Intrinsic::log2:
2050 case Intrinsic::amdgcn_mbcnt_lo:
2051 return visitMbcntLo(
I);
2052 case Intrinsic::amdgcn_mbcnt_hi:
2053 return visitMbcntHi(
I);
2054 case Intrinsic::vector_reduce_add:
2055 return visitVectorReduceAdd(
I);
2056 case Intrinsic::uadd_sat:
2057 case Intrinsic::sadd_sat:
2058 return visitSaturatingAdd(
I);
2066Value *AMDGPUCodeGenPrepareImpl::matchFractPatImpl(
Value &FractSrc,
2067 const APFloat &
C)
const {
2076 OneNextDown.
next(
true);
2079 if (OneNextDown !=
C)
2099Value *AMDGPUCodeGenPrepareImpl::matchFractPatNanAvoidant(
Value &V) {
2111 return matchFractPatImpl(*Arg0, *
C);
2116 SmallVector<Value *, 4> FractVals;
2119 SmallVector<Value *, 4> ResultVals(FractVals.
size());
2122 for (
unsigned I = 0,
E = FractVals.
size();
I !=
E; ++
I) {
2130bool AMDGPUCodeGenPrepareImpl::visitFMinLike(IntrinsicInst &
I) {
2138 FractArg = matchFractPatImpl(*
X, *
C);
2143 FractArg = matchFractPatNanAvoidant(
I);
2155 FastMathFlags FMF =
I.getFastMathFlags();
2159 Value *Fract = applyFractPat(Builder, FractArg);
2161 I.replaceAllUsesWith(Fract);
2162 DeadVals.push_back(&
I);
2167bool AMDGPUCodeGenPrepareImpl::visitSqrt(IntrinsicInst &Sqrt) {
2183 if (ReqdAccuracy < 1.0f)
2187 bool CanTreatAsDAZ = canIgnoreDenormalInput(SrcVal, &Sqrt);
2191 if (!CanTreatAsDAZ && ReqdAccuracy < 2.0f)
2195 SmallVector<Value *, 4> SrcVals;
2198 SmallVector<Value *, 4> ResultVals(SrcVals.
size());
2199 for (
int I = 0,
E = SrcVals.
size();
I !=
E; ++
I) {
2201 ResultVals[
I] = Builder.
CreateCall(getSqrtF32(), SrcVals[
I]);
2203 ResultVals[
I] = emitSqrtIEEE2ULP(Builder, SrcVals[
I], SqrtFMF);
2209 DeadVals.push_back(&Sqrt);
2214bool AMDGPUCodeGenPrepareImpl::visitLog(FPMathOperator &Log,
2220 FastMathFlags FMF =
Log.getFastMathFlags();
2227 if (
Log.getFPAccuracy() < 1.80f)
2238 double Log2BaseInverted =
2245 Log.replaceAllUsesWith(
Mul);
2246 DeadVals.push_back(&Log);
2250bool AMDGPUCodeGenPrepare::runOnFunction(Function &
F) {
2251 if (skipFunction(
F))
2254 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
2258 const AMDGPUTargetMachine &TM = TPC->getTM<AMDGPUTargetMachine>();
2259 const TargetTransformInfo &
TTI =
2260 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
2261 const TargetLibraryInfo *TLI =
2262 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2263 AssumptionCache *AC =
2264 &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
2265 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
2266 const DominatorTree *DT = DTWP ? &DTWP->getDomTree() :
nullptr;
2268 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
2269 return AMDGPUCodeGenPrepareImpl(
F, TM,
TTI, TLI, AC, DT, UA).run();
2280 AMDGPUCodeGenPrepareImpl Impl(
F, ATM,
TTI, TLI, AC, DT, UA);
2284 if (!Impl.FlowChanged)
2290 "AMDGPU IR optimizations",
false,
false)
2301 B.CreateIntrinsicWithoutFolding(Intrinsic::amdgcn_workitem_id_x, {});
2302 ST.makeLIDRangeMetadata(Tid);
2307void AMDGPUCodeGenPrepareImpl::replaceWithWorkitemIdX(Instruction &
I)
const {
2309 CallInst *Tid = createWorkitemIdX(
B);
2315void AMDGPUCodeGenPrepareImpl::replaceWithMaskedWorkitemIdX(
2316 Instruction &
I,
unsigned WaveSize)
const {
2318 CallInst *Tid = createWorkitemIdX(
B);
2320 Value *AndInst =
B.CreateAnd(Tid, Mask);
2328bool AMDGPUCodeGenPrepareImpl::tryReplaceWithWorkitemId(Instruction &
I,
2329 unsigned Wave)
const {
2336 if (*MaybeX == Wave) {
2337 replaceWithWorkitemIdX(
I);
2344 replaceWithMaskedWorkitemIdX(
I, Wave);
2352bool AMDGPUCodeGenPrepareImpl::visitMbcntLo(IntrinsicInst &
I)
const {
2368bool AMDGPUCodeGenPrepareImpl::visitMbcntHi(IntrinsicInst &
I)
const {
2381 if (*MaybeX == Wave) {
2392 using namespace PatternMatch;
2400 return tryReplaceWithWorkitemId(
I, Wave);
2426 Value *ExtSrc0, *ExtSrc1;
2446bool AMDGPUCodeGenPrepareImpl::visitVectorReduceAdd(IntrinsicInst &
I) {
2448 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2451 Value *
A =
nullptr, *
B =
nullptr;
2454 bool IsSigned =
false;
2461 LLVMContext &Ctx =
I.getContext();
2462 Type *I32Ty = Type::getInt32Ty(Ctx);
2470 Value *Acc = ConstantInt::get(I32Ty, 0);
2474 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2479 I.replaceAllUsesWith(Dot);
2480 DeadVals.push_back(&
I);
2488bool AMDGPUCodeGenPrepareImpl::visitSaturatingAdd(IntrinsicInst &
I) {
2490 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2494 bool IsSigned = (IID == Intrinsic::sadd_sat);
2497 Value *Op0 =
I.getArgOperand(0);
2498 Value *Op1 =
I.getArgOperand(1);
2499 Value *MulOp =
nullptr;
2500 Value *Accum =
nullptr;
2501 IntrinsicInst *ReduceInst =
nullptr;
2506 }
else if (
match(Op1,
2514 Value *
A =
nullptr, *
B =
nullptr;
2519 LLVMContext &Ctx =
I.getContext();
2520 Type *I32Ty = Type::getInt32Ty(Ctx);
2531 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2536 I.replaceAllUsesWith(Dot);
2537 DeadVals.push_back(&
I);
2540 DeadVals.push_back(ReduceInst);
2545char AMDGPUCodeGenPrepare::ID = 0;
2548 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< 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)
This file implements a set that has insertion order iteration characteristics.
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 allowReciprocal() const
void setNoNaNs(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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
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)
cstfp_pred_ty< is_pos_zero_fp > m_PosZeroFP()
Match a floating-point positive zero.
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.
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