1919#include " llvm/ADT/SmallBitVector.h"
2020#include " llvm/ADT/SmallVector.h"
2121#include " llvm/ADT/Statistic.h"
22+ #include " llvm/ADT/StringExtras.h"
2223#include " llvm/Analysis/AliasAnalysis.h"
2324#include " llvm/Analysis/AssumeBundleQueries.h"
2425#include " llvm/Analysis/AssumptionCache.h"
@@ -4001,6 +4002,63 @@ Instruction *InstCombinerImpl::visitCallBrInst(CallBrInst &CBI) {
40014002 return visitCallBase (CBI);
40024003}
40034004
4005+ static Value *optimizeModularFormat (CallInst *CI, IRBuilderBase &B) {
4006+ if (!CI->hasFnAttr (" modular-format" ))
4007+ return nullptr ;
4008+
4009+ SmallVector<StringRef> Args (
4010+ llvm::split (CI->getFnAttr (" modular-format" ).getValueAsString (), ' ,' ));
4011+ // TODO: Examine the format argument in Args[0].
4012+ // TODO: Error handling
4013+ unsigned FirstArgIdx;
4014+ if (!llvm::to_integer (Args[1 ], FirstArgIdx))
4015+ return nullptr ;
4016+ if (FirstArgIdx == 0 )
4017+ return nullptr ;
4018+ --FirstArgIdx;
4019+ StringRef FnName = Args[2 ];
4020+ StringRef ImplName = Args[3 ];
4021+ DenseSet<StringRef> Aspects (llvm::from_range,
4022+ ArrayRef<StringRef>(Args).drop_front (4 ));
4023+ Module *M = CI->getModule ();
4024+ Function *Callee = CI->getCalledFunction ();
4025+ FunctionCallee ModularFn =
4026+ M->getOrInsertFunction (FnName, Callee->getFunctionType (),
4027+ Callee->getAttributes ().removeFnAttribute (
4028+ M->getContext (), " modular-format" ));
4029+ CallInst *New = cast<CallInst>(CI->clone ());
4030+ New->setCalledFunction (ModularFn);
4031+ New->removeFnAttr (" modular-format" );
4032+ B.Insert (New);
4033+
4034+ const auto ReferenceAspect = [&](StringRef Aspect) {
4035+ SmallString<20 > Name = ImplName;
4036+ Name += ' _' ;
4037+ Name += Aspect;
4038+ Constant *Sym =
4039+ M->getOrInsertGlobal (Name, Type::getInt8Ty (M->getContext ()));
4040+ Function *RelocNoneFn =
4041+ Intrinsic::getOrInsertDeclaration (M, Intrinsic::reloc_none);
4042+ B.CreateCall (RelocNoneFn, {Sym});
4043+ };
4044+
4045+ if (Aspects.contains (" float" )) {
4046+ Aspects.erase (" float" );
4047+ if (llvm::any_of (
4048+ llvm::make_range (std::next (CI->arg_begin (), FirstArgIdx),
4049+ CI->arg_end ()),
4050+ [](Value *V) { return V->getType ()->isFloatingPointTy (); }))
4051+ ReferenceAspect (" float" );
4052+ }
4053+
4054+ SmallVector<StringRef> UnknownAspects (Aspects.begin (), Aspects.end ());
4055+ llvm::sort (UnknownAspects);
4056+ for (StringRef Request : UnknownAspects)
4057+ ReferenceAspect (Request);
4058+
4059+ return New;
4060+ }
4061+
40044062Instruction *InstCombinerImpl::tryOptimizeCall (CallInst *CI) {
40054063 if (!CI->getCalledFunction ()) return nullptr ;
40064064
@@ -4022,6 +4080,10 @@ Instruction *InstCombinerImpl::tryOptimizeCall(CallInst *CI) {
40224080 ++NumSimplified;
40234081 return CI->use_empty () ? CI : replaceInstUsesWith (*CI, With);
40244082 }
4083+ if (Value *With = optimizeModularFormat (CI, Builder)) {
4084+ ++NumSimplified;
4085+ return CI->use_empty () ? CI : replaceInstUsesWith (*CI, With);
4086+ }
40254087
40264088 return nullptr ;
40274089}
0 commit comments