Skip to content

Commit 5f44aba

Browse files
committed
[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. See issue #146159
1 parent 062fb65 commit 5f44aba

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

llvm/docs/LangRef.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,6 +2620,23 @@ For example:
26202620
This attribute indicates that outlining passes should not modify the
26212621
function.
26222622

2623+
``"modular_format"="<string_idx>,<first_idx_to_check>,<modular_impl_fn>,<impl_name>,<aspects...>"``
2624+
This attribute indicates that the implementation is modular on a particular
2625+
format string argument . When the argument for a given call is constant, the
2626+
compiler may redirect the call to a modular implementation function
2627+
instead.
2628+
2629+
The compiler also emits relocations to report various aspects of the format
2630+
string and arguments that were present. The compiler reports an aspect by
2631+
issing a relocation for the symbol `<impl_name>_<aspect>``. This arranges
2632+
for code and data needed to support the aspect of the implementation to be
2633+
brought into the link to satisfy weak references in the modular
2634+
implemenation function.
2635+
2636+
The following aspects are currently supported:
2637+
2638+
- ``float``: The call has a floating point argument
2639+
26232640
Call Site Attributes
26242641
----------------------
26252642

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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"
@@ -3915,6 +3916,63 @@ Instruction *InstCombinerImpl::visitCallBrInst(CallBrInst &CBI) {
39153916
return visitCallBase(CBI);
39163917
}
39173918

3919+
static Value *optimizeModularFormat(CallInst *CI, IRBuilderBase &B) {
3920+
if (!CI->hasFnAttr("modular-format"))
3921+
return nullptr;
3922+
3923+
SmallVector<StringRef> Args(
3924+
llvm::split(CI->getFnAttr("modular-format").getValueAsString(), ','));
3925+
// TODO: Examine the format argument in Args[0].
3926+
// TODO: Error handling
3927+
unsigned FirstArgIdx;
3928+
if (!llvm::to_integer(Args[1], FirstArgIdx))
3929+
return nullptr;
3930+
if (FirstArgIdx == 0)
3931+
return nullptr;
3932+
--FirstArgIdx;
3933+
StringRef FnName = Args[2];
3934+
StringRef ImplName = Args[3];
3935+
DenseSet<StringRef> Aspects(llvm::from_range,
3936+
ArrayRef<StringRef>(Args).drop_front(4));
3937+
Module *M = CI->getModule();
3938+
Function *Callee = CI->getCalledFunction();
3939+
FunctionCallee ModularFn =
3940+
M->getOrInsertFunction(FnName, Callee->getFunctionType(),
3941+
Callee->getAttributes().removeFnAttribute(
3942+
M->getContext(), "modular-format"));
3943+
CallInst *New = cast<CallInst>(CI->clone());
3944+
New->setCalledFunction(ModularFn);
3945+
New->removeFnAttr("modular-format");
3946+
B.Insert(New);
3947+
3948+
const auto ReferenceAspect = [&](StringRef Aspect) {
3949+
SmallString<20> Name = ImplName;
3950+
Name += '_';
3951+
Name += Aspect;
3952+
Constant *Sym =
3953+
M->getOrInsertGlobal(Name, Type::getInt8Ty(M->getContext()));
3954+
Function *RelocNoneFn =
3955+
Intrinsic::getOrInsertDeclaration(M, Intrinsic::reloc_none);
3956+
B.CreateCall(RelocNoneFn, {Sym});
3957+
};
3958+
3959+
if (Aspects.contains("float")) {
3960+
Aspects.erase("float");
3961+
if (llvm::any_of(
3962+
llvm::make_range(std::next(CI->arg_begin(), FirstArgIdx),
3963+
CI->arg_end()),
3964+
[](Value *V) { return V->getType()->isFloatingPointTy(); }))
3965+
ReferenceAspect("float");
3966+
}
3967+
3968+
SmallVector<StringRef> UnknownAspects(Aspects.begin(), Aspects.end());
3969+
llvm::sort(UnknownAspects);
3970+
for (StringRef Request : UnknownAspects)
3971+
ReferenceAspect(Request);
3972+
3973+
return New;
3974+
}
3975+
39183976
Instruction *InstCombinerImpl::tryOptimizeCall(CallInst *CI) {
39193977
if (!CI->getCalledFunction()) return nullptr;
39203978

@@ -3936,6 +3994,10 @@ Instruction *InstCombinerImpl::tryOptimizeCall(CallInst *CI) {
39363994
++NumSimplified;
39373995
return CI->use_empty() ? CI : replaceInstUsesWith(*CI, With);
39383996
}
3997+
if (Value *With = optimizeModularFormat(CI, Builder)) {
3998+
++NumSimplified;
3999+
return CI->use_empty() ? CI : replaceInstUsesWith(*CI, With);
4000+
}
39394001

39404002
return nullptr;
39414003
}

0 commit comments

Comments
 (0)