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()) {
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;
531 Value *ImplicitBit = Builder.CreateShl(
533 Value *SignificandMask =
534 Builder.CreateSub(ImplicitBit, Builder.getIntN(
BitWidth, 1));
535 Value *NegOne = Builder.CreateSExt(
543 Entry->setName(
Twine(Entry->getName(),
"fp-to-i-entry"));
557 Entry->getTerminator()->eraseFromParent();
560 Builder.SetInsertPoint(Entry);
561 Value *FloatVal0 = FloatVal;
564 if (FloatVal->getType()->isX86_FP80Ty())
568 Builder.CreateBitCast(FloatVal0, Builder.getIntNTy(FloatWidth));
569 Value *ARep = Builder.CreateZExt(ARep0, FPToI->
getType());
570 Value *PosOrNeg = Builder.CreateICmpSGT(
575 Builder.CreateLShr(ARep, Builder.getIntN(
BitWidth, FPMantissaWidth));
576 Value *And2 = Builder.CreateAnd(
577 And, Builder.getIntN(
BitWidth, (1 << ExponentWidth) - 1));
578 Value *Abs = Builder.CreateAnd(ARep, SignificandMask);
579 Value *
Or = Builder.CreateOr(Abs, ImplicitBit);
581 Builder.CreateICmpULT(And2, Builder.getIntN(
BitWidth, ExponentBias));
582 Builder.CreateCondBr(Cmp, End, IfEnd);
585 Builder.SetInsertPoint(IfEnd);
586 Value *Add1 = Builder.CreateAdd(
588 IntTy, -
static_cast<int64_t
>(ExponentBias +
BitWidth)));
589 Value *Cmp3 = Builder.CreateICmpULT(
591 Builder.CreateCondBr(Cmp3, IfThen5, IfEnd9);
594 Builder.SetInsertPoint(IfThen5);
595 Value *PosInf = Builder.CreateXor(NegOne, NegInf);
596 Value *Cond8 = Builder.CreateSelect(PosOrNeg, PosInf, NegInf);
597 Builder.CreateBr(End);
600 Builder.SetInsertPoint(IfEnd9);
601 Value *Cmp10 = Builder.CreateICmpULT(
602 And2, Builder.getIntN(
BitWidth, ExponentBias + FPMantissaWidth));
603 Builder.CreateCondBr(Cmp10, IfThen12, IfElse);
606 Builder.SetInsertPoint(IfThen12);
607 Value *Sub13 = Builder.CreateSub(
608 Builder.getIntN(
BitWidth, ExponentBias + FPMantissaWidth), And2);
609 Value *Shr14 = Builder.CreateLShr(
Or, Sub13);
610 Value *
Mul = Builder.CreateMul(Shr14, Sign);
611 Builder.CreateBr(End);
614 Builder.SetInsertPoint(IfElse);
615 Value *Sub15 = Builder.CreateAdd(
617 IntTy, -
static_cast<int64_t
>(ExponentBias + FPMantissaWidth)));
618 Value *Shl = Builder.CreateShl(
Or, Sub15);
619 Value *Mul16 = Builder.CreateMul(Shl, Sign);
620 Builder.CreateBr(End);
623 Builder.SetInsertPoint(End, End->
begin());
726 unsigned BitWidth = IntVal->getType()->getIntegerBitWidth();
730 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
733 FPMantissaWidth = FPMantissaWidth == 10 ? 23 : FPMantissaWidth;
734 FPMantissaWidth = FPMantissaWidth == 7 ? 23 : FPMantissaWidth;
736 bool IsSigned = IToFP->
getOpcode() == Instruction::SIToFP;
738 assert(
BitWidth > FloatWidth &&
"Unexpected conversion. expandIToFP() "
739 "assumes integer width is larger than fp.");
742 Builder.CreateShl(Builder.getIntN(
BitWidth, 1),
743 Builder.getIntN(
BitWidth, FPMantissaWidth + 3));
747 Entry->setName(
Twine(Entry->getName(),
"itofp-entry"));
767 Entry->getTerminator()->eraseFromParent();
774 Builder.SetInsertPoint(Entry);
776 Builder.CreateCondBr(Cmp, End, IfEnd);
779 Builder.SetInsertPoint(IfEnd);
782 Value *
Xor = Builder.CreateXor(Shr, IntVal);
784 Value *
Call = Builder.CreateCall(CTLZ, {IsSigned ?
Sub : IntVal, True});
785 Value *Cast = Builder.CreateTrunc(
Call, Builder.getInt32Ty());
786 int BitWidthNew = FloatWidth == 128 ?
BitWidth : 32;
787 Value *Sub1 = Builder.CreateSub(Builder.getIntN(BitWidthNew,
BitWidth),
788 FloatWidth == 128 ?
Call : Cast);
789 Value *Sub2 = Builder.CreateSub(Builder.getIntN(BitWidthNew,
BitWidth - 1),
790 FloatWidth == 128 ?
Call : Cast);
791 Value *Cmp3 = Builder.CreateICmpSGT(
792 Sub1, Builder.getIntN(BitWidthNew, FPMantissaWidth + 1));
793 Builder.CreateCondBr(Cmp3, IfThen4, IfElse);
796 Builder.SetInsertPoint(IfThen4);
798 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 2), SwBB);
799 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 3), SwEpilog);
802 Builder.SetInsertPoint(SwBB);
804 Builder.CreateShl(IsSigned ?
Sub : IntVal, Builder.getIntN(
BitWidth, 1));
805 Builder.CreateBr(SwEpilog);
808 Builder.SetInsertPoint(SwDefault);
809 Value *Sub5 = Builder.CreateSub(
810 Builder.getIntN(BitWidthNew,
BitWidth - FPMantissaWidth - 3),
811 FloatWidth == 128 ?
Call : Cast);
812 Value *ShProm = Builder.CreateZExt(Sub5, IntTy);
813 Value *Shr6 = Builder.CreateLShr(IsSigned ?
Sub : IntVal,
814 FloatWidth == 128 ? Sub5 : ShProm);
816 Builder.CreateAdd(FloatWidth == 128 ?
Call : Cast,
817 Builder.getIntN(BitWidthNew, FPMantissaWidth + 3));
818 Value *ShProm9 = Builder.CreateZExt(Sub8, IntTy);
820 FloatWidth == 128 ? Sub8 : ShProm9);
821 Value *
And = Builder.CreateAnd(Shr9, IsSigned ?
Sub : IntVal);
823 Value *Conv11 = Builder.CreateZExt(Cmp10, IntTy);
824 Value *
Or = Builder.CreateOr(Shr6, Conv11);
825 Builder.CreateBr(SwEpilog);
828 Builder.SetInsertPoint(SwEpilog);
829 PHINode *AAddr0 = Builder.CreatePHI(IntTy, 3);
833 Value *A0 = Builder.CreateTrunc(AAddr0, Builder.getInt32Ty());
834 Value *A1 = Builder.CreateLShr(A0, Builder.getInt32(2));
835 Value *A2 = Builder.CreateAnd(A1, Builder.getInt32(1));
836 Value *Conv16 = Builder.CreateZExt(A2, IntTy);
837 Value *Or17 = Builder.CreateOr(AAddr0, Conv16);
838 Value *Inc = Builder.CreateAdd(Or17, Builder.getIntN(
BitWidth, 1));
839 Value *Shr18 =
nullptr;
841 Shr18 = Builder.CreateAShr(Inc, Builder.getIntN(
BitWidth, 2));
843 Shr18 = Builder.CreateLShr(Inc, Builder.getIntN(
BitWidth, 2));
844 Value *A3 = Builder.CreateAnd(Inc, Temp1,
"a3");
845 Value *PosOrNeg = Builder.CreateICmpEQ(A3, Builder.getIntN(
BitWidth, 0));
846 Value *ExtractT60 = Builder.CreateTrunc(Shr18, Builder.getIntNTy(FloatWidth));
847 Value *Extract63 = Builder.CreateLShr(Shr18, Builder.getIntN(
BitWidth, 32));
848 Value *ExtractT64 =
nullptr;
850 ExtractT64 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
852 ExtractT64 = Builder.CreateTrunc(Extract63, Builder.getInt32Ty());
853 Builder.CreateCondBr(PosOrNeg, IfEnd26, IfThen20);
856 Builder.SetInsertPoint(IfThen20);
857 Value *Shr21 =
nullptr;
859 Shr21 = Builder.CreateAShr(Inc, Builder.getIntN(
BitWidth, 3));
861 Shr21 = Builder.CreateLShr(Inc, Builder.getIntN(
BitWidth, 3));
862 Value *ExtractT = Builder.CreateTrunc(Shr21, Builder.getIntNTy(FloatWidth));
863 Value *Extract = Builder.CreateLShr(Shr21, Builder.getIntN(
BitWidth, 32));
864 Value *ExtractT62 =
nullptr;
866 ExtractT62 = Builder.CreateTrunc(Sub1, Builder.getInt64Ty());
868 ExtractT62 = Builder.CreateTrunc(Extract, Builder.getInt32Ty());
869 Builder.CreateBr(IfEnd26);
872 Builder.SetInsertPoint(IfElse);
873 Value *Sub24 = Builder.CreateAdd(
874 FloatWidth == 128 ?
Call : Cast,
876 -(
int)(
BitWidth - FPMantissaWidth - 1)));
877 Value *ShProm25 = Builder.CreateZExt(Sub24, IntTy);
878 Value *Shl26 = Builder.CreateShl(IsSigned ?
Sub : IntVal,
879 FloatWidth == 128 ? Sub24 : ShProm25);
880 Value *ExtractT61 = Builder.CreateTrunc(Shl26, Builder.getIntNTy(FloatWidth));
881 Value *Extract65 = Builder.CreateLShr(Shl26, Builder.getIntN(
BitWidth, 32));
882 Value *ExtractT66 =
nullptr;
884 ExtractT66 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
886 ExtractT66 = Builder.CreateTrunc(Extract65, Builder.getInt32Ty());
887 Builder.CreateBr(IfEnd26);
890 Builder.SetInsertPoint(IfEnd26);
891 PHINode *AAddr1Off0 = Builder.CreatePHI(Builder.getIntNTy(FloatWidth), 3);
895 PHINode *AAddr1Off32 =
nullptr;
896 if (FloatWidth > 32) {
898 Builder.CreatePHI(Builder.getIntNTy(FloatWidth > 80 ? 64 : 32), 3);
904 if (FloatWidth <= 80) {
905 E0 = Builder.CreatePHI(Builder.getIntNTy(BitWidthNew), 3);
910 Value *And29 =
nullptr;
911 if (FloatWidth > 80) {
912 Value *Temp2 = Builder.CreateShl(Builder.getIntN(
BitWidth, 1),
914 And29 = Builder.CreateAnd(Shr, Temp2,
"and29");
916 Value *Conv28 = Builder.CreateTrunc(Shr, Builder.getInt32Ty());
917 And29 = Builder.CreateAnd(
920 unsigned TempMod = FPMantissaWidth % 32;
921 Value *And34 =
nullptr;
922 Value *Shl30 =
nullptr;
923 if (FloatWidth > 80) {
925 Value *
Add = Builder.CreateShl(AAddr1Off32, Builder.getInt64(TempMod));
926 Shl30 = Builder.CreateAdd(
927 Add, Builder.getInt64(((1ull << (62ull - TempMod)) - 1ull) << TempMod));
928 And34 = Builder.CreateZExt(Shl30, Builder.getInt128Ty());
930 Value *
Add = Builder.CreateShl(E0, Builder.getInt32(TempMod));
931 Shl30 = Builder.CreateAdd(
932 Add, Builder.getInt32(((1 << (30 - TempMod)) - 1) << TempMod));
933 And34 = Builder.CreateAnd(FloatWidth > 32 ? AAddr1Off32 : AAddr1Off0,
934 Builder.getInt32((1 << TempMod) - 1));
936 Value *Or35 =
nullptr;
937 if (FloatWidth > 80) {
938 Value *And29Trunc = Builder.CreateTrunc(And29, Builder.getInt128Ty());
939 Value *Or31 = Builder.CreateOr(And29Trunc, And34);
940 Value *Or34 = Builder.CreateShl(Or31, Builder.getIntN(128, 64));
941 Value *Temp3 = Builder.CreateShl(Builder.getIntN(128, 1),
942 Builder.getIntN(128, FPMantissaWidth));
943 Value *Temp4 = Builder.CreateSub(Temp3, Builder.getIntN(128, 1));
944 Value *A6 = Builder.CreateAnd(AAddr1Off0, Temp4);
945 Or35 = Builder.CreateOr(Or34, A6);
947 Value *Or31 = Builder.CreateOr(And34, And29);
948 Or35 = Builder.CreateOr(IsSigned ? Or31 : And34, Shl30);
952 Value *ZExt1 = Builder.CreateZExt(Or35, Builder.getIntNTy(FloatWidth));
953 Value *Shl1 = Builder.CreateShl(ZExt1, Builder.getIntN(FloatWidth, 32));
955 Builder.CreateAnd(AAddr1Off0, Builder.getIntN(FloatWidth, 0xFFFFFFFF));
956 Value *Or1 = Builder.CreateOr(Shl1, And1);
957 A4 = Builder.CreateBitCast(Or1, IToFP->
getType());
961 A4 = Builder.CreateFPTrunc(A40, IToFP->
getType());
967 A4 = Builder.CreateFPTrunc(A40, IToFP->
getType());
969 A4 = Builder.CreateBitCast(Or35, IToFP->
getType());
970 Builder.CreateBr(End);
973 Builder.SetInsertPoint(End, End->
begin());
989 unsigned NumElements = VTy->getElementCount().getFixedValue();
991 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
992 Value *Ext = Builder.CreateExtractElement(
I->getOperand(0), Idx);
994 Value *NewOp =
nullptr;
996 NewOp = Builder.CreateBinOp(
997 BinOp->getOpcode(), Ext,
998 Builder.CreateExtractElement(
I->getOperand(1), Idx));
1000 NewOp = Builder.CreateCast(CastI->getOpcode(), Ext,
1001 I->getType()->getScalarType());
1005 Result = Builder.CreateInsertElement(Result, NewOp, Idx);
1007 ScalarizedI->copyIRFlags(
I,
true);
1012 I->replaceAllUsesWith(Result);
1013 I->dropAllReferences();
1014 I->eraseFromParent();
1019 if (
I.getOperand(0)->getType()->isVectorTy())
1029 unsigned MaxLegalFpConvertBitWidth =
1038 bool DisableExpandLargeFp =
1040 bool DisableExpandLargeDivRem =
1042 bool DisableFrem = !FRemExpander::shouldExpandAnyFremType(TLI);
1044 if (DisableExpandLargeFp && DisableFrem && DisableExpandLargeDivRem)
1048 Type *Ty =
I.getType();
1050 if (Ty->isScalableTy())
1053 switch (
I.getOpcode()) {
1054 case Instruction::FRem:
1055 return !DisableFrem && FRemExpander::shouldExpandFremType(TLI, Ty);
1056 case Instruction::FPToUI:
1057 case Instruction::FPToSI:
1058 return !DisableExpandLargeFp &&
1060 MaxLegalFpConvertBitWidth;
1061 case Instruction::UIToFP:
1062 case Instruction::SIToFP:
1063 return !DisableExpandLargeFp &&
1065 ->getIntegerBitWidth() > MaxLegalFpConvertBitWidth;
1066 case Instruction::UDiv:
1067 case Instruction::SDiv:
1068 case Instruction::URem:
1069 case Instruction::SRem:
1070 return !DisableExpandLargeDivRem &&
1072 MaxLegalDivRemBitWidth
1075 && !isConstantPowerOfTwo(
I.getOperand(1), isSigned(
I.getOpcode()));
1084 if (!ShouldHandleInst(
I))
1091 while (!Worklist.
empty()) {
1094 switch (
I->getOpcode()) {
1095 case Instruction::FRem: {
1096 auto SQ = [&]() -> std::optional<SimplifyQuery> {
1098 auto Res = std::make_optional<SimplifyQuery>(
1099 I->getModule()->getDataLayout(),
I);
1110 case Instruction::FPToUI:
1111 case Instruction::FPToSI:
1115 case Instruction::UIToFP:
1116 case Instruction::SIToFP:
1120 case Instruction::UDiv:
1121 case Instruction::SDiv:
1124 case Instruction::URem:
1125 case Instruction::SRem:
1135class ExpandIRInstsLegacyPass :
public FunctionPass {
1142 : FunctionPass(
ID), OptLevel(OptLevel) {
1149 auto *TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1150 const TargetSubtargetInfo *Subtarget = TM->getSubtargetImpl(
F);
1151 auto *TLI = Subtarget->getTargetLowering();
1152 AssumptionCache *AC =
nullptr;
1154 const LibcallLoweringInfo &Libcalls =
1155 getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
1158 if (OptLevel != CodeGenOptLevel::None && !
F.hasOptNone())
1159 AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
1160 return runImpl(
F, *TLI, Libcalls, AC);
1163 void getAnalysisUsage(AnalysisUsage &AU)
const override {
1166 if (OptLevel != CodeGenOptLevel::None)
1177 : TM(&TM), OptLevel(OptLevel) {}
1182 OS, MapClassName2PassName);
1184 OS <<
"O" << (int)OptLevel;
1201 if (!LibcallLowering) {
1203 "' analysis required");
1208 LibcallLowering->getLibcallLowering(*STI);
1214char ExpandIRInstsLegacyPass::ID = 0;
1216 "Expand certain fp instructions",
false,
false)
1222 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.
bool isNegative() const
Determine sign of this APInt.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
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.
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 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 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 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.
LLVM_ABI void initializeExpandIRInstsLegacyPassPass(PassRegistry &)
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.
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
constexpr 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) 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.
LLVM_ABI FunctionPass * createExpandIRInstsPass()
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.