29#include "llvm/IR/IntrinsicsAMDGPU.h"
39#define DEBUG_TYPE "amdgpu-codegenprepare"
46class AMDGPUCodeGenPrepareImpl
47 :
public InstVisitor<AMDGPUCodeGenPrepareImpl, bool> {
49 const AMDGPUOptions &CLOpts;
58 const bool HasFP32DenormalFlush;
59 const bool ExpandDiv64InIR;
60 bool FlowChanged =
false;
62 mutable Function *LdexpF32 =
nullptr;
77 ExpandDiv64InIR(ExpandDiv64InIR) {}
85 F.getParent(), Intrinsic::amdgcn_sqrt, {Type::getFloatTy(Ctx)});
95 F.getParent(), Intrinsic::ldexp,
96 {Type::getFloatTy(Ctx), Type::getInt32Ty(Ctx)});
100 bool canBreakPHINode(
const PHINode &
I);
103 bool isLegalFloatingTy(
const Type *
T)
const;
113 return HasFP32DenormalFlush ||
138 unsigned MaxDivBits,
bool Signed)
const;
144 bool IsSigned)
const;
148 bool IsDiv,
bool IsSigned)
const;
166 bool canWidenScalarExtLoad(
LoadInst &
I)
const;
181 float ReqdAccuracy)
const;
186 float ReqdAccuracy)
const;
188 std::pair<Value *, Value *> getFrexpResults(
IRBuilder<> &Builder,
192 bool IsNegative)
const;
199 bool IsNegative)
const;
203 void replaceWithMaskedWorkitemIdX(
Instruction &
I,
unsigned WaveSize)
const;
204 bool tryReplaceWithWorkitemId(
Instruction &
I,
unsigned Wave)
const;
232 explicit AMDGPUCodeGenPrepare(
bool ExpandDiv64InIR =
false)
241 if (!ExpandDiv64InIR)
245 StringRef getPassName()
const override {
return "AMDGPU IR optimizations"; }
248 bool ExpandDiv64InIR;
253bool AMDGPUCodeGenPrepareImpl::run() {
254 BreakPhiNodesCache.clear();
255 bool MadeChange =
false;
267 while (!DeadVals.empty()) {
275bool AMDGPUCodeGenPrepareImpl::isLegalFloatingTy(
const Type *Ty)
const {
277 (Ty->
isHalfTy() && ST.has16BitInsts());
280bool AMDGPUCodeGenPrepareImpl::canWidenScalarExtLoad(LoadInst &
I)
const {
281 Type *Ty =
I.getType();
282 int TySize =
DL.getTypeSizeInBits(Ty);
285 return I.isSimple() && TySize < 32 && Alignment >= 4 && UA.
isUniformAtDef(&
I);
289AMDGPUCodeGenPrepareImpl::numBitsUnsigned(
Value *
Op,
290 const Instruction *CtxI)
const {
295AMDGPUCodeGenPrepareImpl::numBitsSigned(
Value *
Op,
296 const Instruction *CtxI)
const {
308 for (
int I = 0,
E = VT->getNumElements();
I !=
E; ++
I)
309 Values.push_back(Builder.CreateExtractElement(
V,
I));
315 if (!Ty->isVectorTy()) {
322 NewVal = Builder.CreateInsertElement(NewVal,
Values[
I],
I);
327bool AMDGPUCodeGenPrepareImpl::replaceMulWithMul24(BinaryOperator &
I)
const {
328 if (
I.getOpcode() != Instruction::Mul)
331 Type *Ty =
I.getType();
333 if (
Size <= 16 && ST.has16BitInsts())
343 Builder.SetCurrentDebugLocation(
I.getDebugLoc());
345 unsigned LHSBits = 0, RHSBits = 0;
346 bool IsSigned =
false;
348 if (ST.
hasMulU24() && (LHSBits = numBitsUnsigned(
LHS, &
I)) <= 24 &&
349 (RHSBits = numBitsUnsigned(
RHS, &
I)) <= 24) {
352 }
else if (ST.
hasMulI24() && (LHSBits = numBitsSigned(
LHS, &
I)) <= 24 &&
353 (RHSBits = numBitsSigned(
RHS, &
I)) <= 24) {
359 SmallVector<Value *, 4> LHSVals;
360 SmallVector<Value *, 4> RHSVals;
361 SmallVector<Value *, 4> ResultVals;
365 IntegerType *I32Ty = Builder.getInt32Ty();
366 IntegerType *IntrinTy =
Size > 32 ? Builder.getInt64Ty() : I32Ty;
367 Type *DstTy = LHSVals[0]->getType();
369 for (
int I = 0,
E = LHSVals.
size();
I !=
E; ++
I) {
370 Value *
LHS = IsSigned ? Builder.CreateSExtOrTrunc(LHSVals[
I], I32Ty)
371 : Builder.CreateZExtOrTrunc(LHSVals[
I], I32Ty);
372 Value *
RHS = IsSigned ? Builder.CreateSExtOrTrunc(RHSVals[
I], I32Ty)
373 : Builder.CreateZExtOrTrunc(RHSVals[
I], I32Ty);
375 IsSigned ? Intrinsic::amdgcn_mul_i24 : Intrinsic::amdgcn_mul_u24;
377 Result = IsSigned ? Builder.CreateSExtOrTrunc(Result, DstTy)
378 : Builder.CreateZExtOrTrunc(Result, DstTy);
384 I.replaceAllUsesWith(NewVal);
385 DeadVals.push_back(&
I);
405bool AMDGPUCodeGenPrepareImpl::foldBinOpIntoSelect(BinaryOperator &BO)
const {
426 if (!CBO || !CT || !CF)
453 Builder.setFastMathFlags(FPOp->getFastMathFlags());
459 DeadVals.push_back(&BO);
461 DeadVals.push_back(CastOp);
462 DeadVals.push_back(Sel);
466std::pair<Value *, Value *>
467AMDGPUCodeGenPrepareImpl::getFrexpResults(
IRBuilder<> &Builder,
469 Type *Ty = Src->getType();
482 : Builder.CreateExtractValue(Frexp, {1});
483 return {FrexpMant, FrexpExp};
489 bool IsNegative)
const {
504 auto [FrexpMant, FrexpExp] = getFrexpResults(Builder, Src);
507 return Builder.
CreateCall(getLdexpF32(), {Rcp, ScaleFactor});
513 FastMathFlags FMF)
const {
517 if (HasFP32DenormalFlush && ST.
hasFractBug() && !ST.hasFastFMAF32() &&
523 auto [FrexpMantRHS, FrexpExpRHS] = getFrexpResults(Builder,
RHS);
528 auto [FrexpMantLHS, FrexpExpLHS] = getFrexpResults(Builder,
LHS);
540 FastMathFlags FMF)
const {
541 Type *Ty = Src->getType();
545 Builder.
CreateFCmpOLT(Src, ConstantFP::get(Ty, SmallestNormal));
548 Value *InputScaleFactor =
555 Value *OutputScaleFactor =
557 return Builder.
CreateCall(getLdexpF32(), {Sqrt, OutputScaleFactor});
568 Type *Ty = Src->getType();
572 Builder.CreateFCmpOLT(Src, ConstantFP::get(Ty, SmallestNormal));
573 Constant *One = ConstantFP::get(Ty, 1.0);
574 Constant *InputScale = ConstantFP::get(Ty, 0x1.0p+24);
576 ConstantFP::get(Ty, IsNegative ? -0x1.0p+12 : 0x1.0p+12);
578 Value *InputScaleFactor = Builder.CreateSelect(NeedScale, InputScale, One);
580 Value *ScaledInput = Builder.CreateFMul(Src, InputScaleFactor);
581 Value *Rsq = Builder.CreateUnaryIntrinsic(Intrinsic::amdgcn_rsq, ScaledInput);
582 Value *OutputScaleFactor = Builder.CreateSelect(
583 NeedScale, OutputScale, IsNegative ? ConstantFP::get(Ty, -1.0) : One);
585 return Builder.CreateFMul(Rsq, OutputScaleFactor);
591 FastMathFlags SqrtFMF,
592 FastMathFlags DivFMF,
593 const Instruction *CtxI,
594 bool IsNegative)
const {
616 bool MaybePosInf = !SqrtFMF.
noInfs() && !DivFMF.
noInfs();
617 bool MaybeZero = !DivFMF.
noInfs();
619 DenormalMode DenormMode;
626 if (Interested !=
fcNone) {
631 DenormMode =
F.getDenormalMode(
X->getType()->getFltSemantics());
637 if (MaybeZero || MaybePosInf) {
639 if (MaybePosInf && MaybeZero) {
640 if (DenormMode.
Input != DenormalMode::DenormalModeKind::Dynamic) {
655 }
else if (MaybeZero) {
668 Value *
E = Builder.
CreateFMA(NegXY0, Y0, ConstantFP::get(
X->getType(), 1.0));
673 ConstantFP::get(
X->getType(), 0.5));
675 return Builder.
CreateFMA(Y0E, EFMA, IsNegative ? NegY0 : Y0);
678bool AMDGPUCodeGenPrepareImpl::canOptimizeWithRsq(FastMathFlags DivFMF,
679 FastMathFlags SqrtFMF)
const {
685Value *AMDGPUCodeGenPrepareImpl::optimizeWithRsq(
687 const FastMathFlags SqrtFMF,
const Instruction *CtxI)
const {
698 bool IsNegative =
false;
704 IRBuilder<>::FastMathFlagGuard Guard(Builder);
705 FastMathFlags NewFMF = DivFMF | SqrtFMF;
713 canIgnoreDenormalInput(Den, CtxI)) {
724 return emitRsqF64(Builder, Den, SqrtFMF, DivFMF, CtxI, IsNegative);
738 Value *Den, FastMathFlags FMF,
739 const Instruction *CtxI)
const {
746 bool IsNegative =
false;
750 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
771 return emitRcpIEEE1ULP(Builder, Src, IsNegative);
780 if (HasFP32DenormalFlush || FMF.
approxFunc()) {
785 Value *Recip = emitRcpIEEE1ULP(Builder, Den,
false);
799Value *AMDGPUCodeGenPrepareImpl::optimizeWithFDivFast(
802 if (ReqdAccuracy < 2.5f)
808 bool NumIsOne =
false;
810 if (CNum->isOne() || CNum->isMinusOne())
818 if (!HasFP32DenormalFlush && !NumIsOne)
821 return Builder.
CreateIntrinsic(Intrinsic::amdgcn_fdiv_fast, {Num, Den});
824Value *AMDGPUCodeGenPrepareImpl::visitFDivElement(
826 FastMathFlags SqrtFMF,
Value *RsqOp,
const Instruction *FDivInst,
827 float ReqdDivAccuracy)
const {
830 optimizeWithRsq(Builder, Num, RsqOp, DivFMF, SqrtFMF, FDivInst);
838 Value *Rcp = optimizeWithRcp(Builder, Num, Den, DivFMF, FDivInst);
846 Value *FDivFast = optimizeWithFDivFast(Builder, Num, Den, ReqdDivAccuracy);
850 return emitFrexpDiv(Builder, Num, Den, DivFMF);
868bool AMDGPUCodeGenPrepareImpl::visitFDiv(BinaryOperator &FDiv) {
869 if (!CLOpts.codegenprepare_fdiv_expansion)
884 FastMathFlags SqrtFMF;
889 Value *RsqOp =
nullptr;
891 if (DenII && DenII->getIntrinsicID() == Intrinsic::sqrt &&
892 DenII->hasOneUse()) {
894 SqrtFMF = SqrtOp->getFastMathFlags();
895 if (canOptimizeWithRsq(DivFMF, SqrtFMF))
896 RsqOp = SqrtOp->getOperand(0);
900 if (!IsFloat && !RsqOp)
912 const bool AllowInaccurateRcp = DivFMF.
approxFunc();
913 if (!RsqOp && AllowInaccurateRcp)
917 if (IsFloat && ReqdAccuracy < 1.0f)
924 SmallVector<Value *, 4> NumVals;
925 SmallVector<Value *, 4> DenVals;
926 SmallVector<Value *, 4> RsqDenVals;
933 SmallVector<Value *, 4> ResultVals(NumVals.
size());
934 for (
int I = 0,
E = NumVals.
size();
I !=
E; ++
I) {
935 Value *NumElt = NumVals[
I];
936 Value *DenElt = DenVals[
I];
937 Value *RsqDenElt = RsqOp ? RsqDenVals[
I] :
nullptr;
940 visitFDivElement(Builder, NumElt, DenElt, DivFMF, SqrtFMF, RsqDenElt,
949 NewEltInst->copyMetadata(FDiv);
952 ResultVals[
I] = NewElt;
960 DeadVals.push_back(&FDiv);
971 Value *LHS_EXT64 = Builder.CreateZExt(
LHS, I64Ty);
972 Value *RHS_EXT64 = Builder.CreateZExt(
RHS, I64Ty);
973 Value *MUL64 = Builder.CreateMul(LHS_EXT64, RHS_EXT64);
974 Value *
Lo = Builder.CreateTrunc(MUL64, I32Ty);
975 Value *
Hi = Builder.CreateLShr(MUL64, Builder.getInt64(32));
976 Hi = Builder.CreateTrunc(
Hi, I32Ty);
977 return std::pair(
Lo,
Hi);
988unsigned AMDGPUCodeGenPrepareImpl::getDivNumBits(BinaryOperator &
I,
Value *Num,
991 bool IsSigned)
const {
998 unsigned DivBits = SSBits - RHSSignBits + 1;
999 if (DivBits > MaxDivBits)
1004 unsigned SignBits = std::min(LHSSignBits, RHSSignBits);
1005 DivBits = SSBits - SignBits + 1;
1012 unsigned RHSBits =
Known.countMaxActiveBits();
1013 if (RHSBits > MaxDivBits)
1017 unsigned LHSBits =
Known.countMaxActiveBits();
1019 unsigned DivBits = std::max(LHSBits, RHSBits);
1027 bool IsSigned)
const {
1028 unsigned DivBits = getDivNumBits(
I, Num, Den, 23, IsSigned);
1030 if (DivBits > (IsSigned ? 23u : 22u))
1032 return expandDivRemToFloatImpl(Builder,
I, Num, Den, DivBits, IsDiv,
1036Value *AMDGPUCodeGenPrepareImpl::expandDivRemToFloatImpl(
1038 unsigned DivBits,
bool IsDiv,
bool IsSigned)
const {
1052 assert(0 < DivBits && DivBits <= (IsSigned ? 23u : 22u) &&
1053 "abs(Num) must be <= 0x400000 for expandDivRemToFloatImpl to work "
1061 ConstantInt *One = Builder.
getInt32(1);
1119bool AMDGPUCodeGenPrepareImpl::divHasSpecialOptimization(BinaryOperator &
I,
1125 if (
C->getType()->getScalarSizeInBits() <= 32)
1141 if (BinOpDen->getOpcode() == Instruction::Shl &&
1155 if (
Known.isNegative())
1157 if (
Known.isNonNegative())
1159 return Builder.CreateAShr(
V, Builder.getInt32(31));
1166 assert(
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1167 Opc == Instruction::SRem ||
Opc == Instruction::SDiv);
1173 if (divHasSpecialOptimization(
I,
X,
Y))
1176 bool IsDiv =
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv;
1177 bool IsSigned =
Opc == Instruction::SRem ||
Opc == Instruction::SDiv;
1179 Type *Ty =
X->getType();
1193 if (
Value *Res = expandDivRemToFloat(Builder,
I,
X,
Y, IsDiv, IsSigned)) {
1199 ConstantInt *One = Builder.
getInt32(1);
1287 BinaryOperator &
I,
Value *Num,
1289 if (!ExpandDiv64InIR && divHasSpecialOptimization(
I, Num, Den))
1294 bool IsDiv =
Opc == Instruction::SDiv ||
Opc == Instruction::UDiv;
1295 bool IsSigned =
Opc == Instruction::SDiv ||
Opc == Instruction::SRem;
1297 unsigned NumDivBits = getDivNumBits(
I, Num, Den, 32, IsSigned);
1298 if (NumDivBits > 32)
1301 Value *Narrowed =
nullptr;
1302 if (NumDivBits <= (IsSigned ? 23u : 22u)) {
1303 Narrowed = expandDivRemToFloatImpl(Builder,
I, Num, Den, NumDivBits, IsDiv,
1305 }
else if (NumDivBits <= (IsSigned ? 31u : 32u)) {
1310 Narrowed = expandDivRem32(Builder,
I, Num, Den);
1321void AMDGPUCodeGenPrepareImpl::expandDivRem64(BinaryOperator &
I)
const {
1324 if (
Opc == Instruction::UDiv ||
Opc == Instruction::SDiv) {
1329 if (
Opc == Instruction::URem ||
Opc == Instruction::SRem) {
1349bool AMDGPUCodeGenPrepareImpl::tryNarrowMathIfNoOverflow(Instruction *
I) {
1350 unsigned Opc =
I->getOpcode();
1352 if (
Opc != Instruction::Add &&
Opc != Instruction::Mul)
1355 Type *OldType =
I->getType();
1359 MaxBitsNeeded = std::max<unsigned>(
bit_ceil(MaxBitsNeeded), 8);
1360 Type *NewType =
DL.getSmallestLegalIntType(
I->getContext(), MaxBitsNeeded);
1364 if (NewBit >= OrigBit)
1375 int NumOfNonConstOps = 2;
1378 NumOfNonConstOps = 1;
1388 if (NewCost >= OldCost)
1399 DeadVals.push_back(
I);
1403bool AMDGPUCodeGenPrepareImpl::visitBinaryOperator(BinaryOperator &
I) {
1404 if (foldBinOpIntoSelect(
I))
1407 if (CLOpts.codegenprepare_mul24 && replaceMulWithMul24(
I))
1409 if (tryNarrowMathIfNoOverflow(&
I))
1414 Type *Ty =
I.getType();
1415 Value *NewDiv =
nullptr;
1420 if ((
Opc == Instruction::URem ||
Opc == Instruction::UDiv ||
1421 Opc == Instruction::SRem ||
Opc == Instruction::SDiv) &&
1422 ScalarSize <= 64 && CLOpts.codegenprepare_idiv_expansion) {
1423 Value *Num =
I.getOperand(0);
1424 Value *Den =
I.getOperand(1);
1431 for (
unsigned N = 0,
E = VT->getNumElements();
N !=
E; ++
N) {
1436 if (ScalarSize <= 32) {
1437 NewElt = expandDivRem32(Builder,
I, NumEltN, DenEltN);
1443 NewElt = shrinkDivRem64(Builder,
I, NumEltN, DenEltN);
1457 NewEltI->copyIRFlags(&
I);
1462 if (ScalarSize <= 32)
1463 NewDiv = expandDivRem32(Builder,
I, Num, Den);
1465 NewDiv = shrinkDivRem64(Builder,
I, Num, Den);
1472 I.replaceAllUsesWith(NewDiv);
1473 DeadVals.push_back(&
I);
1478 if (ExpandDiv64InIR) {
1480 for (BinaryOperator *Div : Div64ToExpand) {
1481 expandDivRem64(*Div);
1490bool AMDGPUCodeGenPrepareImpl::visitLoadInst(LoadInst &
I) {
1491 if (!CLOpts.codegenprepare_widen_constant_loads)
1496 canWidenScalarExtLoad(
I)) {
1507 if (
auto *
Range =
I.getMetadata(LLVMContext::MD_range)) {
1510 if (!
Lower->isNullValue()) {
1517 WidenLoad->setMetadata(LLVMContext::MD_range,
1522 int TySize =
DL.getTypeSizeInBits(
I.getType());
1527 DeadVals.push_back(&
I);
1534bool AMDGPUCodeGenPrepareImpl::visitSelectInst(SelectInst &
I) {
1540 Value *Fract =
nullptr;
1549 Value *FractSrc = matchFractPatImpl(*
X, *
C);
1554 Fract = applyFractPat(Builder, FractSrc);
1564 CmpPredicate IsNanPred;
1573 if (IsNanPred == FCmpInst::FCMP_UNO && TrueVal == CmpVal &&
1574 CmpVal == matchFractPatNanAvoidant(*FalseVal)) {
1576 Fract = applyFractPat(Builder, CmpVal);
1577 }
else if (IsNanPred == FCmpInst::FCMP_ORD && FalseVal == CmpVal) {
1578 if (CmpVal == matchFractPatNanAvoidant(*TrueVal)) {
1580 Fract = applyFractPat(Builder, CmpVal);
1584 CmpPredicate PredInf;
1590 PredInf != FCmpInst::FCMP_UNE ||
1591 CmpVal != matchFractPatNanAvoidant(*IfNotInf))
1601 Value *NewFract = applyFractPat(Builder, CmpVal);
1605 DeadVals.push_back(ClampInfSelect->
getOperand(1));
1609 Fract = ClampInfSelect;
1616 I.replaceAllUsesWith(Fract);
1617 DeadVals.push_back(&
I);
1624 return IA && IB && IA->getParent() == IB->getParent();
1637 BitVector EltsCovered(FVT->getNumElements());
1644 if (!Idx || Idx->getZExtValue() >= FVT->getNumElements())
1647 const auto *VecSrc = IE->getOperand(0);
1656 EltsCovered.
set(Idx->getZExtValue());
1659 if (EltsCovered.
all())
1686 const auto [It, Inserted] = SeenPHIs.
insert(&
I);
1690 for (
const Value *Inc :
I.incoming_values()) {
1695 for (
const User *U :
I.users()) {
1701bool AMDGPUCodeGenPrepareImpl::canBreakPHINode(
const PHINode &
I) {
1703 if (
const auto It = BreakPhiNodesCache.find(&
I);
1704 It != BreakPhiNodesCache.end())
1713 SmallPtrSet<const PHINode *, 8> WorkList;
1719 for (
const PHINode *WLP : WorkList) {
1720 assert(BreakPhiNodesCache.count(WLP) == 0);
1735 const auto Threshold = (
alignTo(WorkList.size() * 2, 3) / 3);
1736 unsigned NumBreakablePHIs = 0;
1737 bool CanBreak =
false;
1738 for (
const PHINode *Cur : WorkList) {
1746 if (++NumBreakablePHIs >= Threshold) {
1753 for (
const PHINode *Cur : WorkList)
1754 BreakPhiNodesCache[Cur] = CanBreak;
1803 Value *&Res = SlicedVals[{BB, Inc}];
1809 B.SetCurrentDebugLocation(IncInst->getDebugLoc());
1815 Res =
B.CreateShuffleVector(Inc, Mask, NewValName);
1817 Res =
B.CreateExtractElement(Inc,
Idx, NewValName);
1826bool AMDGPUCodeGenPrepareImpl::visitPHINode(PHINode &
I) {
1837 if (!CLOpts.codegenprepare_break_large_phis ||
1839 cl::boolOrDefault::BOU_TRUE)
1844 DL.getTypeSizeInBits(FVT) <=
1845 CLOpts.codegenprepare_break_large_phis_threshold)
1848 if (!CLOpts.codegenprepare_force_break_large_phis && !canBreakPHINode(
I))
1851 std::vector<VectorSlice> Slices;
1858 const unsigned EltSize =
DL.getTypeSizeInBits(EltTy);
1860 if (EltSize == 8 || EltSize == 16) {
1861 const unsigned SubVecSize = (32 / EltSize);
1865 Slices.emplace_back(
SubVecTy, Idx, SubVecSize);
1869 for (;
Idx < NumElts; ++
Idx)
1870 Slices.emplace_back(EltTy, Idx, 1);
1873 assert(Slices.size() > 1);
1879 B.SetCurrentDebugLocation(
I.getDebugLoc());
1881 unsigned IncNameSuffix = 0;
1882 for (VectorSlice &S : Slices) {
1885 B.SetInsertPoint(
I.getParent()->getFirstNonPHIIt());
1886 S.NewPHI =
B.CreatePHI(S.Ty,
I.getNumIncomingValues());
1888 for (
const auto &[Idx, BB] :
enumerate(
I.blocks())) {
1889 S.NewPHI->addIncoming(S.getSlicedVal(BB,
I.getIncomingValue(Idx),
1890 "largephi.extractslice" +
1891 std::to_string(IncNameSuffix++)),
1898 unsigned NameSuffix = 0;
1899 for (VectorSlice &S : Slices) {
1900 const auto ValName =
"largephi.insertslice" + std::to_string(NameSuffix++);
1902 Vec =
B.CreateInsertVector(FVT, Vec, S.NewPHI, S.Idx, ValName);
1904 Vec =
B.CreateInsertElement(Vec, S.NewPHI, S.Idx, ValName);
1907 I.replaceAllUsesWith(Vec);
1908 DeadVals.push_back(&
I);
1931 Load &&
Load->hasMetadata(LLVMContext::MD_nonnull))
1950 assert(SrcPtrKB.getBitWidth() ==
DL.getPointerSizeInBits(AS));
1951 assert((NullVal == 0 || NullVal == -1) &&
1952 "don't know how to check for this null value!");
1953 return NullVal ? !SrcPtrKB.getMaxValue().isAllOnes() : SrcPtrKB.isNonZero();
1956bool AMDGPUCodeGenPrepareImpl::visitAddrSpaceCastInst(AddrSpaceCastInst &
I) {
1969 if (
I.getType()->isVectorTy())
1974 const unsigned SrcAS =
I.getSrcAddressSpace();
1975 const unsigned DstAS =
I.getDestAddressSpace();
1977 bool CanLower =
false;
1998bool AMDGPUCodeGenPrepareImpl::visitIntrinsicInst(IntrinsicInst &
I) {
2001 case Intrinsic::minnum:
2002 case Intrinsic::minimumnum:
2003 case Intrinsic::minimum:
2004 return visitFMinLike(
I);
2005 case Intrinsic::sqrt:
2006 return visitSqrt(
I);
2007 case Intrinsic::log:
2008 case Intrinsic::log10:
2010 case Intrinsic::log2:
2013 case Intrinsic::amdgcn_mbcnt_lo:
2014 return visitMbcntLo(
I);
2015 case Intrinsic::amdgcn_mbcnt_hi:
2016 return visitMbcntHi(
I);
2017 case Intrinsic::vector_reduce_add:
2018 return visitVectorReduceAdd(
I);
2019 case Intrinsic::uadd_sat:
2020 case Intrinsic::sadd_sat:
2021 return visitSaturatingAdd(
I);
2029Value *AMDGPUCodeGenPrepareImpl::matchFractPatImpl(
Value &FractSrc,
2030 const APFloat &
C)
const {
2039 OneNextDown.
next(
true);
2042 if (OneNextDown !=
C)
2062Value *AMDGPUCodeGenPrepareImpl::matchFractPatNanAvoidant(
Value &
V) {
2074 return matchFractPatImpl(*Arg0, *
C);
2079 SmallVector<Value *, 4> FractVals;
2082 SmallVector<Value *, 4> ResultVals(FractVals.
size());
2085 for (
unsigned I = 0,
E = FractVals.
size();
I !=
E; ++
I) {
2093bool AMDGPUCodeGenPrepareImpl::visitFMinLike(IntrinsicInst &
I) {
2101 FractArg = matchFractPatImpl(*
X, *
C);
2106 FractArg = matchFractPatNanAvoidant(
I);
2118 FastMathFlags FMF =
I.getFastMathFlags();
2122 Value *Fract = applyFractPat(Builder, FractArg);
2124 I.replaceAllUsesWith(Fract);
2125 DeadVals.push_back(&
I);
2130bool AMDGPUCodeGenPrepareImpl::visitSqrt(IntrinsicInst &Sqrt) {
2146 if (ReqdAccuracy < 1.0f)
2150 bool CanTreatAsDAZ = canIgnoreDenormalInput(SrcVal, &Sqrt);
2154 if (!CanTreatAsDAZ && ReqdAccuracy < 2.0f)
2158 SmallVector<Value *, 4> SrcVals;
2161 SmallVector<Value *, 4> ResultVals(SrcVals.
size());
2162 for (
int I = 0,
E = SrcVals.
size();
I !=
E; ++
I) {
2164 ResultVals[
I] = Builder.
CreateCall(getSqrtF32(), SrcVals[
I]);
2166 ResultVals[
I] = emitSqrtIEEE2ULP(Builder, SrcVals[
I], SqrtFMF);
2172 DeadVals.push_back(&Sqrt);
2177bool AMDGPUCodeGenPrepareImpl::visitLog(FPMathOperator &Log,
2183 FastMathFlags FMF =
Log.getFastMathFlags();
2190 if (
Log.getFPAccuracy() < 1.80f)
2201 double Log2BaseInverted =
2208 Log.replaceAllUsesWith(
Mul);
2209 DeadVals.push_back(&Log);
2213bool AMDGPUCodeGenPrepare::runOnFunction(
Function &
F) {
2214 if (skipFunction(
F))
2217 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
2221 const AMDGPUTargetMachine &TM = TPC->getTM<AMDGPUTargetMachine>();
2222 const TargetTransformInfo &
TTI =
2223 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
2224 const TargetLibraryInfo *
TLI =
2225 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
2226 AssumptionCache *AC =
2227 &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
2228 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
2229 const DominatorTree *DT = DTWP ? &DTWP->getDomTree() :
nullptr;
2231 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
2232 return AMDGPUCodeGenPrepareImpl(
F, TM,
TTI,
TLI, AC, DT, UA, ExpandDiv64InIR)
2244 AMDGPUCodeGenPrepareImpl Impl(
F, ATM,
TTI,
TLI, AC, DT, UA,
2245 ATM.
getCLOpts().codegenprepare_expand_div64);
2249 if (!Impl.FlowChanged)
2255 "AMDGPU IR optimizations",
false,
false)
2266 B.CreateIntrinsicWithoutFolding(Intrinsic::amdgcn_workitem_id_x, {});
2267 ST.makeLIDRangeMetadata(Tid);
2272void AMDGPUCodeGenPrepareImpl::replaceWithWorkitemIdX(Instruction &
I)
const {
2274 CallInst *Tid = createWorkitemIdX(
B);
2280void AMDGPUCodeGenPrepareImpl::replaceWithMaskedWorkitemIdX(
2281 Instruction &
I,
unsigned WaveSize)
const {
2283 CallInst *Tid = createWorkitemIdX(
B);
2285 Value *AndInst =
B.CreateAnd(Tid, Mask);
2293bool AMDGPUCodeGenPrepareImpl::tryReplaceWithWorkitemId(Instruction &
I,
2294 unsigned Wave)
const {
2301 if (*MaybeX == Wave) {
2302 replaceWithWorkitemIdX(
I);
2309 replaceWithMaskedWorkitemIdX(
I, Wave);
2317bool AMDGPUCodeGenPrepareImpl::visitMbcntLo(IntrinsicInst &
I)
const {
2333bool AMDGPUCodeGenPrepareImpl::visitMbcntHi(IntrinsicInst &
I)
const {
2351 using namespace PatternMatch;
2359 return tryReplaceWithWorkitemId(
I, Wave);
2385 Value *ExtSrc0, *ExtSrc1;
2405bool AMDGPUCodeGenPrepareImpl::visitVectorReduceAdd(IntrinsicInst &
I) {
2407 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2410 Value *
A =
nullptr, *
B =
nullptr;
2413 bool IsSigned =
false;
2420 LLVMContext &Ctx =
I.getContext();
2421 Type *I32Ty = Type::getInt32Ty(Ctx);
2429 Value *Acc = ConstantInt::get(I32Ty, 0);
2433 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2438 I.replaceAllUsesWith(Dot);
2439 DeadVals.push_back(&
I);
2447bool AMDGPUCodeGenPrepareImpl::visitSaturatingAdd(IntrinsicInst &
I) {
2449 if (!ST.hasDot7Insts() || (!ST.hasDot1Insts() && !ST.hasDot8Insts()))
2453 bool IsSigned = (IID == Intrinsic::sadd_sat);
2456 Value *Op0 =
I.getArgOperand(0);
2457 Value *Op1 =
I.getArgOperand(1);
2458 Value *MulOp =
nullptr;
2459 Value *Accum =
nullptr;
2460 IntrinsicInst *ReduceInst =
nullptr;
2465 }
else if (
match(Op1,
2473 Value *
A =
nullptr, *
B =
nullptr;
2478 LLVMContext &Ctx =
I.getContext();
2479 Type *I32Ty = Type::getInt32Ty(Ctx);
2490 IsSigned ? Intrinsic::amdgcn_sdot4 : Intrinsic::amdgcn_udot4;
2495 I.replaceAllUsesWith(Dot);
2496 DeadVals.push_back(&
I);
2499 DeadVals.push_back(ReduceInst);
2504char AMDGPUCodeGenPrepare::ID = 0;
2507 return new AMDGPUCodeGenPrepare(ExpandDiv64InIR);
const TargetLowering & TLI
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)
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
bpf unwind BPF Unwind Lower
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool runOnFunction(Function &F, bool PostInlining)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
SmallVector< MachineOperand, 4 > Cond
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Target-Independent Code Generator Pass Configuration Options pass.
VectorSlice(Type *Ty, unsigned Idx, unsigned NumElts)
Value * getSlicedVal(BasicBlock *BB, Value *Inc, StringRef NewValName)
Slice Inc according to the information contained within this slice.
PreservedAnalyses run(Function &, FunctionAnalysisManager &)
std::optional< unsigned > getReqdWorkGroupSize(const Function &F, unsigned Dim) const
unsigned getWavefrontSize() const
bool hasWavefrontsEvenlySplittingXDim(const Function &F, bool RequiresUniformYZ=false) const
const AMDGPUOptions & getCLOpts() const
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative=false)
Returns the smallest (by magnitude) normalized finite number in the given semantics.
opStatus next(bool nextDown)
This class represents a conversion between pointers from one address space to another.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BinaryOps getOpcode() const
BitVector & set()
Set all bits in the bitvector.
bool all() const
Returns true if all bits are set.
Represents analyses that only rely on functions' control flow.
This class represents a function call, abstracting a target machine's calling convention.
This is the base class for all instructions that perform data casts.
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
bool isOne() const
Returns true if this value is exactly +1.0.
static LLVM_ABI ConstantFP * getInfinity(Type *Ty, bool Negative=false)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Utility class for floating point operations which can have information about relaxed accuracy require...
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
LLVM_ABI float getFPAccuracy() const
Get the maximum error permitted by this operation in ULPs.
Convenience struct for specifying and reasoning about fast-math flags.
void setFast(bool B=true)
bool noSignedZeros() const
static FastMathFlags intersectValue(FastMathFlags LHS, FastMathFlags RHS)
Intersect value flags.
bool allowReciprocal() const
void setNoSignedZeros(bool B=true)
void setNoNaNs(bool B=true)
void setNoInfs(bool B=true)
bool allowContract() const
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
bool isWaveSizeKnown() const
Returns if the wavesize of this subtarget is known reliable.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateFDiv(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateFPToUI(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateUIToFP(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false, MDNode *FPMathTag=nullptr)
void setFastMathFlags(FastMathFlags NewFMF)
Set the fast-math flags to be used with generated fp-math operators.
Value * CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)
LLVM_ABI Value * createIsFPClass(Value *FPNum, unsigned Test)
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateFMA(Value *Factor1, Value *Factor2, Value *Summand, FMFSource FMFSource={}, const Twine &Name="")
Create call to the fma intrinsic.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Type * getFloatTy()
Fetch the type representing a 32-bit floating point value.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateSIToFP(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateFMul(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateFNeg(Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Value * CreateSExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a SExt or Trunc from the integer value V to DestTy.
Value * CreateFMulFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI Value * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *Op, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 1 operand which is mangled on its type.
Value * CreateFPToSI(Value *V, Type *DestTy, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
A wrapper class for inspecting calls to intrinsic functions.
bool isKnownNeverSubnormal() const
Return true if it's known this can never be a subnormal.
LLVM_ABI bool isKnownNeverLogicalZero(DenormalMode Mode) const
Return true if it's known this can never be interpreted as a zero.
bool isKnownNeverPosInfinity() const
Return true if it's known this can never be +infinity.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
This class represents the LLVM 'select' instruction.
const Value * getFalseValue() const
const Value * getCondition() const
const Value * getTrueValue() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI unsigned getIntegerBitWidth() const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI const fltSemantics & getFltSemantics() const
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Type * getElementType() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ PRIVATE_ADDRESS
Address space for private memory.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
void copyMetadataForWidenedLoad(LoadInst &Dest, const LoadInst &Source)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
auto m_PosZeroFP()
Matches a floating-point positive zero.
AllOnesConstantMatch m_AllOnes()
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
CmpClass_match< LHS, RHS, FCmpInst > m_FCmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FSub > m_FSub(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_deferred< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
ap_match< APFloat > m_APFloatAllowPoison(const APFloat *&Res)
Match APFloat while allowing poison in splat vector constants.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
FMaxMin_match< LHS, RHS, ufmin_pred_ty > m_UnordFMin(const LHS &L, const RHS &R)
Match an 'unordered' floating point minimum function.
auto m_FMinimum(const Opnd0 &Op0, const Opnd1 &Op1)
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
cstfp_pred_ty< is_nonnan > m_NonNaN()
Match a non-NaN FP constant.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
auto m_FMinNum_or_FMinimumNum(const Opnd0 &Op0, const Opnd1 &Op1)
cstfp_pred_ty< is_signed_inf< false > > m_PosInf()
Match a positive infinity FP constant.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_FAbs(const Opnd0 &Op0)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
RelativeUniformCounterPtr Values
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool expandRemainderUpTo64Bits(BinaryOperator *Rem)
Generate code to calculate the remainder of two integers, replacing Rem with the generated code.
@ Load
The value being inserted comes from a load (InsertElement only).
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
LLVM_ABI void ReplaceInstWithValue(BasicBlock::iterator &BI, Value *V)
Replace all uses of an instruction (specified by BI) with a value, then remove and delete the origina...
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI unsigned ComputeMaxSignificantBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Get the upper bound on bit size for this Value Op as a signed integer.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL, bool OrZero=false, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return true if the given value is known to have exactly one bit set when defined.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
auto reverse(ContainerTy &&C)
LLVM_ABI bool expandDivisionUpTo64Bits(BinaryOperator *Div)
Generate code to divide two integers, replacing Div with the generated code.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
LLVM_ABI Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)
Attempt to constant fold a cast with the specified operand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI CGPassBuilderOption getCGPassBuilderOption(const TargetMachine &TM)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI Constant * ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL)
Attempt to constant fold a binary operation with the specified operands.
To bit_cast(const From &from) noexcept
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isKnownNeverNaN(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the floating-point scalar value is not a NaN or if the floating-point vector value has...
unsigned Log2(Align A)
Returns the log2 of the alignment.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
FunctionPass * createAMDGPUCodeGenPreparePass(bool ExpandDiv64InIR)
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
constexpr bool inputsAreZero() const
Return true if input denormals must be implicitly treated as 0.
static constexpr DenormalMode getPreserveSign()
SimplifyQuery getWithInstruction(const Instruction *I) const