41#define DEBUG_TYPE "expand-fp"
48 cl::desc(
"fp convert instructions on integers with "
49 "more than <N> bits are expanded."));
78 static bool canExpandType(
Type *Ty) {
81 return Ty->isIEEELikeFPTy() && !Ty->isBFloatTy() && !Ty->isFP128Ty();
103 return FRemExpander{B, Ty, Precision / MaxIter, ComputeTy};
119 : B(B), FremTy(FremTy), ComputeFpTy(ComputeFpTy), ExTy(B.getInt32Ty()),
120 Bits(ConstantInt::
get(ExTy, Bits)), One(ConstantInt::
get(ExTy, 1)) {};
122 Value *createRcp(
Value *V,
const Twine &Name)
const {
125 return B.CreateFDiv(ConstantFP::get(ComputeFpTy, 1.0), V, Name);
137 Value *Q = B.CreateUnaryIntrinsic(Intrinsic::rint, B.CreateFMul(Ax, Ayinv),
139 Value *AxUpdate = B.CreateFMA(B.CreateFNeg(Q), Ay, Ax, {},
"ax");
142 Value *Axp = B.CreateFAdd(AxUpdate, Ay,
"axp");
143 return B.CreateSelect(Clt, Axp, AxUpdate,
"ax");
149 std::pair<Value *, Value *> buildExpAndPower(
Value *Src,
Value *NewExp,
151 const Twine &PowName)
const {
155 Type *Ty = Src->getType();
156 Type *ExTy = B.getInt32Ty();
157 Value *Frexp = B.CreateIntrinsic(Intrinsic::frexp, {Ty, ExTy}, Src);
158 Value *Mant = B.CreateExtractValue(Frexp, {0});
159 Value *
Exp = B.CreateExtractValue(Frexp, {1});
161 Exp = B.CreateSub(Exp, One, ExName);
162 Value *Pow = B.CreateLdexp(Mant, NewExp, {}, PowName);
171 void buildRemainderComputation(
Value *AxInitial,
Value *AyInitial,
Value *
X,
172 PHINode *RetPhi, FastMathFlags FMF)
const {
173 IRBuilder<>::FastMathFlagGuard Guard(B);
174 B.setFastMathFlags(FMF);
181 auto [Ax, Ex] = buildExpAndPower(AxInitial, Bits,
"ex",
"ax");
182 auto [Ay, Ey] = buildExpAndPower(AyInitial, One,
"ey",
"ay");
187 Value *Nb = B.CreateSub(Ex, Ey,
"nb");
188 Value *Ayinv = createRcp(Ay,
"ayinv");
204 B.SetInsertPoint(LoopBB);
205 PHINode *NbIv = B.CreatePHI(Nb->
getType(), 2,
"nb_iv");
208 auto *AxPhi = B.CreatePHI(ComputeFpTy, 2,
"ax_loop_phi");
209 AxPhi->addIncoming(Ax, PreheaderBB);
211 Value *AxPhiUpdate = buildUpdateAx(AxPhi, Ay, Ayinv);
212 AxPhiUpdate = B.CreateLdexp(AxPhiUpdate, Bits, {},
"ax_update");
213 AxPhi->addIncoming(AxPhiUpdate, LoopBB);
214 NbIv->
addIncoming(B.CreateSub(NbIv, Bits,
"nb_update"), LoopBB);
221 B.SetInsertPoint(ExitBB);
223 auto *AxPhiExit = B.CreatePHI(ComputeFpTy, 2,
"ax_exit_phi");
224 AxPhiExit->addIncoming(Ax, PreheaderBB);
225 AxPhiExit->addIncoming(AxPhi, LoopBB);
226 auto *NbExitPhi = B.CreatePHI(Nb->
getType(), 2,
"nb_exit_phi");
227 NbExitPhi->addIncoming(NbIv, LoopBB);
228 NbExitPhi->addIncoming(Nb, PreheaderBB);
230 Value *AxFinal = B.CreateLdexp(
231 AxPhiExit, B.CreateAdd(B.CreateSub(NbExitPhi, Bits), One), {},
"ax");
232 AxFinal = buildUpdateAx(AxFinal, Ay, Ayinv);
237 AxFinal = B.CreateLdexp(AxFinal, Ey, {},
"ax");
238 if (ComputeFpTy != FremTy)
239 AxFinal = B.CreateFPTrunc(AxFinal, FremTy);
240 Value *
Ret = B.CreateCopySign(AxFinal,
X);
249 void buildElseBranch(
Value *Ax,
Value *Ay,
Value *
X, PHINode *RetPhi)
const {
253 Value *
Ret = B.CreateSelect(B.CreateFCmpOEQ(Ax, Ay), ZeroWithXSign,
X);
261 std::optional<SimplifyQuery> &SQ,
272 : B.CreateFCmpULT(B.CreateUnaryIntrinsic(Intrinsic::fabs,
X),
274 Ret = B.CreateSelect(XFinite, Ret, Nan);
281 IRBuilder<>::FastMathFlagGuard Guard(
B);
286 B.clearFastMathFlags();
289 Value *Trunc =
B.CreateUnaryIntrinsic(Intrinsic::trunc, Quot, {});
290 Value *Neg =
B.CreateFNeg(Trunc);
292 return B.CreateFMA(Neg,
Y,
X);
296 std::optional<SimplifyQuery> &SQ)
const {
297 assert(
X->getType() == FremTy &&
Y->getType() == FremTy);
299 FastMathFlags FMF =
B.getFastMathFlags();
308 Value *Ax =
B.CreateUnaryIntrinsic(Intrinsic::fabs,
X, {},
"ax");
309 Value *Ay =
B.CreateUnaryIntrinsic(Intrinsic::fabs,
Y, {},
"ay");
310 if (ComputeFpTy !=
X->getType()) {
311 Ax =
B.CreateFPExt(Ax, ComputeFpTy,
"ax");
312 Ay =
B.CreateFPExt(Ay, ComputeFpTy,
"ay");
314 Value *AxAyCmp =
B.CreateFCmpOGT(Ax, Ay);
316 PHINode *RetPhi =
B.CreatePHI(FremTy, 2,
"ret");
322 Ret = handleInputCornerCases(Ret,
X,
Y, SQ, FMF.
noInfs());
329 auto SavedInsertPt =
B.GetInsertPoint();
337 FastMathFlags ComputeFMF = FMF;
341 B.SetInsertPoint(ThenBB);
342 buildRemainderComputation(Ax, Ay,
X, RetPhi, FMF);
346 B.SetInsertPoint(ElseBB);
347 buildElseBranch(Ax, Ay,
X, RetPhi);
350 B.SetInsertPoint(SavedInsertPt);
359 Type *ReturnTy =
I.getType();
368 B.setFastMathFlags(FMF);
369 B.SetCurrentDebugLocation(
I.getDebugLoc());
372 const FRemExpander Expander = FRemExpander::create(
B, ElemTy);
377 ? Expander.buildApproxFRem(
I.getOperand(0),
I.getOperand(1))
378 : Expander.buildFRem(
I.getOperand(0),
I.getOperand(1), SQ);
386 Value *Nums =
I.getOperand(0);
387 Value *Denums =
I.getOperand(1);
389 for (
int I = 0,
E = VecTy->getNumElements();
I !=
E; ++
I) {
390 Value *Num =
B.CreateExtractElement(Nums,
I);
391 Value *Denum =
B.CreateExtractElement(Denums,
I);
393 : Expander.buildFRem(Num, Denum, SQ);
394 Ret =
B.CreateInsertElement(Ret, Rem,
I);
398 I.replaceAllUsesWith(Ret);
464 unsigned FPMantissaWidth = FloatVal->getType()->getFPMantissaWidth() - 1;
469 if (FloatVal->getType()->isHalfTy()) {
470 if (FPToI->
getOpcode() == Instruction::FPToUI) {
471 Value *A0 = Builder.CreateFPToUI(FloatVal, Builder.getInt32Ty());
472 A1 = Builder.CreateZExt(A0, IntTy);
474 Value *A0 = Builder.CreateFPToSI(FloatVal, Builder.getInt32Ty());
475 A1 = Builder.CreateSExt(A0, IntTy);
485 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
486 unsigned FloatWidth =
487 PowerOf2Ceil(FloatVal->getType()->getScalarSizeInBits());
488 unsigned ExponentWidth = FloatWidth - FPMantissaWidth - 1;
489 unsigned ExponentBias = (1 << (ExponentWidth - 1)) - 1;
490 Value *ImplicitBit = Builder.CreateShl(
492 Value *SignificandMask =
493 Builder.CreateSub(ImplicitBit, Builder.getIntN(
BitWidth, 1));
494 Value *NegOne = Builder.CreateSExt(
502 Entry->setName(
Twine(Entry->getName(),
"fp-to-i-entry"));
516 Entry->getTerminator()->eraseFromParent();
519 Builder.SetInsertPoint(Entry);
520 Value *FloatVal0 = FloatVal;
523 if (FloatVal->getType()->isX86_FP80Ty())
527 Builder.CreateBitCast(FloatVal0, Builder.getIntNTy(FloatWidth));
528 Value *ARep = Builder.CreateZExt(ARep0, FPToI->
getType());
529 Value *PosOrNeg = Builder.CreateICmpSGT(
534 Builder.CreateLShr(ARep, Builder.getIntN(
BitWidth, FPMantissaWidth));
535 Value *And2 = Builder.CreateAnd(
536 And, Builder.getIntN(
BitWidth, (1 << ExponentWidth) - 1));
537 Value *Abs = Builder.CreateAnd(ARep, SignificandMask);
538 Value *
Or = Builder.CreateOr(Abs, ImplicitBit);
540 Builder.CreateICmpULT(And2, Builder.getIntN(
BitWidth, ExponentBias));
541 Builder.CreateCondBr(Cmp, End, IfEnd);
544 Builder.SetInsertPoint(IfEnd);
545 Value *Add1 = Builder.CreateAdd(
547 IntTy, -
static_cast<int64_t
>(ExponentBias +
BitWidth)));
548 Value *Cmp3 = Builder.CreateICmpULT(
550 Builder.CreateCondBr(Cmp3, IfThen5, IfEnd9);
553 Builder.SetInsertPoint(IfThen5);
554 Value *PosInf = Builder.CreateXor(NegOne, NegInf);
555 Value *Cond8 = Builder.CreateSelect(PosOrNeg, PosInf, NegInf);
556 Builder.CreateBr(End);
559 Builder.SetInsertPoint(IfEnd9);
560 Value *Cmp10 = Builder.CreateICmpULT(
561 And2, Builder.getIntN(
BitWidth, ExponentBias + FPMantissaWidth));
562 Builder.CreateCondBr(Cmp10, IfThen12, IfElse);
565 Builder.SetInsertPoint(IfThen12);
566 Value *Sub13 = Builder.CreateSub(
567 Builder.getIntN(
BitWidth, ExponentBias + FPMantissaWidth), And2);
568 Value *Shr14 = Builder.CreateLShr(
Or, Sub13);
569 Value *
Mul = Builder.CreateMul(Shr14, Sign);
570 Builder.CreateBr(End);
573 Builder.SetInsertPoint(IfElse);
574 Value *Sub15 = Builder.CreateAdd(
576 IntTy, -
static_cast<int64_t
>(ExponentBias + FPMantissaWidth)));
577 Value *Shl = Builder.CreateShl(
Or, Sub15);
578 Value *Mul16 = Builder.CreateMul(Shl, Sign);
579 Builder.CreateBr(End);
582 Builder.SetInsertPoint(End, End->
begin());
685 unsigned BitWidth = IntVal->getType()->getIntegerBitWidth();
689 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
692 FPMantissaWidth = FPMantissaWidth == 10 ? 23 : FPMantissaWidth;
693 FPMantissaWidth = FPMantissaWidth == 7 ? 23 : FPMantissaWidth;
695 bool IsSigned = IToFP->
getOpcode() == Instruction::SIToFP;
697 assert(
BitWidth > FloatWidth &&
"Unexpected conversion. expandIToFP() "
698 "assumes integer width is larger than fp.");
701 Builder.CreateShl(Builder.getIntN(
BitWidth, 1),
702 Builder.getIntN(
BitWidth, FPMantissaWidth + 3));
706 Entry->setName(
Twine(Entry->getName(),
"itofp-entry"));
726 Entry->getTerminator()->eraseFromParent();
733 Builder.SetInsertPoint(Entry);
735 Builder.CreateCondBr(Cmp, End, IfEnd);
738 Builder.SetInsertPoint(IfEnd);
741 Value *
Xor = Builder.CreateXor(Shr, IntVal);
743 Value *
Call = Builder.CreateCall(CTLZ, {IsSigned ?
Sub : IntVal, True});
744 Value *Cast = Builder.CreateTrunc(
Call, Builder.getInt32Ty());
745 int BitWidthNew = FloatWidth == 128 ?
BitWidth : 32;
746 Value *Sub1 = Builder.CreateSub(Builder.getIntN(BitWidthNew,
BitWidth),
747 FloatWidth == 128 ?
Call : Cast);
748 Value *Sub2 = Builder.CreateSub(Builder.getIntN(BitWidthNew,
BitWidth - 1),
749 FloatWidth == 128 ?
Call : Cast);
750 Value *Cmp3 = Builder.CreateICmpSGT(
751 Sub1, Builder.getIntN(BitWidthNew, FPMantissaWidth + 1));
752 Builder.CreateCondBr(Cmp3, IfThen4, IfElse);
755 Builder.SetInsertPoint(IfThen4);
757 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 2), SwBB);
758 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 3), SwEpilog);
761 Builder.SetInsertPoint(SwBB);
763 Builder.CreateShl(IsSigned ?
Sub : IntVal, Builder.getIntN(
BitWidth, 1));
764 Builder.CreateBr(SwEpilog);
767 Builder.SetInsertPoint(SwDefault);
768 Value *Sub5 = Builder.CreateSub(
769 Builder.getIntN(BitWidthNew,
BitWidth - FPMantissaWidth - 3),
770 FloatWidth == 128 ?
Call : Cast);
771 Value *ShProm = Builder.CreateZExt(Sub5, IntTy);
772 Value *Shr6 = Builder.CreateLShr(IsSigned ?
Sub : IntVal,
773 FloatWidth == 128 ? Sub5 : ShProm);
775 Builder.CreateAdd(FloatWidth == 128 ?
Call : Cast,
776 Builder.getIntN(BitWidthNew, FPMantissaWidth + 3));
777 Value *ShProm9 = Builder.CreateZExt(Sub8, IntTy);
779 FloatWidth == 128 ? Sub8 : ShProm9);
780 Value *
And = Builder.CreateAnd(Shr9, IsSigned ?
Sub : IntVal);
782 Value *Conv11 = Builder.CreateZExt(Cmp10, IntTy);
783 Value *
Or = Builder.CreateOr(Shr6, Conv11);
784 Builder.CreateBr(SwEpilog);
787 Builder.SetInsertPoint(SwEpilog);
788 PHINode *AAddr0 = Builder.CreatePHI(IntTy, 3);
792 Value *A0 = Builder.CreateTrunc(AAddr0, Builder.getInt32Ty());
793 Value *A1 = Builder.CreateLShr(A0, Builder.getInt32(2));
794 Value *A2 = Builder.CreateAnd(A1, Builder.getInt32(1));
795 Value *Conv16 = Builder.CreateZExt(A2, IntTy);
796 Value *Or17 = Builder.CreateOr(AAddr0, Conv16);
797 Value *Inc = Builder.CreateAdd(Or17, Builder.getIntN(
BitWidth, 1));
798 Value *Shr18 =
nullptr;
800 Shr18 = Builder.CreateAShr(Inc, Builder.getIntN(
BitWidth, 2));
802 Shr18 = Builder.CreateLShr(Inc, Builder.getIntN(
BitWidth, 2));
803 Value *A3 = Builder.CreateAnd(Inc, Temp1,
"a3");
804 Value *PosOrNeg = Builder.CreateICmpEQ(A3, Builder.getIntN(
BitWidth, 0));
805 Value *ExtractT60 = Builder.CreateTrunc(Shr18, Builder.getIntNTy(FloatWidth));
806 Value *Extract63 = Builder.CreateLShr(Shr18, Builder.getIntN(
BitWidth, 32));
807 Value *ExtractT64 =
nullptr;
809 ExtractT64 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
811 ExtractT64 = Builder.CreateTrunc(Extract63, Builder.getInt32Ty());
812 Builder.CreateCondBr(PosOrNeg, IfEnd26, IfThen20);
815 Builder.SetInsertPoint(IfThen20);
816 Value *Shr21 =
nullptr;
818 Shr21 = Builder.CreateAShr(Inc, Builder.getIntN(
BitWidth, 3));
820 Shr21 = Builder.CreateLShr(Inc, Builder.getIntN(
BitWidth, 3));
821 Value *ExtractT = Builder.CreateTrunc(Shr21, Builder.getIntNTy(FloatWidth));
822 Value *Extract = Builder.CreateLShr(Shr21, Builder.getIntN(
BitWidth, 32));
823 Value *ExtractT62 =
nullptr;
825 ExtractT62 = Builder.CreateTrunc(Sub1, Builder.getInt64Ty());
827 ExtractT62 = Builder.CreateTrunc(Extract, Builder.getInt32Ty());
828 Builder.CreateBr(IfEnd26);
831 Builder.SetInsertPoint(IfElse);
832 Value *Sub24 = Builder.CreateAdd(
833 FloatWidth == 128 ?
Call : Cast,
835 -(
BitWidth - FPMantissaWidth - 1)));
836 Value *ShProm25 = Builder.CreateZExt(Sub24, IntTy);
837 Value *Shl26 = Builder.CreateShl(IsSigned ?
Sub : IntVal,
838 FloatWidth == 128 ? Sub24 : ShProm25);
839 Value *ExtractT61 = Builder.CreateTrunc(Shl26, Builder.getIntNTy(FloatWidth));
840 Value *Extract65 = Builder.CreateLShr(Shl26, Builder.getIntN(
BitWidth, 32));
841 Value *ExtractT66 =
nullptr;
843 ExtractT66 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
845 ExtractT66 = Builder.CreateTrunc(Extract65, Builder.getInt32Ty());
846 Builder.CreateBr(IfEnd26);
849 Builder.SetInsertPoint(IfEnd26);
850 PHINode *AAddr1Off0 = Builder.CreatePHI(Builder.getIntNTy(FloatWidth), 3);
854 PHINode *AAddr1Off32 =
nullptr;
855 if (FloatWidth > 32) {
857 Builder.CreatePHI(Builder.getIntNTy(FloatWidth > 80 ? 64 : 32), 3);
863 if (FloatWidth <= 80) {
864 E0 = Builder.CreatePHI(Builder.getIntNTy(BitWidthNew), 3);
869 Value *And29 =
nullptr;
870 if (FloatWidth > 80) {
871 Value *Temp2 = Builder.CreateShl(Builder.getIntN(
BitWidth, 1),
873 And29 = Builder.CreateAnd(Shr, Temp2,
"and29");
875 Value *Conv28 = Builder.CreateTrunc(Shr, Builder.getInt32Ty());
876 And29 = Builder.CreateAnd(
879 unsigned TempMod = FPMantissaWidth % 32;
880 Value *And34 =
nullptr;
881 Value *Shl30 =
nullptr;
882 if (FloatWidth > 80) {
884 Value *
Add = Builder.CreateShl(AAddr1Off32, Builder.getInt64(TempMod));
885 Shl30 = Builder.CreateAdd(
886 Add, Builder.getInt64(((1ull << (62ull - TempMod)) - 1ull) << TempMod));
887 And34 = Builder.CreateZExt(Shl30, Builder.getInt128Ty());
889 Value *
Add = Builder.CreateShl(E0, Builder.getInt32(TempMod));
890 Shl30 = Builder.CreateAdd(
891 Add, Builder.getInt32(((1 << (30 - TempMod)) - 1) << TempMod));
892 And34 = Builder.CreateAnd(FloatWidth > 32 ? AAddr1Off32 : AAddr1Off0,
893 Builder.getInt32((1 << TempMod) - 1));
895 Value *Or35 =
nullptr;
896 if (FloatWidth > 80) {
897 Value *And29Trunc = Builder.CreateTrunc(And29, Builder.getInt128Ty());
898 Value *Or31 = Builder.CreateOr(And29Trunc, And34);
899 Value *Or34 = Builder.CreateShl(Or31, Builder.getIntN(128, 64));
900 Value *Temp3 = Builder.CreateShl(Builder.getIntN(128, 1),
901 Builder.getIntN(128, FPMantissaWidth));
902 Value *Temp4 = Builder.CreateSub(Temp3, Builder.getIntN(128, 1));
903 Value *A6 = Builder.CreateAnd(AAddr1Off0, Temp4);
904 Or35 = Builder.CreateOr(Or34, A6);
906 Value *Or31 = Builder.CreateOr(And34, And29);
907 Or35 = Builder.CreateOr(IsSigned ? Or31 : And34, Shl30);
911 Value *ZExt1 = Builder.CreateZExt(Or35, Builder.getIntNTy(FloatWidth));
912 Value *Shl1 = Builder.CreateShl(ZExt1, Builder.getIntN(FloatWidth, 32));
914 Builder.CreateAnd(AAddr1Off0, Builder.getIntN(FloatWidth, 0xFFFFFFFF));
915 Value *Or1 = Builder.CreateOr(Shl1, And1);
916 A4 = Builder.CreateBitCast(Or1, IToFP->
getType());
920 A4 = Builder.CreateFPTrunc(A40, IToFP->
getType());
926 A4 = Builder.CreateFPTrunc(A40, IToFP->
getType());
928 A4 = Builder.CreateBitCast(Or35, IToFP->
getType());
929 Builder.CreateBr(End);
932 Builder.SetInsertPoint(End, End->
begin());
947 unsigned NumElements = VTy->getElementCount().getFixedValue();
949 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
950 Value *Ext = Builder.CreateExtractElement(
I->getOperand(0), Idx);
952 I->getType()->getScalarType());
953 Result = Builder.CreateInsertElement(Result, Cast, Idx);
957 I->replaceAllUsesWith(Result);
958 I->dropAllReferences();
959 I->eraseFromParent();
967 assert(Ty->isFloatingPointTy());
968 if (Ty->isFloatTy() || Ty->is16bitFPTy())
969 return RTLIB::REM_F32;
970 if (Ty->isDoubleTy())
971 return RTLIB::REM_F64;
973 return RTLIB::REM_F128;
974 if (Ty->isX86_FP80Ty())
975 return RTLIB::REM_F80;
976 if (Ty->isPPC_FP128Ty())
977 return RTLIB::REM_PPCF128;
998 unsigned MaxLegalFpConvertBitWidth =
1007 switch (
I.getOpcode()) {
1008 case Instruction::FRem: {
1009 Type *Ty =
I.getType();
1011 if (Ty->isScalableTy())
1015 !FRemExpander::canExpandType(Ty->getScalarType()))
1023 case Instruction::FPToUI:
1024 case Instruction::FPToSI: {
1026 if (
I.getOperand(0)->getType()->isScalableTy())
1030 if (IntTy->getIntegerBitWidth() <= MaxLegalFpConvertBitWidth)
1033 if (
I.getOperand(0)->getType()->isVectorTy())
1040 case Instruction::UIToFP:
1041 case Instruction::SIToFP: {
1043 if (
I.getOperand(0)->getType()->isScalableTy())
1048 if (IntTy->getIntegerBitWidth() <= MaxLegalFpConvertBitWidth)
1051 if (
I.getOperand(0)->getType()->isVectorTy())
1063 while (!ReplaceVector.
empty()) {
1068 if (Replace.
empty())
1071 while (!Replace.
empty()) {
1073 if (
I->getOpcode() == Instruction::FRem) {
1074 auto SQ = [&]() -> std::optional<SimplifyQuery> {
1076 auto Res = std::make_optional<SimplifyQuery>(
1077 I->getModule()->getDataLayout(),
I);
1085 }
else if (
I->getOpcode() == Instruction::FPToUI ||
1086 I->getOpcode() == Instruction::FPToSI) {
1097class ExpandFpLegacyPass :
public FunctionPass {
1104 : FunctionPass(
ID), OptLevel(OptLevel) {
1111 auto *
TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1112 auto *TLI =
TM->getSubtargetImpl(
F)->getTargetLowering();
1113 AssumptionCache *AC =
nullptr;
1115 if (OptLevel != CodeGenOptLevel::None && !
F.hasOptNone())
1116 AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
1120 void getAnalysisUsage(AnalysisUsage &AU)
const override {
1122 if (OptLevel != CodeGenOptLevel::None)
1131 : TM(TM), OptLevel(OptLevel) {}
1136 OS, MapClassName2PassName);
1138 OS <<
"O" << (int)OptLevel;
1152char ExpandFpLegacyPass::ID = 0;
1154 "Expand certain fp instructions",
false,
false)
1158 return new ExpandFpLegacyPass(OptLevel);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
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)
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 void expandFPToI(Instruction *FPToI)
Generate code to convert a fp number to integer, replacing FPToS(U)I with the generated code.
static RTLIB::Libcall fremToLibcall(Type *Ty)
Return the Libcall for a frem instruction of type Ty.
static bool runImpl(Function &F, const TargetLowering &TLI, AssumptionCache *AC)
static bool targetSupportsFrem(const TargetLowering &TLI, Type *Ty)
static void scalarize(Instruction *I, SmallVectorImpl< Instruction * > &Replace)
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."))
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_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 std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
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.
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.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
unsigned getMaxLargeFPConvertBitWidthSupported() const
Returns the size in bits of the maximum fp to/from int conversion the backend supports.
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
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.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
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.
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...
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
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.
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...
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.
LLVM_ABI FunctionPass * createExpandFpPass()
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
A CRTP mix-in to automatically provide informational APIs needed for passes.