Skip to content

Commit a7ac6ed

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. This change only adds support for the 'float' aspect, but it also builds the structure needed for others. See issue #146159
1 parent eed5988 commit a7ac6ed

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
@@ -2747,6 +2747,23 @@ For example:
27472747
all arguments are not undef and not poison. Otherwise, it is undefined
27482748
behavior.
27492749

2750+
``"modular_format"="<string_idx>,<first_idx_to_check>,<modular_impl_fn>,<impl_name>,<aspects...>"``
2751+
This attribute indicates that the implementation is modular on a particular
2752+
format string argument . When the argument for a given call is constant, the
2753+
compiler may redirect the call to a modular implementation function
2754+
instead.
2755+
2756+
The compiler also emits relocations to report various aspects of the format
2757+
string and arguments that were present. The compiler reports an aspect by
2758+
issing a relocation for the symbol `<impl_name>_<aspect>``. This arranges
2759+
for code and data needed to support the aspect of the implementation to be
2760+
brought into the link to satisfy weak references in the modular
2761+
implemenation function.
2762+
2763+
The following aspects are currently supported:
2764+
2765+
- ``float``: The call has a floating point argument
2766+
27502767
Call Site Attributes
27512768
----------------------
27522769

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"
@@ -4091,6 +4092,63 @@ Instruction *InstCombinerImpl::visitCallBrInst(CallBrInst &CBI) {
40914092
return visitCallBase(CBI);
40924093
}
40934094

4095+
static Value *optimizeModularFormat(CallInst *CI, IRBuilderBase &B) {
4096+
if (!CI->hasFnAttr("modular-format"))
4097+
return nullptr;
4098+
4099+
SmallVector<StringRef> Args(
4100+
llvm::split(CI->getFnAttr("modular-format").getValueAsString(), ','));
4101+
// TODO: Examine the format argument in Args[0].
4102+
// TODO: Error handling
4103+
unsigned FirstArgIdx;
4104+
if (!llvm::to_integer(Args[1], FirstArgIdx))
4105+
return nullptr;
4106+
if (FirstArgIdx == 0)
4107+
return nullptr;
4108+
--FirstArgIdx;
4109+
StringRef FnName = Args[2];
4110+
StringRef ImplName = Args[3];
4111+
DenseSet<StringRef> Aspects(llvm::from_range,
4112+
ArrayRef<StringRef>(Args).drop_front(4));
4113+
Module *M = CI->getModule();
4114+
Function *Callee = CI->getCalledFunction();
4115+
FunctionCallee ModularFn =
4116+
M->getOrInsertFunction(FnName, Callee->getFunctionType(),
4117+
Callee->getAttributes().removeFnAttribute(
4118+
M->getContext(), "modular-format"));
4119+
CallInst *New = cast<CallInst>(CI->clone());
4120+
New->setCalledFunction(ModularFn);
4121+
New->removeFnAttr("modular-format");
4122+
B.Insert(New);
4123+
4124+
const auto ReferenceAspect = [&](StringRef Aspect) {
4125+
SmallString<20> Name = ImplName;
4126+
Name += '_';
4127+
Name += Aspect;
4128+
Constant *Sym =
4129+
M->getOrInsertGlobal(Name, Type::getInt8Ty(M->getContext()));
4130+
Function *RelocNoneFn =
4131+
Intrinsic::getOrInsertDeclaration(M, Intrinsic::reloc_none);
4132+
B.CreateCall(RelocNoneFn, {Sym});
4133+
};
4134+
4135+
if (Aspects.contains("float")) {
4136+
Aspects.erase("float");
4137+
if (llvm::any_of(
4138+
llvm::make_range(std::next(CI->arg_begin(), FirstArgIdx),
4139+
CI->arg_end()),
4140+
[](Value *V) { return V->getType()->isFloatingPointTy(); }))
4141+
ReferenceAspect("float");
4142+
}
4143+
4144+
SmallVector<StringRef> UnknownAspects(Aspects.begin(), Aspects.end());
4145+
llvm::sort(UnknownAspects);
4146+
for (StringRef Request : UnknownAspects)
4147+
ReferenceAspect(Request);
4148+
4149+
return New;
4150+
}
4151+
40944152
Instruction *InstCombinerImpl::tryOptimizeCall(CallInst *CI) {
40954153
if (!CI->getCalledFunction()) return nullptr;
40964154

@@ -4112,6 +4170,10 @@ Instruction *InstCombinerImpl::tryOptimizeCall(CallInst *CI) {
41124170
++NumSimplified;
41134171
return CI->use_empty() ? CI : replaceInstUsesWith(*CI, With);
41144172
}
4173+
if (Value *With = optimizeModularFormat(CI, Builder)) {
4174+
++NumSimplified;
4175+
return CI->use_empty() ? CI : replaceInstUsesWith(*CI, With);
4176+
}
41154177

41164178
return nullptr;
41174179
}

0 commit comments

Comments
 (0)