https://github.com/PiJoules created https://github.com/llvm/llvm-project/pull/144612
This saves about 3kB on embedded project. >From 9f179e644ddadba15f51d45479b20744b66f6291 Mon Sep 17 00:00:00 2001 From: Leonard Chan <leonardc...@google.com> Date: Tue, 17 Jun 2025 15:06:10 -0700 Subject: [PATCH] [WIP][llvm] Flag to forcibly outline fixed point mul/div intrinsics This saves about 3kB on embedded project. --- clang/include/clang/Basic/CodeGenOptions.def | 3 + clang/include/clang/Driver/Options.td | 9 +++ clang/lib/CodeGen/CGExprScalar.cpp | 8 +- clang/lib/Driver/ToolChains/Clang.cpp | 3 + llvm/include/llvm/IR/FixedPointBuilder.h | 78 +++++++++++++++++--- 5 files changed, 89 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index e5566a540dc65..6cf06196bd2d5 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -483,6 +483,9 @@ CODEGENOPT(StaticClosure, 1, 0) /// Assume that UAVs/SRVs may alias CODEGENOPT(ResMayAlias, 1, 0) +/// Outline fixed point multiplication and division intrinsics. +CODEGENOPT(OutlineFixedPointMulDiv, 1, 0) + /// Controls how unwind v2 (epilog) information should be generated for x64 /// Windows. ENUM_CODEGENOPT(WinX64EHUnwindV2, llvm::WinX64EHUnwindV2Mode, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 72d564e1ba0be..899b563f97bba 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2741,6 +2741,15 @@ defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", " of the target's native float-to-int conversion instructions">, PosFlag<SetTrue, [], [ClangOption], "Assume that overflowing float-to-int casts are undefined (default)">>; +defm outline_fixed_point_mul_div_intrinsics + : BoolFOption< + "outline-fixed-point-mul-div-intrinsics", + CodeGenOpts<"OutlineFixedPointMulDiv">, DefaultFalse, + NegFlag<SetFalse, [], [ClangOption, CC1Option], "Do not outline ">, + PosFlag<SetTrue, [], [ClangOption, CC1Option], "Outline ">, + BothFlags<[], [ClangOption, CC1Option], + "the fixed point multiplication and division intrinsics">>; + defm protect_parens : BoolFOption<"protect-parens", LangOpts<"ProtectParens">, DefaultFalse, PosFlag<SetTrue, [], [ClangOption, CLOption, CC1Option], diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 193710bef2d16..e8de96dedc90a 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4543,11 +4543,15 @@ Value *ScalarExprEmitter::EmitFixedPointBinOp(const BinOpInfo &op) { break; case BO_MulAssign: case BO_Mul: - Result = FPBuilder.CreateMul(LHS, LHSFixedSema, RHS, RHSFixedSema); + Result = + FPBuilder.CreateMul(LHS, LHSFixedSema, RHS, RHSFixedSema, + CGF.CGM.getCodeGenOpts().OutlineFixedPointMulDiv); break; case BO_DivAssign: case BO_Div: - Result = FPBuilder.CreateDiv(LHS, LHSFixedSema, RHS, RHSFixedSema); + Result = + FPBuilder.CreateDiv(LHS, LHSFixedSema, RHS, RHSFixedSema, + CGF.CGM.getCodeGenOpts().OutlineFixedPointMulDiv); break; case BO_ShlAssign: case BO_Shl: diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 7dfed3a3356bb..e18feae4e2059 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6369,6 +6369,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fexperimental_omit_vtable_rtti, options::OPT_fno_experimental_omit_vtable_rtti); + Args.AddLastArg(CmdArgs, options::OPT_foutline_fixed_point_mul_div_intrinsics, + options::OPT_fno_outline_fixed_point_mul_div_intrinsics); + if (Arg *A = Args.getLastArg(options::OPT_ffuchsia_api_level_EQ)) A->render(Args, CmdArgs); diff --git a/llvm/include/llvm/IR/FixedPointBuilder.h b/llvm/include/llvm/IR/FixedPointBuilder.h index 1a22dd6b60936..ec983c96ab7b8 100644 --- a/llvm/include/llvm/IR/FixedPointBuilder.h +++ b/llvm/include/llvm/IR/FixedPointBuilder.h @@ -132,6 +132,44 @@ template <class IRBuilderTy> class FixedPointBuilder { return Type::getFloatingPointTy(Ty->getContext(), *FloatSema); } + static SmallString<16> GetOutlinedFuncName(StringRef OpName, bool Saturated, + unsigned Scale) { + SmallString<16> OutlinedFuncName("__outlined_"); + OutlinedFuncName += OpName; + OutlinedFuncName += "_fix"; + if (Saturated) + OutlinedFuncName += "_sat"; + OutlinedFuncName += "_"; + OutlinedFuncName += std::to_string(Scale); + return OutlinedFuncName; + } + + Value *CallFixedPointIntrinsicWrapper(Intrinsic::ID IID, + StringRef OutlinedFuncName, + Value *WideLHS, Value *WideRHS, + unsigned Scale) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + FunctionCallee Callee = + M->getOrInsertFunction(OutlinedFuncName, WideLHS->getType(), + WideLHS->getType(), WideRHS->getType()); + Function *OutlinedFunc = cast<Function>(Callee.getCallee()); + if (OutlinedFunc->empty()) { + BasicBlock *BB = + BasicBlock::Create(M->getContext(), "entry", OutlinedFunc); + IRBuilder<> Builder(BB); + Value *V = Builder.CreateIntrinsic(IID, {WideLHS->getType()}, + {OutlinedFunc->getArg(0), + OutlinedFunc->getArg(1), + Builder.getInt32(Scale)}); + Builder.CreateRet(V); + + Comdat *C = M->getOrInsertComdat(OutlinedFuncName); + OutlinedFunc->setComdat(C); + OutlinedFunc->addFnAttr(Attribute::NoInline); + } + return B.CreateCall(Callee, {WideLHS, WideRHS}); + } + public: FixedPointBuilder(IRBuilderTy &Builder) : B(Builder) {} @@ -285,8 +323,8 @@ template <class IRBuilderTy> class FixedPointBuilder { /// \p LHSSema - The semantic of the left hand side /// \p RHS - The right hand side /// \p RHSSema - The semantic of the right hand side - Value *CreateMul(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { + Value *CreateMul(Value *LHS, const FixedPointSemantics &LHSSema, Value *RHS, + const FixedPointSemantics &RHSSema, bool Outlined = false) { auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); bool UseSigned = CommonSema.isSigned() || CommonSema.hasUnsignedPadding(); @@ -299,9 +337,19 @@ template <class IRBuilderTy> class FixedPointBuilder { } else { IID = UseSigned ? Intrinsic::smul_fix : Intrinsic::umul_fix; } - Value *Result = B.CreateIntrinsic( - IID, {WideLHS->getType()}, - {WideLHS, WideRHS, B.getInt32(CommonSema.getScale())}); + + Value *Result; + if (!Outlined) { + Result = B.CreateIntrinsic( + IID, {WideLHS->getType()}, + {WideLHS, WideRHS, B.getInt32(CommonSema.getScale())}); + } else { + auto OutlinedFuncName = + GetOutlinedFuncName(UseSigned ? "smul" : "umul", + CommonSema.isSaturated(), CommonSema.getScale()); + Result = CallFixedPointIntrinsicWrapper(IID, OutlinedFuncName, WideLHS, + WideRHS, CommonSema.getScale()); + } return CreateFixedToFixed(Result, CommonSema, LHSSema.getCommonSemantics(RHSSema)); @@ -313,8 +361,8 @@ template <class IRBuilderTy> class FixedPointBuilder { /// \p LHSSema - The semantic of the left hand side /// \p RHS - The right hand side /// \p RHSSema - The semantic of the right hand side - Value *CreateDiv(Value *LHS, const FixedPointSemantics &LHSSema, - Value *RHS, const FixedPointSemantics &RHSSema) { + Value *CreateDiv(Value *LHS, const FixedPointSemantics &LHSSema, Value *RHS, + const FixedPointSemantics &RHSSema, bool Outlined = false) { auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema); bool UseSigned = CommonSema.isSigned() || CommonSema.hasUnsignedPadding(); @@ -327,9 +375,19 @@ template <class IRBuilderTy> class FixedPointBuilder { } else { IID = UseSigned ? Intrinsic::sdiv_fix : Intrinsic::udiv_fix; } - Value *Result = B.CreateIntrinsic( - IID, {WideLHS->getType()}, - {WideLHS, WideRHS, B.getInt32(CommonSema.getScale())}); + + Value *Result; + if (!Outlined) { + Result = B.CreateIntrinsic( + IID, {WideLHS->getType()}, + {WideLHS, WideRHS, B.getInt32(CommonSema.getScale())}); + } else { + auto OutlinedFuncName = + GetOutlinedFuncName(UseSigned ? "sdiv" : "udiv", + CommonSema.isSaturated(), CommonSema.getScale()); + Result = CallFixedPointIntrinsicWrapper(IID, OutlinedFuncName, WideLHS, + WideRHS, CommonSema.getScale()); + } return CreateFixedToFixed(Result, CommonSema, LHSSema.getCommonSemantics(RHSSema)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits