40#define DEBUG_TYPE "expand-fp"
47 cl::desc(
"fp convert instructions on integers with "
48 "more than <N> bits are expanded."));
79 static constexpr std::array<MVT, 3> ExpandableTypes{MVT::f16, MVT::f32,
83 static bool canExpandType(
Type *Ty) {
90 static bool shouldExpandFremType(
const TargetLowering &TLI, EVT VT) {
91 assert(!VT.
isVector() &&
"Cannot handle vector type; must scalarize first");
93 TargetLowering::LegalizeAction::Expand;
96 static bool shouldExpandFremType(
const TargetLowering &TLI,
Type *Ty) {
105 static bool shouldExpandAnyFremType(
const TargetLowering &TLI) {
106 return any_of(ExpandableTypes,
107 [&](MVT V) {
return shouldExpandFremType(TLI, EVT(V)); });
111 assert(canExpandType(Ty) &&
"Expected supported floating point type");
115 Type *ComputeTy = Ty;
119 unsigned MaxIter = 2;
129 return FRemExpander{B, Ty, Precision / MaxIter, ComputeTy};
145 : B(B), FremTy(FremTy), ComputeFpTy(ComputeFpTy), ExTy(B.getInt32Ty()),
146 Bits(ConstantInt::
get(ExTy, Bits)), One(ConstantInt::
get(ExTy, 1)) {};
148 Value *createRcp(
Value *V,
const Twine &Name)
const {
151 return B.CreateFDiv(ConstantFP::get(ComputeFpTy, 1.0), V, Name);
163 Value *Q = B.CreateUnaryIntrinsic(Intrinsic::rint, B.CreateFMul(Ax, Ayinv),
165 Value *AxUpdate = B.CreateFMA(B.CreateFNeg(Q), Ay, Ax, {},
"ax");
168 Value *Axp = B.CreateFAdd(AxUpdate, Ay,
"axp");
169 return B.CreateSelect(Clt, Axp, AxUpdate,
"ax");
175 std::pair<Value *, Value *> buildExpAndPower(
Value *Src,
Value *NewExp,
177 const Twine &PowName)
const {
181 Type *Ty = Src->getType();
182 Type *ExTy = B.getInt32Ty();
183 Value *Frexp = B.CreateIntrinsic(Intrinsic::frexp, {Ty, ExTy}, Src);
184 Value *Mant = B.CreateExtractValue(Frexp, {0});
185 Value *
Exp = B.CreateExtractValue(Frexp, {1});
187 Exp = B.CreateSub(Exp, One, ExName);
188 Value *Pow = B.CreateLdexp(Mant, NewExp, {}, PowName);
197 void buildRemainderComputation(
Value *AxInitial,
Value *AyInitial,
Value *
X,
198 PHINode *RetPhi, FastMathFlags FMF)
const {
199 IRBuilder<>::FastMathFlagGuard Guard(B);
200 B.setFastMathFlags(FMF);
207 auto [Ax, Ex] = buildExpAndPower(AxInitial, Bits,
"ex",
"ax");
208 auto [Ay, Ey] = buildExpAndPower(AyInitial, One,
"ey",
"ay");
213 Value *Nb = B.CreateSub(Ex, Ey,
"nb");
214 Value *Ayinv = createRcp(Ay,
"ayinv");
230 B.SetInsertPoint(LoopBB);
231 PHINode *NbIv = B.CreatePHI(Nb->
getType(), 2,
"nb_iv");
234 auto *AxPhi = B.CreatePHI(ComputeFpTy, 2,
"ax_loop_phi");
235 AxPhi->addIncoming(Ax, PreheaderBB);
237 Value *AxPhiUpdate = buildUpdateAx(AxPhi, Ay, Ayinv);
238 AxPhiUpdate = B.CreateLdexp(AxPhiUpdate, Bits, {},
"ax_update");
239 AxPhi->addIncoming(AxPhiUpdate, LoopBB);
240 NbIv->
addIncoming(B.CreateSub(NbIv, Bits,
"nb_update"), LoopBB);
247 B.SetInsertPoint(ExitBB);
249 auto *AxPhiExit = B.CreatePHI(ComputeFpTy, 2,
"ax_exit_phi");
250 AxPhiExit->addIncoming(Ax, PreheaderBB);
251 AxPhiExit->addIncoming(AxPhi, LoopBB);
252 auto *NbExitPhi = B.CreatePHI(Nb->
getType(), 2,
"nb_exit_phi");
253 NbExitPhi->addIncoming(NbIv, LoopBB);
254 NbExitPhi->addIncoming(Nb, PreheaderBB);
256 Value *AxFinal = B.CreateLdexp(
257 AxPhiExit, B.CreateAdd(B.CreateSub(NbExitPhi, Bits), One), {},
"ax");
258 AxFinal = buildUpdateAx(AxFinal, Ay, Ayinv);
263 AxFinal = B.CreateLdexp(AxFinal, Ey, {},
"ax");
264 if (ComputeFpTy != FremTy)
265 AxFinal = B.CreateFPTrunc(AxFinal, FremTy);
266 Value *Ret = B.CreateCopySign(AxFinal,
X);
275 void buildElseBranch(
Value *Ax,
Value *Ay,
Value *
X, PHINode *RetPhi)
const {
279 Value *Ret = B.CreateSelect(B.CreateFCmpOEQ(Ax, Ay), ZeroWithXSign,
X);
287 std::optional<SimplifyQuery> &SQ,
298 : B.CreateFCmpULT(B.CreateUnaryIntrinsic(Intrinsic::fabs,
X),
300 Ret = B.CreateSelect(XFinite, Ret, Nan);
307 IRBuilder<>::FastMathFlagGuard Guard(
B);
312 B.clearFastMathFlags();
315 Value *Trunc =
B.CreateUnaryIntrinsic(Intrinsic::trunc, Quot, {});
316 Value *Neg =
B.CreateFNeg(Trunc);
318 return B.CreateFMA(Neg,
Y,
X);
322 std::optional<SimplifyQuery> &SQ)
const {
323 assert(
X->getType() == FremTy &&
Y->getType() == FremTy);
325 FastMathFlags FMF =
B.getFastMathFlags();
334 Value *Ax =
B.CreateUnaryIntrinsic(Intrinsic::fabs,
X, {},
"ax");
335 Value *Ay =
B.CreateUnaryIntrinsic(Intrinsic::fabs,
Y, {},
"ay");
336 if (ComputeFpTy !=
X->getType()) {
337 Ax =
B.CreateFPExt(Ax, ComputeFpTy,
"ax");
338 Ay =
B.CreateFPExt(Ay, ComputeFpTy,
"ay");
340 Value *AxAyCmp =
B.CreateFCmpOGT(Ax, Ay);
342 PHINode *RetPhi =
B.CreatePHI(FremTy, 2,
"ret");
348 Ret = handleInputCornerCases(Ret,
X,
Y, SQ, FMF.
noInfs());
355 auto SavedInsertPt =
B.GetInsertPoint();
363 FastMathFlags ComputeFMF = FMF;
367 B.SetInsertPoint(ThenBB);
368 buildRemainderComputation(Ax, Ay,
X, RetPhi, FMF);
372 B.SetInsertPoint(ElseBB);
373 buildElseBranch(Ax, Ay,
X, RetPhi);
376 B.SetInsertPoint(SavedInsertPt);
385 Type *Ty =
I.getType();
386 assert(FRemExpander::canExpandType(Ty) &&
387 "Expected supported floating point type");
395 B.setFastMathFlags(FMF);
396 B.SetCurrentDebugLocation(
I.getDebugLoc());
398 const FRemExpander Expander = FRemExpander::create(
B, Ty);
400 ? Expander.buildApproxFRem(
I.getOperand(0),
I.getOperand(1))
401 : Expander.buildFRem(
I.getOperand(0),
I.getOperand(1), SQ);
403 I.replaceAllUsesWith(Ret);
469 unsigned FPMantissaWidth = FloatVal->getType()->getFPMantissaWidth() - 1;
474 if (FloatVal->getType()->isHalfTy()) {
475 if (FPToI->
getOpcode() == Instruction::FPToUI) {
476 Value *A0 = Builder.CreateFPToUI(FloatVal, Builder.getInt32Ty());
477 A1 = Builder.CreateZExt(A0, IntTy);
479 Value *A0 = Builder.CreateFPToSI(FloatVal, Builder.getInt32Ty());
480 A1 = Builder.CreateSExt(A0, IntTy);
490 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
491 unsigned FloatWidth =
492 PowerOf2Ceil(FloatVal->getType()->getScalarSizeInBits());
493 unsigned ExponentWidth = FloatWidth - FPMantissaWidth - 1;
494 unsigned ExponentBias = (1 << (ExponentWidth - 1)) - 1;
495 Value *ImplicitBit = Builder.CreateShl(
497 Value *SignificandMask =
498 Builder.CreateSub(ImplicitBit, Builder.getIntN(
BitWidth, 1));
499 Value *NegOne = Builder.CreateSExt(
507 Entry->setName(
Twine(Entry->getName(),
"fp-to-i-entry"));
521 Entry->getTerminator()->eraseFromParent();
524 Builder.SetInsertPoint(Entry);
525 Value *FloatVal0 = FloatVal;
528 if (FloatVal->getType()->isX86_FP80Ty())
532 Builder.CreateBitCast(FloatVal0, Builder.getIntNTy(FloatWidth));
533 Value *ARep = Builder.CreateZExt(ARep0, FPToI->
getType());
534 Value *PosOrNeg = Builder.CreateICmpSGT(
539 Builder.CreateLShr(ARep, Builder.getIntN(
BitWidth, FPMantissaWidth));
540 Value *And2 = Builder.CreateAnd(
541 And, Builder.getIntN(
BitWidth, (1 << ExponentWidth) - 1));
542 Value *Abs = Builder.CreateAnd(ARep, SignificandMask);
543 Value *
Or = Builder.CreateOr(Abs, ImplicitBit);
545 Builder.CreateICmpULT(And2, Builder.getIntN(
BitWidth, ExponentBias));
546 Builder.CreateCondBr(Cmp, End, IfEnd);
549 Builder.SetInsertPoint(IfEnd);
550 Value *Add1 = Builder.CreateAdd(
552 IntTy, -
static_cast<int64_t
>(ExponentBias +
BitWidth)));
553 Value *Cmp3 = Builder.CreateICmpULT(
555 Builder.CreateCondBr(Cmp3, IfThen5, IfEnd9);
558 Builder.SetInsertPoint(IfThen5);
559 Value *PosInf = Builder.CreateXor(NegOne, NegInf);
560 Value *Cond8 = Builder.CreateSelect(PosOrNeg, PosInf, NegInf);
561 Builder.CreateBr(End);
564 Builder.SetInsertPoint(IfEnd9);
565 Value *Cmp10 = Builder.CreateICmpULT(
566 And2, Builder.getIntN(
BitWidth, ExponentBias + FPMantissaWidth));
567 Builder.CreateCondBr(Cmp10, IfThen12, IfElse);
570 Builder.SetInsertPoint(IfThen12);
571 Value *Sub13 = Builder.CreateSub(
572 Builder.getIntN(
BitWidth, ExponentBias + FPMantissaWidth), And2);
573 Value *Shr14 = Builder.CreateLShr(
Or, Sub13);
574 Value *
Mul = Builder.CreateMul(Shr14, Sign);
575 Builder.CreateBr(End);
578 Builder.SetInsertPoint(IfElse);
579 Value *Sub15 = Builder.CreateAdd(
581 IntTy, -
static_cast<int64_t
>(ExponentBias + FPMantissaWidth)));
582 Value *Shl = Builder.CreateShl(
Or, Sub15);
583 Value *Mul16 = Builder.CreateMul(Shl, Sign);
584 Builder.CreateBr(End);
587 Builder.SetInsertPoint(End, End->
begin());
690 unsigned BitWidth = IntVal->getType()->getIntegerBitWidth();
694 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
697 FPMantissaWidth = FPMantissaWidth == 10 ? 23 : FPMantissaWidth;
698 FPMantissaWidth = FPMantissaWidth == 7 ? 23 : FPMantissaWidth;
700 bool IsSigned = IToFP->
getOpcode() == Instruction::SIToFP;
702 assert(
BitWidth > FloatWidth &&
"Unexpected conversion. expandIToFP() "
703 "assumes integer width is larger than fp.");
706 Builder.CreateShl(Builder.getIntN(
BitWidth, 1),
707 Builder.getIntN(
BitWidth, FPMantissaWidth + 3));
711 Entry->setName(
Twine(Entry->getName(),
"itofp-entry"));
731 Entry->getTerminator()->eraseFromParent();
738 Builder.SetInsertPoint(Entry);
740 Builder.CreateCondBr(Cmp, End, IfEnd);
743 Builder.SetInsertPoint(IfEnd);
746 Value *
Xor = Builder.CreateXor(Shr, IntVal);
748 Value *
Call = Builder.CreateCall(CTLZ, {IsSigned ?
Sub : IntVal, True});
749 Value *Cast = Builder.CreateTrunc(
Call, Builder.getInt32Ty());
750 int BitWidthNew = FloatWidth == 128 ?
BitWidth : 32;
751 Value *Sub1 = Builder.CreateSub(Builder.getIntN(BitWidthNew,
BitWidth),
752 FloatWidth == 128 ?
Call : Cast);
753 Value *Sub2 = Builder.CreateSub(Builder.getIntN(BitWidthNew,
BitWidth - 1),
754 FloatWidth == 128 ?
Call : Cast);
755 Value *Cmp3 = Builder.CreateICmpSGT(
756 Sub1, Builder.getIntN(BitWidthNew, FPMantissaWidth + 1));
757 Builder.CreateCondBr(Cmp3, IfThen4, IfElse);
760 Builder.SetInsertPoint(IfThen4);
762 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 2), SwBB);
763 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 3), SwEpilog);
766 Builder.SetInsertPoint(SwBB);
768 Builder.CreateShl(IsSigned ?
Sub : IntVal, Builder.getIntN(
BitWidth, 1));
769 Builder.CreateBr(SwEpilog);
772 Builder.SetInsertPoint(SwDefault);
773 Value *Sub5 = Builder.CreateSub(
774 Builder.getIntN(BitWidthNew,
BitWidth - FPMantissaWidth - 3),
775 FloatWidth == 128 ?
Call : Cast);
776 Value *ShProm = Builder.CreateZExt(Sub5, IntTy);
777 Value *Shr6 = Builder.CreateLShr(IsSigned ?
Sub : IntVal,
778 FloatWidth == 128 ? Sub5 : ShProm);
780 Builder.CreateAdd(FloatWidth == 128 ?
Call : Cast,
781 Builder.getIntN(BitWidthNew, FPMantissaWidth + 3));
782 Value *ShProm9 = Builder.CreateZExt(Sub8, IntTy);
784 FloatWidth == 128 ? Sub8 : ShProm9);
785 Value *
And = Builder.CreateAnd(Shr9, IsSigned ?
Sub : IntVal);
787 Value *Conv11 = Builder.CreateZExt(Cmp10, IntTy);
788 Value *
Or = Builder.CreateOr(Shr6, Conv11);
789 Builder.CreateBr(SwEpilog);
792 Builder.SetInsertPoint(SwEpilog);
793 PHINode *AAddr0 = Builder.CreatePHI(IntTy, 3);
797 Value *A0 = Builder.CreateTrunc(AAddr0, Builder.getInt32Ty());
798 Value *A1 = Builder.CreateLShr(A0, Builder.getInt32(2));
799 Value *A2 = Builder.CreateAnd(A1, Builder.getInt32(1));
800 Value *Conv16 = Builder.CreateZExt(A2, IntTy);
801 Value *Or17 = Builder.CreateOr(AAddr0, Conv16);
802 Value *Inc = Builder.CreateAdd(Or17, Builder.getIntN(
BitWidth, 1));
803 Value *Shr18 =
nullptr;
805 Shr18 = Builder.CreateAShr(Inc, Builder.getIntN(
BitWidth, 2));
807 Shr18 = Builder.CreateLShr(Inc, Builder.getIntN(
BitWidth, 2));
808 Value *A3 = Builder.CreateAnd(Inc, Temp1,
"a3");
809 Value *PosOrNeg = Builder.CreateICmpEQ(A3, Builder.getIntN(
BitWidth, 0));
810 Value *ExtractT60 = Builder.CreateTrunc(Shr18, Builder.getIntNTy(FloatWidth));
811 Value *Extract63 = Builder.CreateLShr(Shr18, Builder.getIntN(
BitWidth, 32));
812 Value *ExtractT64 =
nullptr;
814 ExtractT64 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
816 ExtractT64 = Builder.CreateTrunc(Extract63, Builder.getInt32Ty());
817 Builder.CreateCondBr(PosOrNeg, IfEnd26, IfThen20);
820 Builder.SetInsertPoint(IfThen20);
821 Value *Shr21 =
nullptr;
823 Shr21 = Builder.CreateAShr(Inc, Builder.getIntN(
BitWidth, 3));
825 Shr21 = Builder.CreateLShr(Inc, Builder.getIntN(
BitWidth, 3));
826 Value *ExtractT = Builder.CreateTrunc(Shr21, Builder.getIntNTy(FloatWidth));
827 Value *Extract = Builder.CreateLShr(Shr21, Builder.getIntN(
BitWidth, 32));
828 Value *ExtractT62 =
nullptr;
830 ExtractT62 = Builder.CreateTrunc(Sub1, Builder.getInt64Ty());
832 ExtractT62 = Builder.CreateTrunc(Extract, Builder.getInt32Ty());
833 Builder.CreateBr(IfEnd26);
836 Builder.SetInsertPoint(IfElse);
837 Value *Sub24 = Builder.CreateAdd(
838 FloatWidth == 128 ?
Call : Cast,
840 -(
int)(
BitWidth - FPMantissaWidth - 1)));
841 Value *ShProm25 = Builder.CreateZExt(Sub24, IntTy);
842 Value *Shl26 = Builder.CreateShl(IsSigned ?
Sub : IntVal,
843 FloatWidth == 128 ? Sub24 : ShProm25);
844 Value *ExtractT61 = Builder.CreateTrunc(Shl26, Builder.getIntNTy(FloatWidth));
845 Value *Extract65 = Builder.CreateLShr(Shl26, Builder.getIntN(
BitWidth, 32));
846 Value *ExtractT66 =
nullptr;
848 ExtractT66 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
850 ExtractT66 = Builder.CreateTrunc(Extract65, Builder.getInt32Ty());
851 Builder.CreateBr(IfEnd26);
854 Builder.SetInsertPoint(IfEnd26);
855 PHINode *AAddr1Off0 = Builder.CreatePHI(Builder.getIntNTy(FloatWidth), 3);
859 PHINode *AAddr1Off32 =
nullptr;
860 if (FloatWidth > 32) {
862 Builder.CreatePHI(Builder.getIntNTy(FloatWidth > 80 ? 64 : 32), 3);
868 if (FloatWidth <= 80) {
869 E0 = Builder.CreatePHI(Builder.getIntNTy(BitWidthNew), 3);
874 Value *And29 =
nullptr;
875 if (FloatWidth > 80) {
876 Value *Temp2 = Builder.CreateShl(Builder.getIntN(
BitWidth, 1),
878 And29 = Builder.CreateAnd(Shr, Temp2,
"and29");
880 Value *Conv28 = Builder.CreateTrunc(Shr, Builder.getInt32Ty());
881 And29 = Builder.CreateAnd(
884 unsigned TempMod = FPMantissaWidth % 32;
885 Value *And34 =
nullptr;
886 Value *Shl30 =
nullptr;
887 if (FloatWidth > 80) {
889 Value *
Add = Builder.CreateShl(AAddr1Off32, Builder.getInt64(TempMod));
890 Shl30 = Builder.CreateAdd(
891 Add, Builder.getInt64(((1ull << (62ull - TempMod)) - 1ull) << TempMod));
892 And34 = Builder.CreateZExt(Shl30, Builder.getInt128Ty());
894 Value *
Add = Builder.CreateShl(E0, Builder.getInt32(TempMod));
895 Shl30 = Builder.CreateAdd(
896 Add, Builder.getInt32(((1 << (30 - TempMod)) - 1) << TempMod));
897 And34 = Builder.CreateAnd(FloatWidth > 32 ? AAddr1Off32 : AAddr1Off0,
898 Builder.getInt32((1 << TempMod) - 1));
900 Value *Or35 =
nullptr;
901 if (FloatWidth > 80) {
902 Value *And29Trunc = Builder.CreateTrunc(And29, Builder.getInt128Ty());
903 Value *Or31 = Builder.CreateOr(And29Trunc, And34);
904 Value *Or34 = Builder.CreateShl(Or31, Builder.getIntN(128, 64));
905 Value *Temp3 = Builder.CreateShl(Builder.getIntN(128, 1),
906 Builder.getIntN(128, FPMantissaWidth));
907 Value *Temp4 = Builder.CreateSub(Temp3, Builder.getIntN(128, 1));
908 Value *A6 = Builder.CreateAnd(AAddr1Off0, Temp4);
909 Or35 = Builder.CreateOr(Or34, A6);
911 Value *Or31 = Builder.CreateOr(And34, And29);
912 Or35 = Builder.CreateOr(IsSigned ? Or31 : And34, Shl30);
916 Value *ZExt1 = Builder.CreateZExt(Or35, Builder.getIntNTy(FloatWidth));
917 Value *Shl1 = Builder.CreateShl(ZExt1, Builder.getIntN(FloatWidth, 32));
919 Builder.CreateAnd(AAddr1Off0, Builder.getIntN(FloatWidth, 0xFFFFFFFF));
920 Value *Or1 = Builder.CreateOr(Shl1, And1);
921 A4 = Builder.CreateBitCast(Or1, IToFP->
getType());
925 A4 = Builder.CreateFPTrunc(A40, IToFP->
getType());
931 A4 = Builder.CreateFPTrunc(A40, IToFP->
getType());
933 A4 = Builder.CreateBitCast(Or35, IToFP->
getType());
934 Builder.CreateBr(End);
937 Builder.SetInsertPoint(End, End->
begin());
953 unsigned NumElements = VTy->getElementCount().getFixedValue();
955 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
956 Value *Ext = Builder.CreateExtractElement(
I->getOperand(0), Idx);
958 Value *NewOp =
nullptr;
960 NewOp = Builder.CreateBinOp(
961 BinOp->getOpcode(), Ext,
962 Builder.CreateExtractElement(
I->getOperand(1), Idx));
964 NewOp = Builder.CreateCast(CastI->getOpcode(), Ext,
965 I->getType()->getScalarType());
969 Result = Builder.CreateInsertElement(Result, NewOp, Idx);
971 ScalarizedI->copyIRFlags(
I,
true);
976 I->replaceAllUsesWith(Result);
977 I->dropAllReferences();
978 I->eraseFromParent();
983 if (
I.getOperand(0)->getType()->isVectorTy())
993 unsigned MaxLegalFpConvertBitWidth =
998 bool DisableExpandLargeFp =
1000 bool DisableFrem = !FRemExpander::shouldExpandAnyFremType(TLI);
1002 if (DisableExpandLargeFp && DisableFrem)
1006 Type *Ty =
I.getType();
1008 if (Ty->isScalableTy())
1011 switch (
I.getOpcode()) {
1012 case Instruction::FRem:
1013 return !DisableFrem && FRemExpander::shouldExpandFremType(TLI, Ty);
1014 case Instruction::FPToUI:
1015 case Instruction::FPToSI:
1016 return !DisableExpandLargeFp &&
1018 MaxLegalFpConvertBitWidth;
1019 case Instruction::UIToFP:
1020 case Instruction::SIToFP:
1021 return !DisableExpandLargeFp &&
1023 ->getIntegerBitWidth() > MaxLegalFpConvertBitWidth;
1032 if (!ShouldHandleInst(
I))
1039 while (!Worklist.
empty()) {
1042 switch (
I->getOpcode()) {
1043 case Instruction::FRem: {
1044 auto SQ = [&]() -> std::optional<SimplifyQuery> {
1046 auto Res = std::make_optional<SimplifyQuery>(
1047 I->getModule()->getDataLayout(),
I);
1058 case Instruction::FPToUI:
1059 case Instruction::FPToSI:
1063 case Instruction::UIToFP:
1064 case Instruction::SIToFP:
1074class ExpandFpLegacyPass :
public FunctionPass {
1081 : FunctionPass(
ID), OptLevel(OptLevel) {
1088 auto *TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1089 const TargetSubtargetInfo *Subtarget = TM->getSubtargetImpl(
F);
1090 auto *TLI = Subtarget->getTargetLowering();
1091 AssumptionCache *AC =
nullptr;
1093 const LibcallLoweringInfo &Libcalls =
1094 getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
1097 if (OptLevel != CodeGenOptLevel::None && !
F.hasOptNone())
1098 AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
1099 return runImpl(
F, *TLI, Libcalls, AC);
1102 void getAnalysisUsage(AnalysisUsage &AU)
const override {
1105 if (OptLevel != CodeGenOptLevel::None)
1115 : TM(&TM), OptLevel(OptLevel) {}
1120 OS, MapClassName2PassName);
1122 OS <<
"O" << (int)OptLevel;
1138 if (!LibcallLowering) {
1140 "' analysis required");
1145 LibcallLowering->getLibcallLowering(*STI);
1151char ExpandFpLegacyPass::ID = 0;
1153 "Expand certain fp instructions",
false,
false)
1158 return new ExpandFpLegacyPass(OptLevel);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool runOnFunction(Function &F, bool PostInlining)
static bool expandFRem(BinaryOperator &I, std::optional< SimplifyQuery > &SQ)
static void expandIToFP(Instruction *IToFP)
Generate code to convert a fp number to integer, replacing S(U)IToFP with the generated code.
static bool runImpl(Function &F, const TargetLowering &TLI, const LibcallLoweringInfo &Libcalls, AssumptionCache *AC)
static void expandFPToI(Instruction *FPToI)
Generate code to convert a fp number to integer, replacing FPToS(U)I with the generated code.
static void addToWorklist(Instruction &I, SmallVector< Instruction *, 4 > &Worklist)
static cl::opt< unsigned > ExpandFpConvertBits("expand-fp-convert-bits", cl::Hidden, cl::init(llvm::IntegerType::MAX_INT_BITS), cl::desc("fp convert instructions on integers with " "more than <N> bits are expanded."))
static void scalarize(Instruction *I, SmallVectorImpl< Instruction * > &Worklist)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
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)
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ ICMP_SGT
signed greater than
static LLVM_ABI Constant * getInfinity(Type *Ty, bool Negative=false)
static LLVM_ABI Constant * getZero(Type *Ty, bool Negative=false)
static LLVM_ABI Constant * getQNaN(Type *Ty, bool Negative=false, APInt *Payload=nullptr)
This is the shared class of boolean and integer constants.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
ExpandFpPass(const TargetMachine &TM, CodeGenOptLevel OptLevel)
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Convenience struct for specifying and reasoning about fast-math flags.
void setAllowContract(bool B=true)
void setAllowReciprocal(bool B=true)
void setNoNaNs(bool B=true)
void setNoInfs(bool B=true)
FunctionPass class - This class is used to implement most global optimizations.
Module * getParent()
Get the module that this global value is contained inside of...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
Tracks which library functions to use for a particular subtarget.
Record a mapping from subtarget to LibcallLoweringInfo.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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.
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.
StringRef - Represent a constant reference to a string, i.e.
unsigned getMaxLargeFPConvertBitWidthSupported() const
Returns the size in bits of the maximum fp to/from int conversion the backend supports.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isX86_FP80Ty() const
Return true if this is x86 long double.
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
LLVM_ABI int getFPMantissaWidth() const
Return the width of the mantissa of this type.
LLVM_ABI const fltSemantics & getFltSemantics() const
void dropAllReferences()
Drop all references to operands.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type 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.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI bool isKnownNeverInfinity(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the floating-point scalar value is not an infinity or if the floating-point vector val...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
inst_iterator inst_begin(Function *F)
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
inst_iterator inst_end(Function *F)
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void initializeExpandFpLegacyPassPass(PassRegistry &)
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI FunctionPass * createExpandFpPass()
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
A CRTP mix-in to automatically provide informational APIs needed for passes.