From 813226efec4aac6b8db595a19b0ebb9f3aa67d1d Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 2 Apr 2025 16:24:57 -0700 Subject: [PATCH 1/2] [IR] "modular-format" attribute for functions using format strings A new InstCombine transform uses this attribute to rewrite calls to a modular version of the implementation along with llvm.reloc.none relocations against aspects of the implementation needed by the call. This change only adds support for the 'float' aspect, but it also builds the structure needed for others. See issue #146159 --- llvm/docs/LangRef.rst | 17 +++++ .../InstCombine/InstCombineCalls.cpp | 62 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index f3aba8755b20c..cc8c0e471a196 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2620,6 +2620,23 @@ For example: This attribute indicates that outlining passes should not modify the function. +``"modular_format"=",,,,"`` + This attribute indicates that the implementation is modular on a particular + format string argument . When the argument for a given call is constant, the + compiler may redirect the call to a modular implementation function + instead. + + The compiler also emits relocations to report various aspects of the format + string and arguments that were present. The compiler reports an aspect by + issing a relocation for the symbol `_``. This arranges + for code and data needed to support the aspect of the implementation to be + brought into the link to satisfy weak references in the modular + implemenation function. + + The following aspects are currently supported: + + - ``float``: The call has a floating point argument + Call Site Attributes ---------------------- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index b6ed1dc4331d2..579e5769796c6 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumeBundleQueries.h" #include "llvm/Analysis/AssumptionCache.h" @@ -3915,6 +3916,63 @@ Instruction *InstCombinerImpl::visitCallBrInst(CallBrInst &CBI) { return visitCallBase(CBI); } +static Value *optimizeModularFormat(CallInst *CI, IRBuilderBase &B) { + if (!CI->hasFnAttr("modular-format")) + return nullptr; + + SmallVector Args( + llvm::split(CI->getFnAttr("modular-format").getValueAsString(), ',')); + // TODO: Examine the format argument in Args[0]. + // TODO: Error handling + unsigned FirstArgIdx; + if (!llvm::to_integer(Args[1], FirstArgIdx)) + return nullptr; + if (FirstArgIdx == 0) + return nullptr; + --FirstArgIdx; + StringRef FnName = Args[2]; + StringRef ImplName = Args[3]; + DenseSet Aspects(llvm::from_range, + ArrayRef(Args).drop_front(4)); + Module *M = CI->getModule(); + Function *Callee = CI->getCalledFunction(); + FunctionCallee ModularFn = + M->getOrInsertFunction(FnName, Callee->getFunctionType(), + Callee->getAttributes().removeFnAttribute( + M->getContext(), "modular-format")); + CallInst *New = cast(CI->clone()); + New->setCalledFunction(ModularFn); + New->removeFnAttr("modular-format"); + B.Insert(New); + + const auto ReferenceAspect = [&](StringRef Aspect) { + SmallString<20> Name = ImplName; + Name += '_'; + Name += Aspect; + Constant *Sym = + M->getOrInsertGlobal(Name, Type::getInt8Ty(M->getContext())); + Function *RelocNoneFn = + Intrinsic::getOrInsertDeclaration(M, Intrinsic::reloc_none); + B.CreateCall(RelocNoneFn, {Sym}); + }; + + if (Aspects.contains("float")) { + Aspects.erase("float"); + if (llvm::any_of( + llvm::make_range(std::next(CI->arg_begin(), FirstArgIdx), + CI->arg_end()), + [](Value *V) { return V->getType()->isFloatingPointTy(); })) + ReferenceAspect("float"); + } + + SmallVector UnknownAspects(Aspects.begin(), Aspects.end()); + llvm::sort(UnknownAspects); + for (StringRef Request : UnknownAspects) + ReferenceAspect(Request); + + return New; +} + Instruction *InstCombinerImpl::tryOptimizeCall(CallInst *CI) { if (!CI->getCalledFunction()) return nullptr; @@ -3936,6 +3994,10 @@ Instruction *InstCombinerImpl::tryOptimizeCall(CallInst *CI) { ++NumSimplified; return CI->use_empty() ? CI : replaceInstUsesWith(*CI, With); } + if (Value *With = optimizeModularFormat(CI, Builder)) { + ++NumSimplified; + return CI->use_empty() ? CI : replaceInstUsesWith(*CI, With); + } return nullptr; } From 271a63fbafeb05aff985a8a793614f4e500fd5cf Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Tue, 8 Jul 2025 15:11:42 -0700 Subject: [PATCH 2/2] issing -> issuing --- llvm/docs/LangRef.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index cc8c0e471a196..5171c39fb1319 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2628,7 +2628,7 @@ For example: The compiler also emits relocations to report various aspects of the format string and arguments that were present. The compiler reports an aspect by - issing a relocation for the symbol `_``. This arranges + issuing a relocation for the symbol `_``. This arranges for code and data needed to support the aspect of the implementation to be brought into the link to satisfy weak references in the modular implemenation function.