@@ -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+
135173public:
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