Skip to content

Commit 9f179e6

Browse files
committed
[WIP][llvm] Flag to forcibly outline fixed point mul/div intrinsics
This saves about 3kB on embedded project.
1 parent 99e53cb commit 9f179e6

File tree

5 files changed

+89
-12
lines changed

5 files changed

+89
-12
lines changed

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,9 @@ CODEGENOPT(StaticClosure, 1, 0)
483483
/// Assume that UAVs/SRVs may alias
484484
CODEGENOPT(ResMayAlias, 1, 0)
485485

486+
/// Outline fixed point multiplication and division intrinsics.
487+
CODEGENOPT(OutlineFixedPointMulDiv, 1, 0)
488+
486489
/// Controls how unwind v2 (epilog) information should be generated for x64
487490
/// Windows.
488491
ENUM_CODEGENOPT(WinX64EHUnwindV2, llvm::WinX64EHUnwindV2Mode,

clang/include/clang/Driver/Options.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,6 +2741,15 @@ defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow",
27412741
" of the target's native float-to-int conversion instructions">,
27422742
PosFlag<SetTrue, [], [ClangOption], "Assume that overflowing float-to-int casts are undefined (default)">>;
27432743

2744+
defm outline_fixed_point_mul_div_intrinsics
2745+
: BoolFOption<
2746+
"outline-fixed-point-mul-div-intrinsics",
2747+
CodeGenOpts<"OutlineFixedPointMulDiv">, DefaultFalse,
2748+
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Do not outline ">,
2749+
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Outline ">,
2750+
BothFlags<[], [ClangOption, CC1Option],
2751+
"the fixed point multiplication and division intrinsics">>;
2752+
27442753
defm protect_parens : BoolFOption<"protect-parens",
27452754
LangOpts<"ProtectParens">, DefaultFalse,
27462755
PosFlag<SetTrue, [], [ClangOption, CLOption, CC1Option],

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4543,11 +4543,15 @@ Value *ScalarExprEmitter::EmitFixedPointBinOp(const BinOpInfo &op) {
45434543
break;
45444544
case BO_MulAssign:
45454545
case BO_Mul:
4546-
Result = FPBuilder.CreateMul(LHS, LHSFixedSema, RHS, RHSFixedSema);
4546+
Result =
4547+
FPBuilder.CreateMul(LHS, LHSFixedSema, RHS, RHSFixedSema,
4548+
CGF.CGM.getCodeGenOpts().OutlineFixedPointMulDiv);
45474549
break;
45484550
case BO_DivAssign:
45494551
case BO_Div:
4550-
Result = FPBuilder.CreateDiv(LHS, LHSFixedSema, RHS, RHSFixedSema);
4552+
Result =
4553+
FPBuilder.CreateDiv(LHS, LHSFixedSema, RHS, RHSFixedSema,
4554+
CGF.CGM.getCodeGenOpts().OutlineFixedPointMulDiv);
45514555
break;
45524556
case BO_ShlAssign:
45534557
case BO_Shl:

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6369,6 +6369,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
63696369
Args.AddLastArg(CmdArgs, options::OPT_fexperimental_omit_vtable_rtti,
63706370
options::OPT_fno_experimental_omit_vtable_rtti);
63716371

6372+
Args.AddLastArg(CmdArgs, options::OPT_foutline_fixed_point_mul_div_intrinsics,
6373+
options::OPT_fno_outline_fixed_point_mul_div_intrinsics);
6374+
63726375
if (Arg *A = Args.getLastArg(options::OPT_ffuchsia_api_level_EQ))
63736376
A->render(Args, CmdArgs);
63746377

llvm/include/llvm/IR/FixedPointBuilder.h

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,44 @@ template <class IRBuilderTy> class FixedPointBuilder {
132132
return Type::getFloatingPointTy(Ty->getContext(), *FloatSema);
133133
}
134134

135+
static SmallString<16> GetOutlinedFuncName(StringRef OpName, bool Saturated,
136+
unsigned Scale) {
137+
SmallString<16> OutlinedFuncName("__outlined_");
138+
OutlinedFuncName += OpName;
139+
OutlinedFuncName += "_fix";
140+
if (Saturated)
141+
OutlinedFuncName += "_sat";
142+
OutlinedFuncName += "_";
143+
OutlinedFuncName += std::to_string(Scale);
144+
return OutlinedFuncName;
145+
}
146+
147+
Value *CallFixedPointIntrinsicWrapper(Intrinsic::ID IID,
148+
StringRef OutlinedFuncName,
149+
Value *WideLHS, Value *WideRHS,
150+
unsigned Scale) {
151+
Module *M = B.GetInsertBlock()->getParent()->getParent();
152+
FunctionCallee Callee =
153+
M->getOrInsertFunction(OutlinedFuncName, WideLHS->getType(),
154+
WideLHS->getType(), WideRHS->getType());
155+
Function *OutlinedFunc = cast<Function>(Callee.getCallee());
156+
if (OutlinedFunc->empty()) {
157+
BasicBlock *BB =
158+
BasicBlock::Create(M->getContext(), "entry", OutlinedFunc);
159+
IRBuilder<> Builder(BB);
160+
Value *V = Builder.CreateIntrinsic(IID, {WideLHS->getType()},
161+
{OutlinedFunc->getArg(0),
162+
OutlinedFunc->getArg(1),
163+
Builder.getInt32(Scale)});
164+
Builder.CreateRet(V);
165+
166+
Comdat *C = M->getOrInsertComdat(OutlinedFuncName);
167+
OutlinedFunc->setComdat(C);
168+
OutlinedFunc->addFnAttr(Attribute::NoInline);
169+
}
170+
return B.CreateCall(Callee, {WideLHS, WideRHS});
171+
}
172+
135173
public:
136174
FixedPointBuilder(IRBuilderTy &Builder) : B(Builder) {}
137175

@@ -285,8 +323,8 @@ template <class IRBuilderTy> class FixedPointBuilder {
285323
/// \p LHSSema - The semantic of the left hand side
286324
/// \p RHS - The right hand side
287325
/// \p RHSSema - The semantic of the right hand side
288-
Value *CreateMul(Value *LHS, const FixedPointSemantics &LHSSema,
289-
Value *RHS, const FixedPointSemantics &RHSSema) {
326+
Value *CreateMul(Value *LHS, const FixedPointSemantics &LHSSema, Value *RHS,
327+
const FixedPointSemantics &RHSSema, bool Outlined = false) {
290328
auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema);
291329
bool UseSigned = CommonSema.isSigned() || CommonSema.hasUnsignedPadding();
292330

@@ -299,9 +337,19 @@ template <class IRBuilderTy> class FixedPointBuilder {
299337
} else {
300338
IID = UseSigned ? Intrinsic::smul_fix : Intrinsic::umul_fix;
301339
}
302-
Value *Result = B.CreateIntrinsic(
303-
IID, {WideLHS->getType()},
304-
{WideLHS, WideRHS, B.getInt32(CommonSema.getScale())});
340+
341+
Value *Result;
342+
if (!Outlined) {
343+
Result = B.CreateIntrinsic(
344+
IID, {WideLHS->getType()},
345+
{WideLHS, WideRHS, B.getInt32(CommonSema.getScale())});
346+
} else {
347+
auto OutlinedFuncName =
348+
GetOutlinedFuncName(UseSigned ? "smul" : "umul",
349+
CommonSema.isSaturated(), CommonSema.getScale());
350+
Result = CallFixedPointIntrinsicWrapper(IID, OutlinedFuncName, WideLHS,
351+
WideRHS, CommonSema.getScale());
352+
}
305353

306354
return CreateFixedToFixed(Result, CommonSema,
307355
LHSSema.getCommonSemantics(RHSSema));
@@ -313,8 +361,8 @@ template <class IRBuilderTy> class FixedPointBuilder {
313361
/// \p LHSSema - The semantic of the left hand side
314362
/// \p RHS - The right hand side
315363
/// \p RHSSema - The semantic of the right hand side
316-
Value *CreateDiv(Value *LHS, const FixedPointSemantics &LHSSema,
317-
Value *RHS, const FixedPointSemantics &RHSSema) {
364+
Value *CreateDiv(Value *LHS, const FixedPointSemantics &LHSSema, Value *RHS,
365+
const FixedPointSemantics &RHSSema, bool Outlined = false) {
318366
auto CommonSema = getCommonBinopSemantic(LHSSema, RHSSema);
319367
bool UseSigned = CommonSema.isSigned() || CommonSema.hasUnsignedPadding();
320368

@@ -327,9 +375,19 @@ template <class IRBuilderTy> class FixedPointBuilder {
327375
} else {
328376
IID = UseSigned ? Intrinsic::sdiv_fix : Intrinsic::udiv_fix;
329377
}
330-
Value *Result = B.CreateIntrinsic(
331-
IID, {WideLHS->getType()},
332-
{WideLHS, WideRHS, B.getInt32(CommonSema.getScale())});
378+
379+
Value *Result;
380+
if (!Outlined) {
381+
Result = B.CreateIntrinsic(
382+
IID, {WideLHS->getType()},
383+
{WideLHS, WideRHS, B.getInt32(CommonSema.getScale())});
384+
} else {
385+
auto OutlinedFuncName =
386+
GetOutlinedFuncName(UseSigned ? "sdiv" : "udiv",
387+
CommonSema.isSaturated(), CommonSema.getScale());
388+
Result = CallFixedPointIntrinsicWrapper(IID, OutlinedFuncName, WideLHS,
389+
WideRHS, CommonSema.getScale());
390+
}
333391

334392
return CreateFixedToFixed(Result, CommonSema,
335393
LHSSema.getCommonSemantics(RHSSema));

0 commit comments

Comments
 (0)