55#define DEBUG_TYPE "expand-ir-insts"
62 cl::desc(
"fp convert instructions on integers with "
63 "more than <N> bits are expanded."));
68 cl::desc(
"div and rem instructions on integers with "
69 "more than <N> bits are expanded."));
72bool isConstantPowerOfTwo(
llvm::Value *V,
bool SignedOp) {
83bool isSigned(
unsigned int Opcode) {
84 return Opcode == Instruction::SDiv || Opcode == Instruction::SRem;
115 static constexpr std::array<MVT, 3> ExpandableTypes{MVT::f16, MVT::f32,
119 static bool canExpandType(
Type *Ty) {
126 static bool shouldExpandFremType(
const TargetLowering &TLI, EVT VT) {
127 assert(!VT.
isVector() &&
"Cannot handle vector type; must scalarize first");
129 TargetLowering::LegalizeAction::Expand;
132 static bool shouldExpandFremType(
const TargetLowering &TLI,
Type *Ty) {
141 static bool shouldExpandAnyFremType(
const TargetLowering &TLI) {
142 return any_of(ExpandableTypes,
143 [&](MVT V) {
return shouldExpandFremType(TLI, EVT(V)); });
147 assert(canExpandType(Ty) &&
"Expected supported floating point type");
151 Type *ComputeTy = Ty;
155 unsigned MaxIter = 2;
165 return FRemExpander{B, Ty, Precision / MaxIter, ComputeTy};
181 : B(B), FremTy(FremTy), ComputeFpTy(ComputeFpTy), ExTy(B.getInt32Ty()),
182 Bits(ConstantInt::
get(ExTy, Bits)), One(ConstantInt::
get(ExTy, 1)) {};
184 Value *createRcp(
Value *V,
const Twine &Name)
const {
187 return B.CreateFDiv(ConstantFP::get(ComputeFpTy, 1.0), V, Name);
199 Value *Q = B.CreateUnaryIntrinsic(Intrinsic::rint, B.CreateFMul(Ax, Ayinv),
201 Value *AxUpdate = B.CreateFMA(B.CreateFNeg(Q), Ay, Ax, {},
"ax");
204 Value *Axp = B.CreateFAdd(AxUpdate, Ay,
"axp");
205 return B.CreateSelect(Clt, Axp, AxUpdate,
"ax");
211 std::pair<Value *, Value *> buildExpAndPower(
Value *Src,
Value *NewExp,
213 const Twine &PowName)
const {
217 Type *Ty = Src->getType();
218 Type *ExTy = B.getInt32Ty();
219 Value *Frexp = B.CreateIntrinsic(Intrinsic::frexp, {Ty, ExTy}, Src);
220 Value *Mant = B.CreateExtractValue(Frexp, {0});
221 Value *
Exp = B.CreateExtractValue(Frexp, {1});
223 Exp = B.CreateSub(Exp, One, ExName);
224 Value *Pow = B.CreateLdexp(Mant, NewExp, {}, PowName);
233 void buildRemainderComputation(
Value *AxInitial,
Value *AyInitial,
Value *
X,
234 PHINode *RetPhi, FastMathFlags FMF)
const {
235 IRBuilder<>::FastMathFlagGuard Guard(B);
236 B.setFastMathFlags(FMF);
243 auto [Ax, Ex] = buildExpAndPower(AxInitial, Bits,
"ex",
"ax");
244 auto [Ay, Ey] = buildExpAndPower(AyInitial, One,
"ey",
"ay");
249 Value *Nb = B.CreateSub(Ex, Ey,
"nb");
250 Value *Ayinv = createRcp(Ay,
"ayinv");
266 B.SetInsertPoint(LoopBB);
267 PHINode *NbIv = B.CreatePHI(Nb->
getType(), 2,
"nb_iv");
270 auto *AxPhi = B.CreatePHI(ComputeFpTy, 2,
"ax_loop_phi");
271 AxPhi->addIncoming(Ax, PreheaderBB);
273 Value *AxPhiUpdate = buildUpdateAx(AxPhi, Ay, Ayinv);
274 AxPhiUpdate = B.CreateLdexp(AxPhiUpdate, Bits, {},
"ax_update");
275 AxPhi->addIncoming(AxPhiUpdate, LoopBB);
276 NbIv->
addIncoming(B.CreateSub(NbIv, Bits,
"nb_update"), LoopBB);
283 B.SetInsertPoint(ExitBB);
285 auto *AxPhiExit = B.CreatePHI(ComputeFpTy, 2,
"ax_exit_phi");
286 AxPhiExit->addIncoming(Ax, PreheaderBB);
287 AxPhiExit->addIncoming(AxPhi, LoopBB);
288 auto *NbExitPhi = B.CreatePHI(Nb->
getType(), 2,
"nb_exit_phi");
289 NbExitPhi->addIncoming(NbIv, LoopBB);
290 NbExitPhi->addIncoming(Nb, PreheaderBB);
292 Value *AxFinal = B.CreateLdexp(
293 AxPhiExit, B.CreateAdd(B.CreateSub(NbExitPhi, Bits), One), {},
"ax");
294 AxFinal = buildUpdateAx(AxFinal, Ay, Ayinv);
299 AxFinal = B.CreateLdexp(AxFinal, Ey, {},
"ax");
300 if (ComputeFpTy != FremTy)
301 AxFinal = B.CreateFPTrunc(AxFinal, FremTy);
302 Value *Ret = B.CreateCopySign(AxFinal,
X);
311 void buildElseBranch(
Value *Ax,
Value *Ay,
Value *
X, PHINode *RetPhi)
const {
315 Value *Ret = B.CreateSelect(B.CreateFCmpOEQ(Ax, Ay), ZeroWithXSign,
X);
323 std::optional<SimplifyQuery> &SQ,
334 : B.CreateFCmpULT(B.CreateUnaryIntrinsic(Intrinsic::fabs,
X),
336 Ret = B.CreateSelect(XFinite, Ret, Nan);
343 IRBuilder<>::FastMathFlagGuard Guard(
B);
348 B.clearFastMathFlags();
351 Value *Trunc =
B.CreateUnaryIntrinsic(Intrinsic::trunc, Quot, {});
352 Value *Neg =
B.CreateFNeg(Trunc);
354 return B.CreateFMA(Neg,
Y,
X);
358 std::optional<SimplifyQuery> &SQ)
const {
359 assert(
X->getType() == FremTy &&
Y->getType() == FremTy);
361 FastMathFlags FMF =
B.getFastMathFlags();
370 Value *Ax =
B.CreateUnaryIntrinsic(Intrinsic::fabs,
X, {},
"ax");
371 Value *Ay =
B.CreateUnaryIntrinsic(Intrinsic::fabs,
Y, {},
"ay");
372 if (ComputeFpTy !=
X->getType()) {
373 Ax =
B.CreateFPExt(Ax, ComputeFpTy,
"ax");
374 Ay =
B.CreateFPExt(Ay, ComputeFpTy,
"ay");
376 Value *AxAyCmp =
B.CreateFCmpOGT(Ax, Ay);
378 PHINode *RetPhi =
B.CreatePHI(FremTy, 2,
"ret");
384 Ret = handleInputCornerCases(Ret,
X,
Y, SQ, FMF.
noInfs());
391 auto SavedInsertPt =
B.GetInsertPoint();
399 FastMathFlags ComputeFMF = FMF;
403 B.SetInsertPoint(ThenBB);
404 buildRemainderComputation(Ax, Ay,
X, RetPhi, FMF);
408 B.SetInsertPoint(ElseBB);
409 buildElseBranch(Ax, Ay,
X, RetPhi);
412 B.SetInsertPoint(SavedInsertPt);
421 Type *Ty =
I.getType();
422 assert(FRemExpander::canExpandType(Ty) &&
423 "Expected supported floating point type");
431 B.setFastMathFlags(FMF);
432 B.SetCurrentDebugLocation(
I.getDebugLoc());
434 const FRemExpander Expander = FRemExpander::create(
B, Ty);
436 ? Expander.buildApproxFRem(
I.getOperand(0),
I.getOperand(1))
437 : Expander.buildFRem(
I.getOperand(0),
I.getOperand(1), SQ);
439 I.replaceAllUsesWith(Ret);
505 unsigned FPMantissaWidth = FloatVal->getType()->getFPMantissaWidth() - 1;
510 if (FloatVal->getType()->isHalfTy() &&
BitWidth >= 32) {
511 if (FPToI->
getOpcode() == Instruction::FPToUI) {
512 Value *A0 = Builder.CreateFPToUI(FloatVal, Builder.getInt32Ty());
513 A1 = Builder.CreateZExt(A0, IntTy);
515 Value *A0 = Builder.CreateFPToSI(FloatVal, Builder.getInt32Ty());
516 A1 = Builder.CreateSExt(A0, IntTy);
526 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
527 unsigned FloatWidth =
528 PowerOf2Ceil(FloatVal->getType()->getScalarSizeInBits());
529 unsigned ExponentWidth = FloatWidth - FPMantissaWidth - 1;
530 unsigned ExponentBias = (1 << (ExponentWidth - 1)) - 1;
532 Value *ImplicitBit = ConstantInt::get(
534 Value *SignificandMask = ConstantInt::get(
539 Entry->setName(
Twine(Entry->getName(),
"fp-to-i-entry"));
543 Builder.getContext(),
"fp-to-i-if-check.saturate",
F, End);
547 Builder.getContext(),
"fp-to-i-if-check.exp.size",
F, End);
553 Entry->getTerminator()->eraseFromParent();
556 Builder.SetInsertPoint(Entry);
557 Value *FloatVal0 = FloatVal;
560 if (FloatVal->getType()->isX86_FP80Ty())
563 Value *ARep = Builder.CreateBitCast(FloatVal0, FloatIntTy);
569 Builder.CreateLShr(ARep, Builder.getIntN(FloatWidth, FPMantissaWidth));
570 Value *BiasedExp = Builder.CreateAnd(
571 And, Builder.getIntN(FloatWidth, (1 << ExponentWidth) - 1),
"biased.exp");
572 Value *Abs = Builder.CreateAnd(ARep, SignificandMask);
573 Value *Significand = Builder.CreateOr(Abs, ImplicitBit,
"significand");
574 Value *ExpIsNegative = Builder.CreateICmpULT(
575 BiasedExp, Builder.getIntN(FloatWidth, ExponentBias),
"exp.is.negative");
576 Builder.CreateCondBr(ExpIsNegative, End, CheckSaturateBB);
579 Builder.SetInsertPoint(CheckSaturateBB);
580 Value *Add1 = Builder.CreateAdd(
583 -
static_cast<int64_t
>(ExponentBias +
BitWidth)));
584 Value *Cmp3 = Builder.CreateICmpULT(
587 Builder.CreateCondBr(Cmp3, SaturateBB, CheckExpSizeBB);
590 Builder.SetInsertPoint(SaturateBB);
596 Builder.CreateSelect(PosOrNeg, SignedMax, SignedMin,
"saturated");
597 Builder.CreateBr(End);
600 Builder.SetInsertPoint(CheckExpSizeBB);
601 Value *ExpSmallerMantissaWidth = Builder.CreateICmpULT(
602 BiasedExp, Builder.getIntN(FloatWidth, ExponentBias + FPMantissaWidth),
603 "exp.smaller.mantissa.width");
604 Builder.CreateCondBr(ExpSmallerMantissaWidth, ExpSmallBB, ExpLargeBB);
607 Builder.SetInsertPoint(ExpSmallBB);
608 Value *Sub13 = Builder.CreateSub(
609 Builder.getIntN(FloatWidth, ExponentBias + FPMantissaWidth), BiasedExp);
611 Builder.CreateZExtOrTrunc(Builder.CreateLShr(Significand, Sub13), IntTy);
612 Value *
Mul = Builder.CreateMul(Shr14, Sign);
613 Builder.CreateBr(End);
616 Builder.SetInsertPoint(ExpLargeBB);
617 Value *Sub15 = Builder.CreateAdd(
620 FloatIntTy, -
static_cast<int64_t
>(ExponentBias + FPMantissaWidth)));
621 Value *SignificandCast = Builder.CreateZExtOrTrunc(Significand, IntTy);
622 Value *Shl = Builder.CreateShl(SignificandCast,
623 Builder.CreateZExtOrTrunc(Sub15, IntTy));
624 Value *Mul16 = Builder.CreateMul(Shl, Sign);
625 Builder.CreateBr(End);
628 Builder.SetInsertPoint(End, End->
begin());
731 unsigned BitWidth = IntVal->getType()->getIntegerBitWidth();
735 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
738 FPMantissaWidth = FPMantissaWidth == 10 ? 23 : FPMantissaWidth;
739 FPMantissaWidth = FPMantissaWidth == 7 ? 23 : FPMantissaWidth;
741 bool IsSigned = IToFP->
getOpcode() == Instruction::SIToFP;
743 assert(
BitWidth > FloatWidth &&
"Unexpected conversion. expandIToFP() "
744 "assumes integer width is larger than fp.");
747 Builder.CreateShl(Builder.getIntN(
BitWidth, 1),
748 Builder.getIntN(
BitWidth, FPMantissaWidth + 3));
752 Entry->setName(
Twine(Entry->getName(),
"itofp-entry"));
772 Entry->getTerminator()->eraseFromParent();
779 Builder.SetInsertPoint(Entry);
781 Builder.CreateCondBr(Cmp, End, IfEnd);
784 Builder.SetInsertPoint(IfEnd);
787 Value *
Xor = Builder.CreateXor(Shr, IntVal);
789 Value *
Call = Builder.CreateCall(CTLZ, {IsSigned ?
Sub : IntVal, True});
790 Value *Cast = Builder.CreateTrunc(
Call, Builder.getInt32Ty());
791 int BitWidthNew = FloatWidth == 128 ?
BitWidth : 32;
792 Value *Sub1 = Builder.CreateSub(Builder.getIntN(BitWidthNew,
BitWidth),
793 FloatWidth == 128 ?
Call : Cast);
794 Value *Sub2 = Builder.CreateSub(Builder.getIntN(BitWidthNew,
BitWidth - 1),
795 FloatWidth == 128 ?
Call : Cast);
796 Value *Cmp3 = Builder.CreateICmpSGT(
797 Sub1, Builder.getIntN(BitWidthNew, FPMantissaWidth + 1));
798 Builder.CreateCondBr(Cmp3, IfThen4, IfElse);
801 Builder.SetInsertPoint(IfThen4);
803 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 2), SwBB);
804 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 3), SwEpilog);
807 Builder.SetInsertPoint(SwBB);
809 Builder.CreateShl(IsSigned ?
Sub : IntVal, Builder.getIntN(
BitWidth, 1));
810 Builder.CreateBr(SwEpilog);
813 Builder.SetInsertPoint(SwDefault);
814 Value *Sub5 = Builder.CreateSub(
815 Builder.getIntN(BitWidthNew,
BitWidth - FPMantissaWidth - 3),
816 FloatWidth == 128 ?
Call : Cast);
817 Value *ShProm = Builder.CreateZExt(Sub5, IntTy);
818 Value *Shr6 = Builder.CreateLShr(IsSigned ?
Sub : IntVal,
819 FloatWidth == 128 ? Sub5 : ShProm);
821 Builder.CreateAdd(FloatWidth == 128 ?
Call : Cast,
822 Builder.getIntN(BitWidthNew, FPMantissaWidth + 3));
823 Value *ShProm9 = Builder.CreateZExt(Sub8, IntTy);
825 FloatWidth == 128 ? Sub8 : ShProm9);
826 Value *
And = Builder.CreateAnd(Shr9, IsSigned ?
Sub : IntVal);
828 Value *Conv11 = Builder.CreateZExt(Cmp10, IntTy);
829 Value *
Or = Builder.CreateOr(Shr6, Conv11);
830 Builder.CreateBr(SwEpilog);
833 Builder.SetInsertPoint(SwEpilog);
834 PHINode *AAddr0 = Builder.CreatePHI(IntTy, 3);
838 Value *A0 = Builder.CreateTrunc(AAddr0, Builder.getInt32Ty());
839 Value *A1 = Builder.CreateLShr(A0, Builder.getInt32(2));
840 Value *A2 = Builder.CreateAnd(A1, Builder.getInt32(1));
841 Value *Conv16 = Builder.CreateZExt(A2, IntTy);
842 Value *Or17 = Builder.CreateOr(AAddr0, Conv16);
843 Value *Inc = Builder.CreateAdd(Or17, Builder.getIntN(
BitWidth, 1));
844 Value *Shr18 =
nullptr;
846 Shr18 = Builder.CreateAShr(Inc, Builder.getIntN(
BitWidth, 2));
848 Shr18 = Builder.CreateLShr(Inc, Builder.getIntN(
BitWidth, 2));
849 Value *A3 = Builder.CreateAnd(Inc, Temp1,
"a3");
850 Value *PosOrNeg = Builder.CreateICmpEQ(A3, Builder.getIntN(
BitWidth, 0));
851 Value *ExtractT60 = Builder.CreateTrunc(Shr18, Builder.getIntNTy(FloatWidth));
852 Value *Extract63 = Builder.CreateLShr(Shr18, Builder.getIntN(
BitWidth, 32));
853 Value *ExtractT64 =
nullptr;
855 ExtractT64 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
857 ExtractT64 = Builder.CreateTrunc(Extract63, Builder.getInt32Ty());
858 Builder.CreateCondBr(PosOrNeg, IfEnd26, IfThen20);
861 Builder.SetInsertPoint(IfThen20);
862 Value *Shr21 =
nullptr;
864 Shr21 = Builder.CreateAShr(Inc, Builder.getIntN(
BitWidth, 3));
866 Shr21 = Builder.CreateLShr(Inc, Builder.getIntN(
BitWidth, 3));
867 Value *ExtractT = Builder.CreateTrunc(Shr21, Builder.getIntNTy(FloatWidth));
868 Value *Extract = Builder.CreateLShr(Shr21, Builder.getIntN(
BitWidth, 32));
869 Value *ExtractT62 =
nullptr;
871 ExtractT62 = Builder.CreateTrunc(Sub1, Builder.getInt64Ty());
873 ExtractT62 = Builder.CreateTrunc(Extract, Builder.getInt32Ty());
874 Builder.CreateBr(IfEnd26);
877 Builder.SetInsertPoint(IfElse);
878 Value *Sub24 = Builder.CreateAdd(
879 FloatWidth == 128 ?
Call : Cast,
881 -(
int)(
BitWidth - FPMantissaWidth - 1)));
882 Value *ShProm25 = Builder.CreateZExt(Sub24, IntTy);
883 Value *Shl26 = Builder.CreateShl(IsSigned ?
Sub : IntVal,
884 FloatWidth == 128 ? Sub24 : ShProm25);
885 Value *ExtractT61 = Builder.CreateTrunc(Shl26, Builder.getIntNTy(FloatWidth));
886 Value *Extract65 = Builder.CreateLShr(Shl26, Builder.getIntN(
BitWidth, 32));
887 Value *ExtractT66 =
nullptr;
889 ExtractT66 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
891 ExtractT66 = Builder.CreateTrunc(Extract65, Builder.getInt32Ty());
892 Builder.CreateBr(IfEnd26);
895 Builder.SetInsertPoint(IfEnd26);
896 PHINode *AAddr1Off0 = Builder.CreatePHI(Builder.getIntNTy(FloatWidth), 3);
900 PHINode *AAddr1Off32 =
nullptr;
901 if (FloatWidth > 32) {
903 Builder.CreatePHI(Builder.getIntNTy(FloatWidth > 80 ? 64 : 32), 3);
909 if (FloatWidth <= 80) {
910 E0 = Builder.CreatePHI(Builder.getIntNTy(BitWidthNew), 3);
915 Value *And29 =
nullptr;
916 if (FloatWidth > 80) {
917 Value *Temp2 = Builder.CreateShl(Builder.getIntN(
BitWidth, 1),
919 And29 = Builder.CreateAnd(Shr, Temp2,
"and29");
921 Value *Conv28 = Builder.CreateTrunc(Shr, Builder.getInt32Ty());
922 And29 = Builder.CreateAnd(
925 unsigned TempMod = FPMantissaWidth % 32;
926 Value *And34 =
nullptr;
927 Value *Shl30 =
nullptr;
928 if (FloatWidth > 80) {
930 Value *
Add = Builder.CreateShl(AAddr1Off32, Builder.getInt64(TempMod));
931 Shl30 = Builder.CreateAdd(
932 Add, Builder.getInt64(((1ull << (62ull - TempMod)) - 1ull) << TempMod));
933 And34 = Builder.CreateZExt(Shl30, Builder.getInt128Ty());
935 Value *
Add = Builder.CreateShl(E0, Builder.getInt32(TempMod));
936 Shl30 = Builder.CreateAdd(
937 Add, Builder.getInt32(((1 << (30 - TempMod)) - 1) << TempMod));
938 And34 = Builder.CreateAnd(FloatWidth > 32 ? AAddr1Off32 : AAddr1Off0,
939 Builder.getInt32((1 << TempMod) - 1));
941 Value *Or35 =
nullptr;
942 if (FloatWidth > 80) {
943 Value *And29Trunc = Builder.CreateTrunc(And29, Builder.getInt128Ty());
944 Value *Or31 = Builder.CreateOr(And29Trunc, And34);
945 Value *Or34 = Builder.CreateShl(Or31, Builder.getIntN(128, 64));
946 Value *Temp3 = Builder.CreateShl(Builder.getIntN(128, 1),
947 Builder.getIntN(128, FPMantissaWidth));
948 Value *Temp4 = Builder.CreateSub(Temp3, Builder.getIntN(128, 1));
949 Value *A6 = Builder.CreateAnd(AAddr1Off0, Temp4);
950 Or35 = Builder.CreateOr(Or34, A6);
952 Value *Or31 = Builder.CreateOr(And34, And29);
953 Or35 = Builder.CreateOr(IsSigned ? Or31 : And34, Shl30);
957 Value *ZExt1 = Builder.CreateZExt(Or35, Builder.getIntNTy(FloatWidth));
958 Value *Shl1 = Builder.CreateShl(ZExt1, Builder.getIntN(FloatWidth, 32));
960 Builder.CreateAnd(AAddr1Off0, Builder.getIntN(FloatWidth, 0xFFFFFFFF));
961 Value *Or1 = Builder.CreateOr(Shl1, And1);
962 A4 = Builder.CreateBitCast(Or1, IToFP->
getType());
966 A4 = Builder.CreateFPTrunc(A40, IToFP->
getType());
972 A4 = Builder.CreateFPTrunc(A40, IToFP->
getType());
974 A4 = Builder.CreateBitCast(Or35, IToFP->
getType());
975 Builder.CreateBr(End);
978 Builder.SetInsertPoint(End, End->
begin());
994 unsigned NumElements = VTy->getElementCount().getFixedValue();
996 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
997 Value *Ext = Builder.CreateExtractElement(
I->getOperand(0), Idx);
999 Value *NewOp =
nullptr;
1001 NewOp = Builder.CreateBinOp(
1002 BinOp->getOpcode(), Ext,
1003 Builder.CreateExtractElement(
I->getOperand(1), Idx));
1005 NewOp = Builder.CreateCast(CastI->getOpcode(), Ext,
1006 I->getType()->getScalarType());
1010 Result = Builder.CreateInsertElement(Result, NewOp, Idx);
1012 ScalarizedI->copyIRFlags(
I,
true);
1017 I->replaceAllUsesWith(Result);
1018 I->dropAllReferences();
1019 I->eraseFromParent();
1024 if (
I.getOperand(0)->getType()->isVectorTy())
1034 unsigned MaxLegalFpConvertBitWidth =
1043 bool DisableExpandLargeFp =
1045 bool DisableExpandLargeDivRem =
1047 bool DisableFrem = !FRemExpander::shouldExpandAnyFremType(TLI);
1049 if (DisableExpandLargeFp && DisableFrem && DisableExpandLargeDivRem)
1053 Type *Ty =
I.getType();
1055 if (Ty->isScalableTy())
1058 switch (
I.getOpcode()) {
1059 case Instruction::FRem:
1060 return !DisableFrem && FRemExpander::shouldExpandFremType(TLI, Ty);
1061 case Instruction::FPToUI:
1062 case Instruction::FPToSI:
1063 return !DisableExpandLargeFp &&
1065 MaxLegalFpConvertBitWidth;
1066 case Instruction::UIToFP:
1067 case Instruction::SIToFP:
1068 return !DisableExpandLargeFp &&
1070 ->getIntegerBitWidth() > MaxLegalFpConvertBitWidth;
1071 case Instruction::UDiv:
1072 case Instruction::SDiv:
1073 case Instruction::URem:
1074 case Instruction::SRem:
1075 return !DisableExpandLargeDivRem &&
1077 MaxLegalDivRemBitWidth
1080 && !isConstantPowerOfTwo(
I.getOperand(1), isSigned(
I.getOpcode()));
1089 if (!ShouldHandleInst(
I))
1096 while (!Worklist.
empty()) {
1099 switch (
I->getOpcode()) {
1100 case Instruction::FRem: {
1101 auto SQ = [&]() -> std::optional<SimplifyQuery> {
1103 auto Res = std::make_optional<SimplifyQuery>(
1104 I->getModule()->getDataLayout(),
I);
1115 case Instruction::FPToUI:
1116 case Instruction::FPToSI:
1120 case Instruction::UIToFP:
1121 case Instruction::SIToFP:
1125 case Instruction::UDiv:
1126 case Instruction::SDiv:
1129 case Instruction::URem:
1130 case Instruction::SRem:
1140class ExpandIRInstsLegacyPass :
public FunctionPass {
1147 : FunctionPass(
ID), OptLevel(OptLevel) {}
1152 auto *TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1153 const TargetSubtargetInfo *Subtarget = TM->getSubtargetImpl(
F);
1154 auto *TLI = Subtarget->getTargetLowering();
1155 AssumptionCache *AC =
nullptr;
1157 const LibcallLoweringInfo &Libcalls =
1158 getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
1159 *
F.getParent(), *Subtarget);
1161 if (OptLevel != CodeGenOptLevel::None && !
F.hasOptNone())
1162 AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
1163 return runImpl(
F, *TLI, Libcalls, AC);
1166 void getAnalysisUsage(AnalysisUsage &AU)
const override {
1169 if (OptLevel != CodeGenOptLevel::None)
1180 : TM(&TM), OptLevel(OptLevel) {}
1185 OS, MapClassName2PassName);
1187 OS <<
"O" << (int)OptLevel;
1204 if (!LibcallLowering) {
1206 "' analysis required");
1211 LibcallLowering->getLibcallLowering(*STI);
1217char ExpandIRInstsLegacyPass::ID = 0;
1219 "Expand certain fp instructions",
false,
false)
1225 return new ExpandIRInstsLegacyPass(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 cl::opt< unsigned > ExpandDivRemBits("expand-div-rem-bits", cl::Hidden, cl::init(llvm::IntegerType::MAX_INT_BITS), cl::desc("div and rem instructions on integers with " "more than <N> bits are expanded."))
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 &)
Class for arbitrary precision integers.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
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, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
ExpandIRInstsPass(const TargetMachine &TM, CodeGenOptLevel OptLevel)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
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 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 getMaxDivRemBitWidthSupported() const
Returns the size in bits of the maximum div/rem the backend supports.
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 IntegerType * getIntNTy(LLVMContext &C, unsigned N)
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.
@ C
The default llvm calling convention, compatible with C.
@ 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 expandDivision(BinaryOperator *Div)
Generate code to divide two integers, replacing Div with the generated code.
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.
LLVM_ABI FunctionPass * createExpandIRInstsPass(CodeGenOptLevel)
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 >
@ 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 bool expandRemainder(BinaryOperator *Rem)
Generate code to calculate the remainder of two integers, replacing Rem with the generated code.
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.