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;
747 IRBuilder<>::FastMathFlagGuard Guard(Builder);
748 FastMathFlags NewFMF = DivFMF | SqrtFMF;
755 canIgnoreDenormalInput(Den, CtxI)) {
766 return emitRsqF64(Builder, Den, SqrtFMF, DivFMF, CtxI, IsNegative);
780 Value *Den, FastMathFlags FMF,
781 const Instruction *CtxI)
const {
788 bool IsNegative =
false;
792 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
813 return emitRcpIEEE1ULP(Builder, Src, IsNegative);
822 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
827 Value *Recip = emitRcpIEEE1ULP(Builder, Den,
false);
841Value *AMDGPUCodeGenPrepareImpl::optimizeWithFDivFast(
844 if (ReqdAccuracy < 2.5f)
850 bool NumIsOne =
false;
852 if (CNum->isOne() || CNum->isMinusOne())
860 if (!HasFP32DenormalFlush && !NumIsOne)
863 return Builder.
CreateIntrinsic(Intrinsic::amdgcn_fdiv_fast, {Num, Den});
866Value *AMDGPUCodeGenPrepareImpl::visitFDivElement(
868 FastMathFlags SqrtFMF,
Value *RsqOp,
const Instruction *FDivInst,
869 float ReqdDivAccuracy)
const {
872 optimizeWithRsq(Builder, Num, RsqOp, DivFMF, SqrtFMF, FDivInst);
880 Value *Rcp = optimizeWithRcp(Builder, Num, Den, DivFMF, FDivInst);
888 Value *FDivFast = optimizeWithFDivFast(Builder, Num, Den, ReqdDivAccuracy);
892 return emitFrexpDiv(Builder, Num, Den, DivFMF);
910bool AMDGPUCodeGenPrepareImpl::visitFDiv(BinaryOperator &FDiv) {
911 if (DisableFDivExpand)
926 FastMathFlags SqrtFMF;
931 Value *RsqOp =
nullptr;
933 if (DenII && DenII->getIntrinsicID() == Intrinsic::sqrt &&
934 DenII->hasOneUse()) {
936 SqrtFMF = SqrtOp->getFastMathFlags();
937 if (canOptimizeWithRsq(DivFMF, SqrtFMF))
938 RsqOp = SqrtOp->getOperand(0);
942 if (!IsFloat && !RsqOp)
954 const bool AllowInaccurateRcp = DivFMF.
approxFunc();
955 if (!RsqOp && AllowInaccurateRcp)
959 if (IsFloat && ReqdAccuracy < 1.0f)
966 SmallVector<Value *, 4> NumVals;
967 SmallVector<Value *, 4> DenVals;
968 SmallVector<Value *, 4> RsqDenVals;
975 SmallVector<Value *, 4> ResultVals(NumVals.
size());
976 for (
int I = 0,
E = NumVals.
size();
I !=
E; ++
I) {
977 Value *NumElt = NumVals[
I];
978 Value *DenElt = DenVals[
I];
979 Value *RsqDenElt = RsqOp ? RsqDenVals[
I] :
nullptr;
982 visitFDivElement(Builder, NumElt, DenElt, DivFMF, SqrtFMF, RsqDenElt,
991 NewEltInst->copyMetadata(FDiv);
994 ResultVals[
I] = NewElt;
1002 DeadVals.push_back(&FDiv);
1013 Value *LHS_EXT64 = Builder.CreateZExt(
LHS, I64Ty);
1014 Value *RHS_EXT64 = Builder.CreateZExt(
RHS, I64Ty);
1015 Value *MUL64 = Builder.CreateMul(LHS_EXT64, RHS_EXT64);
1016 Value *
Lo = Builder.CreateTrunc(MUL64, I32Ty);
1017 Value *
Hi = Builder.CreateLShr(MUL64, Builder.getInt64(32));
1018 Hi = Builder.CreateTrunc(
Hi, I32Ty);
1019 return std::pair(
Lo,
Hi);
1030unsigned AMDGPUCodeGenPrepareImpl::getDivNumBits(BinaryOperator &
I,
Value *Num,
1032 unsigned MaxDivBits,
1033 bool IsSigned)
const {
1040 unsigned DivBits = SSBits - RHSSignBits + 1;
1041 if (DivBits > MaxDivBits)
1046 unsigned SignBits = std::min(LHSSignBits, RHSSignBits);
1047 DivBits = SSBits - SignBits + 1;
1054 unsigned RHSBits =
Known.countMaxActiveBits();
1055 if (RHSBits > MaxDivBits)
1059 unsigned LHSBits =
Known.countMaxActiveBits();
1061 unsigned DivBits = std::max(LHSBits, RHSBits);
1069 bool IsSigned)
const {
1070 unsigned DivBits = getDivNumBits(
I, Num, Den, 23, IsSigned);
1072 if (DivBits > (IsSigned ? 23 : 22))
1074 return expandDivRemToFloatImpl(Builder,
I, Num, Den, DivBits, IsDiv,
1078Value *AMDGPUCodeGenPrepareImpl::expandDivRemToFloatImpl(
1080 unsigned DivBits,
bool IsDiv,
bool IsSigned)
const {
1094 assert(0 < DivBits && DivBits <= (IsSigned ? 23 : 22) &&
1095 "abs(Num) must be <= 0x400000 for expandDivRemToFloatImpl to work "
1103 ConstantInt *One = Builder.
getInt32(1);
1161bool AMDGPUCodeGenPrepareImpl::divHasSpecialOptimization(BinaryOperator &
I,
1167 if (
C->getType()->getScalarSizeInBits() <= 32)
1183 if (BinOpDen->getOpcode() == Instruction::Shl &&
1197 if (
Known.isNegative())
1199 if (
Known.isNonNegative())
1201 return Builder.CreateAShr(V, Builder.getInt32(31));
1208 assert(
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1209 Opc == Instruction::SRem ||
Opc == Instruction::SDiv);
1215 if (divHasSpecialOptimization(
I,
X,
Y))
1218 bool IsDiv =
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv;
1219 bool IsSigned =
Opc == Instruction::SRem ||
Opc == Instruction::SDiv;
1221 Type *Ty =
X->getType();
1235 if (
Value *Res = expandDivRemToFloat(Builder,
I,
X,
Y, IsDiv, IsSigned)) {
1241 ConstantInt *One = Builder.
getInt32(1);
1243 Value *Sign =
nullptr;
1248 Sign = IsDiv ? Builder.
CreateXor(SignX, SignY) : SignX;
1329 BinaryOperator &
I,
Value *Num,
1331 if (!ExpandDiv64InIR && divHasSpecialOptimization(
I, Num, Den))
1336 bool IsDiv =
Opc == Instruction::SDiv ||
Opc == Instruction::UDiv;
1337 bool IsSigned =
Opc == Instruction::SDiv ||
Opc == Instruction::SRem;
1339 unsigned NumDivBits = getDivNumBits(
I, Num, Den, 32, IsSigned);
1340 if (NumDivBits > 32)
1343 Value *Narrowed =
nullptr;
1344 if (NumDivBits <= (IsSigned ? 23 : 22)) {
1345 Narrowed = expandDivRemToFloatImpl(Builder,
I, Num, Den, NumDivBits, IsDiv,
1347 }
else if (NumDivBits <= (IsSigned ? 31 : 32)) {
1352 Narrowed = expandDivRem32(Builder,
I, Num, Den);
1363void AMDGPUCodeGenPrepareImpl::expandDivRem64(BinaryOperator &
I)
const {
1366 if (
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv) {
1371 if (
Opc == Instruction::URem ||
Opc == Instruction::SRem) {
1391bool AMDGPUCodeGenPrepareImpl::tryNarrowMathIfNoOverflow(Instruction *
I) {
1392 unsigned Opc =
I->getOpcode();
1393 Type *OldType =
I->getType();
1395 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1400 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1402 "Instruction::Mul.");
1406 MaxBitsNeeded = std::max<unsigned>(
bit_ceil(MaxBitsNeeded), 8);
1407 Type *NewType =
DL.getSmallestLegalIntType(
I->getContext(), MaxBitsNeeded);
1411 if (NewBit >= OrigBit)
1422 int NumOfNonConstOps = 2;
1425 NumOfNonConstOps = 1;
1435 if (NewCost >= OldCost)
1446 DeadVals.push_back(
I);
1450bool AMDGPUCodeGenPrepareImpl::visitBinaryOperator(BinaryOperator &
I) {
1451 if (foldBinOpIntoSelect(
I))
1454 if (UseMul24Intrin && replaceMulWithMul24(
I))
1456 if (tryNarrowMathIfNoOverflow(&
I))
1461 Type *Ty =
I.getType();
1462 Value *NewDiv =
nullptr;
1467 if ((
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1468 Opc == Instruction::SRem ||
Opc == Instruction::SDiv) &&
1470 !DisableIDivExpand) {
1471 Value *Num =
I.getOperand(0);
1472 Value *Den =
I.getOperand(1);
1479 for (
unsigned N = 0,
E = VT->getNumElements();
N !=
E; ++
N) {
1484 if (ScalarSize <= 32) {
1485 NewElt = expandDivRem32(Builder,
I, NumEltN, DenEltN);
1491 NewElt = shrinkDivRem64(Builder,
I, NumEltN, DenEltN);
1505 NewEltI->copyIRFlags(&
I);
1510 if (ScalarSize <= 32)
1511 NewDiv = expandDivRem32(Builder,
I, Num, Den);
1513 NewDiv = shrinkDivRem64(Builder,
I, Num, Den);
1520 I.replaceAllUsesWith(NewDiv);
1521 DeadVals.push_back(&
I);
1526 if (ExpandDiv64InIR) {
1528 for (BinaryOperator *Div : Div64ToExpand) {
1529 expandDivRem64(*Div);
1538bool AMDGPUCodeGenPrepareImpl::visitLoadInst(LoadInst &
I) {
1544 canWidenScalarExtLoad(
I)) {
1555 if (
auto *
Range =
I.getMetadata(LLVMContext::MD_range)) {
1558 if (!
Lower->isNullValue()) {
1565 WidenLoad->setMetadata(LLVMContext::MD_range,
1570 int TySize =
DL.getTypeSizeInBits(
I.getType());
1575 DeadVals.push_back(&
I);
1582bool AMDGPUCodeGenPrepareImpl::visitSelectInst(SelectInst &
I) {
1588 Value *Fract =
nullptr;
1597 Value *FractSrc = matchFractPatImpl(*
X, *
C);
1602 Fract = applyFractPat(Builder, FractSrc);
1612 CmpPredicate IsNanPred;
1621 if (IsNanPred == FCmpInst::FCMP_UNO && TrueVal == CmpVal &&
1622 CmpVal == matchFractPatNanAvoidant(*FalseVal)) {
1624 Fract = applyFractPat(Builder, CmpVal);
1625 }
else if (IsNanPred == FCmpInst::FCMP_ORD && FalseVal == CmpVal) {
1626 if (CmpVal == matchFractPatNanAvoidant(*TrueVal)) {
1628 Fract = applyFractPat(Builder, CmpVal);
1632 CmpPredicate PredInf;
1638 PredInf != FCmpInst::FCMP_UNE ||
1639 CmpVal != matchFractPatNanAvoidant(*IfNotInf))
1649 Value *NewFract = applyFractPat(Builder, CmpVal);
1653 DeadVals.push_back(ClampInfSelect->
getOperand(1));
1657 Fract = ClampInfSelect;
1664 I.replaceAllUsesWith(Fract);
1665 DeadVals.push_back(&
I);
1672 return IA && IB && IA->getParent() == IB->getParent();
1682 const Value *CurVal = V;
1685 BitVector EltsCovered(FVT->getNumElements());
1692 if (!Idx || Idx->getZExtValue() >= FVT->getNumElements())
1695 const auto *VecSrc = IE->getOperand(0);
1704 EltsCovered.
set(Idx->getZExtValue());
1707 if (EltsCovered.
all())
1734 const auto [It, Inserted] = SeenPHIs.
insert(&
I);
1738 for (
const Value *Inc :
I.incoming_values()) {
1743 for (
const User *U :
I.users()) {
1749bool AMDGPUCodeGenPrepareImpl::canBreakPHINode(
const PHINode &
I) {
1751 if (
const auto It = BreakPhiNodesCache.find(&
I);
1752 It != BreakPhiNodesCache.end())
1761 SmallPtrSet<const PHINode *, 8> WorkList;
1767 for (
const PHINode *WLP : WorkList) {
1768 assert(BreakPhiNodesCache.count(WLP) == 0);
1783 const auto Threshold = (
alignTo(WorkList.size() * 2, 3) / 3);
1784 unsigned NumBreakablePHIs = 0;
1785 bool CanBreak =
false;
1786 for (
const PHINode *Cur : WorkList) {
1794 if (++NumBreakablePHIs >= Threshold) {
1801 for (
const PHINode *Cur : WorkList)
1802 BreakPhiNodesCache[Cur] = CanBreak;
1851 Value *&Res = SlicedVals[{BB, Inc}];
1857 B.SetCurrentDebugLocation(IncInst->getDebugLoc());
1863 Res =
B.CreateShuffleVector(Inc, Mask, NewValName);
1865 Res =
B.CreateExtractElement(Inc,
Idx, NewValName);
1874bool AMDGPUCodeGenPrepareImpl::visitPHINode(PHINode &
I) {
1886 cl::boolOrDefault::BOU_TRUE)
1891 DL.getTypeSizeInBits(FVT) <= BreakLargePHIsThreshold)
1894 if (!ForceBreakLargePHIs && !canBreakPHINode(
I))
1897 std::vector<VectorSlice> Slices;
1904 const unsigned EltSize =
DL.getTypeSizeInBits(EltTy);
1906 if (EltSize == 8 || EltSize == 16) {
1907 const unsigned SubVecSize = (32 / EltSize);
1909 for (
unsigned End =
alignDown(NumElts, SubVecSize); Idx < End;
1911 Slices.emplace_back(SubVecTy, Idx, SubVecSize);
1915 for (; Idx < NumElts; ++Idx)
1916 Slices.emplace_back(EltTy, Idx, 1);
1919 assert(Slices.size() > 1);
1925 B.SetCurrentDebugLocation(
I.getDebugLoc());
1927 unsigned IncNameSuffix = 0;
1928 for (VectorSlice &S : Slices) {
1931 B.SetInsertPoint(
I.getParent()->getFirstNonPHIIt());
1932 S.NewPHI =
B.CreatePHI(S.Ty,
I.getNumIncomingValues());
1934 for (
const auto &[Idx, BB] :
enumerate(
I.blocks())) {
1935 S.NewPHI->addIncoming(S.getSlicedVal(BB,
I.getIncomingValue(Idx),
1936 "largephi.extractslice" +
1937 std::to_string(IncNameSuffix++)),
1944 unsigned NameSuffix = 0;
1945 for (VectorSlice &S : Slices) {
1946 const auto ValName =
"largephi.insertslice" + std::to_string(NameSuffix++);
1948 Vec =
B.CreateInsertVector(FVT, Vec, S.NewPHI, S.Idx, ValName);
1950 Vec =
B.CreateInsertElement(Vec, S.NewPHI, S.Idx, ValName);
1953 I.replaceAllUsesWith(Vec);
1954 DeadVals.push_back(&
I);
1977 Load &&
Load->hasMetadata(LLVMContext::MD_nonnull))
1996 assert(SrcPtrKB.getBitWidth() ==
DL.getPointerSizeInBits(AS));
1997 assert((NullVal == 0 || NullVal == -1) &&
1998 "don't know how to check for this null value!");
1999 return NullVal ? !SrcPtrKB.getMaxValue().isAllOnes() : SrcPtrKB.isNonZero();
2002bool AMDGPUCodeGenPrepareImpl::visitAddrSpaceCastInst(AddrSpaceCastInst &
I) {
2006 if (
I.getType()->isVectorTy())
2011 const unsigned SrcAS =
I.getSrcAddressSpace();
2012 const unsigned DstAS =
I.getDestAddressSpace();
2014 bool CanLower =
false;
2032 auto *Intrin =
B.CreateIntrinsic(
2033 I.getType(), Intrinsic::amdgcn_addrspacecast_nonnull, {I.getOperand(0)});
2034 I.replaceAllUsesWith(Intrin);
2035 DeadVals.push_back(&
I);
2039bool AMDGPUCodeGenPrepareImpl::visitIntrinsicInst(IntrinsicInst &
I) {
2042 case Intrinsic::minnum:
2043 case Intrinsic::minimumnum:
2044 case Intrinsic::minimum:
2045 return visitFMinLike(
I);
2046 case Intrinsic::sqrt:
2047 return visitSqrt(
I);
2048 case Intrinsic::log:
2049 case Intrinsic::log10:
2051 case Intrinsic::log2:
2054 case Intrinsic::amdgcn_mbcnt_lo:
2055 return visitMbcntLo(
I);
2056 case Intrinsic::amdgcn_mbcnt_hi:
2057 return visitMbcntHi(
I);
2058 case Intrinsic::vector_reduce_add:
2059 return visitVectorReduceAdd(
I);
2060 case Intrinsic::uadd_sat:
2061 case Intrinsic::sadd_sat:
2062 return visitSaturatingAdd(
I);
2070Value *AMDGPUCodeGenPrepareImpl::matchFractPatImpl(
Value &FractSrc,
2071 const APFloat &
C)
const {
2080 OneNextDown.
next(
true);
2083 if (OneNextDown !=
C)
2103Value *AMDGPUCodeGenPrepareImpl::matchFractPatNanAvoidant(
Value &V) {
2115 return matchFractPatImpl(*Arg0, *
C);
2120 SmallVector<Value *, 4> FractVals;
2123 SmallVector<Value *, 4> ResultVals(FractVals.
size());
2126 for (
unsigned I = 0,
E = FractVals.
size();
I !=
E; ++
I) {
2134bool AMDGPUCodeGenPrepareImpl::visitFMinLike(IntrinsicInst &
I) {
2142 FractArg = matchFractPatImpl(*
X, *
C);
2147 FractArg = matchFractPatNanAvoidant(
I);
2159 FastMathFlags FMF =
I.getFastMathFlags();
2163 Value *Fract = applyFractPat(Builder, FractArg);
2165 I.replaceAllUsesWith(Fract);
2166 DeadVals.push_back(&
I);
2171bool AMDGPUCodeGenPrepareImpl::visitSqrt(IntrinsicInst &Sqrt) {
2187 if (ReqdAccuracy < 1.0f)
2191 bool CanTreatAsDAZ = canIgnoreDenormalInput(SrcVal, &Sqrt);
2195 if (!CanTreatAsDAZ && ReqdAccuracy < 2.0f)
2199 SmallVector<Value *, 4> SrcVals;
2202 SmallVector<Value *, 4> ResultVals(SrcVals.
size());
2203 for (
int I = 0,
E = SrcVals.
size();
I !=
E; ++
I) {
2205 ResultVals[
I] = Builder.
CreateCall(getSqrtF32(), SrcVals[
I]);
2207 ResultVals[
I] = emitSqrtIEEE2ULP(Builder, SrcVals[
I], SqrtFMF);
2213 DeadVals.push_back(&Sqrt);
2218bool AMDGPUCodeGenPrepareImpl::visitLog(FPMathOperator &Log,
2224 FastMathFlags FMF =
Log.getFastMathFlags();
2231 if (
Log.getFPAccuracy() < 1.80f)
2242 double Log2BaseInverted =
2249 Log.replaceAllUsesWith(
Mul);
2250 DeadVals.push_back(&Log);
2254bool AMDGPUCodeGenPrepare::runOnFunction(
Function &
F) {
2255 if (skipFunction(
F))
2258 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
2262 const AMDGPUTargetMachine &TM = TPC->getTM<AMDGPUTargetMachine>();
2263 const TargetTransformInfo &
TTI =
2264 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
2265 const TargetLibraryInfo *TLI =
2266 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2267 AssumptionCache *AC =
2268 &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
2269 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
2270 const DominatorTree *DT = DTWP ? &DTWP->getDomTree() :
nullptr;
2272 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
2273 return AMDGPUCodeGenPrepareImpl(
F, TM,
TTI, TLI, AC, DT, UA).run();
2284 AMDGPUCodeGenPrepareImpl Impl(
F, ATM,
TTI, TLI, AC, DT, UA);
2288 if (!Impl.FlowChanged)
2294 "AMDGPU IR optimizations",
false,
false)
2305 B.CreateIntrinsicWithoutFolding(Intrinsic::amdgcn_workitem_id_x, {});
2306 ST.makeLIDRangeMetadata(Tid);
2311void AMDGPUCodeGenPrepareImpl::replaceWithWorkitemIdX(Instruction &
I)
const {
2313 CallInst *Tid = createWorkitemIdX(
B);
2319void AMDGPUCodeGenPrepareImpl::replaceWithMaskedWorkitemIdX(
2320 Instruction &
I,
unsigned WaveSize)
const {
2322 CallInst *Tid = createWorkitemIdX(
B);
2324 Value *AndInst =
B.CreateAnd(Tid, Mask);
2332bool AMDGPUCodeGenPrepareImpl::tryReplaceWithWorkitemId(Instruction &
I,
2333 unsigned Wave)
const {
2340 if (*MaybeX == Wave) {
2341 replaceWithWorkitemIdX(
I);
2348 replaceWithMaskedWorkitemIdX(
I, Wave);
2356bool AMDGPUCodeGenPrepareImpl::visitMbcntLo(IntrinsicInst &
I)
const {
2372bool AMDGPUCodeGenPrepareImpl::visitMbcntHi(IntrinsicInst &
I)
const {
2385 if (*MaybeX == Wave) {
2396 using namespace PatternMatch;
2404 return tryReplaceWithWorkitemId(
I, Wave);
2430 Value *ExtSrc0, *ExtSrc1;
2450bool AMDGPUCodeGenPrepareImpl::visitVectorReduceAdd(IntrinsicInst &
I) {
2452 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2455 Value *
A =
nullptr, *
B =
nullptr;
2458 bool IsSigned =
false;
2465 LLVMContext &Ctx =
I.getContext();
2466 Type *I32Ty = Type::getInt32Ty(Ctx);
2474 Value *Acc = ConstantInt::get(I32Ty, 0);
2478 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2483 I.replaceAllUsesWith(Dot);
2484 DeadVals.push_back(&
I);
2492bool AMDGPUCodeGenPrepareImpl::visitSaturatingAdd(IntrinsicInst &
I) {
2494 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2498 bool IsSigned = (IID == Intrinsic::sadd_sat);
2501 Value *Op0 =
I.getArgOperand(0);
2502 Value *Op1 =
I.getArgOperand(1);
2503 Value *MulOp =
nullptr;
2504 Value *Accum =
nullptr;
2505 IntrinsicInst *ReduceInst =
nullptr;
2510 }
else if (
match(Op1,
2518 Value *
A =
nullptr, *
B =
nullptr;
2523 LLVMContext &Ctx =
I.getContext();
2524 Type *I32Ty = Type::getInt32Ty(Ctx);
2535 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2540 I.replaceAllUsesWith(Dot);
2541 DeadVals.push_back(&
I);
2544 DeadVals.push_back(ReduceInst);
2549char AMDGPUCodeGenPrepare::ID = 0;
2552 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)
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 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