[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
This commit is contained in:
parent
341dd6a3ca
commit
40bafe2ceb
@ -2635,6 +2635,23 @@ For example:
|
||||
This attribute indicates that outlining passes should not modify the
|
||||
function.
|
||||
|
||||
``"modular_format"="<string_idx>,<first_idx_to_check>,<modular_impl_fn>,<impl_name>,<aspects...>"``
|
||||
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 `<impl_name>_<aspect>``. 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
|
||||
----------------------
|
||||
|
||||
|
||||
@ -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"
|
||||
@ -4001,6 +4002,63 @@ Instruction *InstCombinerImpl::visitCallBrInst(CallBrInst &CBI) {
|
||||
return visitCallBase(CBI);
|
||||
}
|
||||
|
||||
static Value *optimizeModularFormat(CallInst *CI, IRBuilderBase &B) {
|
||||
if (!CI->hasFnAttr("modular-format"))
|
||||
return nullptr;
|
||||
|
||||
SmallVector<StringRef> 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<StringRef> Aspects(llvm::from_range,
|
||||
ArrayRef<StringRef>(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<CallInst>(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<StringRef> 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;
|
||||
|
||||
@ -4022,6 +4080,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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user