Skip to content

Commit 0f8c626

Browse files
committed
[BuildLibCalls] Introduce getOrInsertLibFunc() for use when building libcalls.
A new set of overloaded functions named getOrInsertLibFunc() are now supposed to be used instead of getOrInsertFunction() when building a libcall from within an LLVM optimizer(). The idea is that this new function also makes sure that any mandatory argument attributes are added to the function prototype (after calling getOrInsertFunction()). inferLibFuncAttributes() is renamed to inferNonMandatoryLibFuncAttrs() as it only adds attributes that are not necessary for correctness but merely helping with later optimizations. Generally, the front end is responsible for building a correct function prototype with the needed argument attributes. If the middle end however is the one creating the call, e.g. when replacing one libcall with another, it then must take this responsibility. This continues the work of properly handling argument extension if required by the target ABI when building a lib call. getOrInsertLibFunc() now does this for all libcalls currently built by any LLVM optimizer. It is expected that when in the future a new optimization builds a new libcall with an integer argument it is to be added to getOrInsertLibFunc() with the proper handling. Note that not all targets have it in their ABI to sign/zero extend integer arguments to the full register width, but this will be done selectively as determined by getExtAttrForI32Param(). Review: Eli Friedman, Nikita Popov, Dávid Bolvanský Differential Revision: https://reviews.llvm.org/D123198
1 parent 8a9c70f commit 0f8c626

File tree

9 files changed

+316
-102
lines changed

9 files changed

+316
-102
lines changed

llvm/include/llvm/IR/Module.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,8 @@ class LLVM_EXTERNAL_VISIBILITY Module {
363363
/// In all cases, the returned value is a FunctionCallee wrapper around the
364364
/// 'FunctionType *T' passed in, as well as a 'Value*' either of the Function or
365365
/// the bitcast to the function.
366+
///
367+
/// Note: For library calls getOrInsertLibFunc() should be used instead.
366368
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T,
367369
AttributeList AttributeList);
368370

llvm/include/llvm/Transforms/Utils/BuildLibCalls.h

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,56 @@ namespace llvm {
2222
class IRBuilderBase;
2323

2424
/// Analyze the name and prototype of the given function and set any
25-
/// applicable attributes.
25+
/// applicable attributes. Note that this merely helps optimizations on an
26+
/// already existing function but does not consider mandatory attributes.
27+
///
2628
/// If the library function is unavailable, this doesn't modify it.
2729
///
2830
/// Returns true if any attributes were set and false otherwise.
29-
bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI);
30-
bool inferLibFuncAttributes(Module *M, StringRef Name, const TargetLibraryInfo &TLI);
31+
bool inferNonMandatoryLibFuncAttrs(Module *M, StringRef Name,
32+
const TargetLibraryInfo &TLI);
33+
bool inferNonMandatoryLibFuncAttrs(Function &F, const TargetLibraryInfo &TLI);
34+
35+
/// Calls getOrInsertFunction() and then makes sure to add mandatory
36+
/// argument attributes.
37+
FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
38+
LibFunc TheLibFunc, FunctionType *T,
39+
AttributeList AttributeList);
40+
FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
41+
LibFunc TheLibFunc, FunctionType *T);
42+
template <typename... ArgsTy>
43+
FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
44+
LibFunc TheLibFunc, AttributeList AttributeList,
45+
Type *RetTy, ArgsTy... Args) {
46+
SmallVector<Type*, sizeof...(ArgsTy)> ArgTys{Args...};
47+
return getOrInsertLibFunc(M, TLI, TheLibFunc,
48+
FunctionType::get(RetTy, ArgTys, false),
49+
AttributeList);
50+
}
51+
/// Same as above, but without the attributes.
52+
template <typename... ArgsTy>
53+
FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
54+
LibFunc TheLibFunc, Type *RetTy, ArgsTy... Args) {
55+
return getOrInsertLibFunc(M, TLI, TheLibFunc, AttributeList{}, RetTy,
56+
Args...);
57+
}
58+
// Avoid an incorrect ordering that'd otherwise compile incorrectly.
59+
template <typename... ArgsTy>
60+
FunctionCallee
61+
getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
62+
LibFunc TheLibFunc, AttributeList AttributeList,
63+
FunctionType *Invalid, ArgsTy... Args) = delete;
3164

3265
/// Check whether the overloaded floating point function
3366
/// corresponding to \a Ty is available.
3467
bool hasFloatFn(const TargetLibraryInfo *TLI, Type *Ty,
3568
LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn);
3669

3770
/// Get the name of the overloaded floating point function
38-
/// corresponding to \a Ty.
39-
StringRef getFloatFnName(const TargetLibraryInfo *TLI, Type *Ty,
40-
LibFunc DoubleFn, LibFunc FloatFn,
41-
LibFunc LongDoubleFn);
71+
/// corresponding to \a Ty. Return the LibFunc in \a TheLibFunc.
72+
StringRef getFloatFn(const TargetLibraryInfo *TLI, Type *Ty,
73+
LibFunc DoubleFn, LibFunc FloatFn,
74+
LibFunc LongDoubleFn, LibFunc &TheLibFunc);
4275

4376
/// Return V if it is an i8*, otherwise cast it to i8*.
4477
Value *castToCStr(Value *V, IRBuilderBase &B);
@@ -148,7 +181,8 @@ namespace llvm {
148181
/// function is known to take a single of type matching 'Op' and returns one
149182
/// value with the same type. If 'Op' is a long double, 'l' is added as the
150183
/// suffix of name, if 'Op' is a float, we add a 'f' suffix.
151-
Value *emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilderBase &B,
184+
Value *emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI,
185+
StringRef Name, IRBuilderBase &B,
152186
const AttributeList &Attrs);
153187

154188
/// Emit a call to the unary function DoubleFn, FloatFn or LongDoubleFn,
@@ -162,8 +196,10 @@ namespace llvm {
162196
/// function is known to take type matching 'Op1' and 'Op2' and return one
163197
/// value with the same type. If 'Op1/Op2' are long double, 'l' is added as
164198
/// the suffix of name, if 'Op1/Op2' are float, we add a 'f' suffix.
165-
Value *emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
166-
IRBuilderBase &B, const AttributeList &Attrs);
199+
Value *emitBinaryFloatFnCall(Value *Op1, Value *Op2,
200+
const TargetLibraryInfo *TLI,
201+
StringRef Name, IRBuilderBase &B,
202+
const AttributeList &Attrs);
167203

168204
/// Emit a call to the binary function DoubleFn, FloatFn or LongDoubleFn,
169205
/// depending of the type of Op1.

llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static bool inferAllPrototypeAttributes(
2929
// explicitly visited by CGSCC passes in the new pass manager.)
3030
if (F.isDeclaration() && !F.hasOptNone()) {
3131
if (!F.hasFnAttribute(Attribute::NoBuiltin))
32-
Changed |= inferLibFuncAttributes(F, GetTLI(F));
32+
Changed |= inferNonMandatoryLibFuncAttrs(F, GetTLI(F));
3333
Changed |= inferAttributesFromOthers(F);
3434
}
3535

llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,9 +1188,9 @@ bool LoopIdiomRecognize::processLoopStridedStore(
11881188

11891189
Module *M = TheStore->getModule();
11901190
StringRef FuncName = "memset_pattern16";
1191-
FunctionCallee MSP = M->getOrInsertFunction(FuncName, Builder.getVoidTy(),
1192-
Int8PtrTy, Int8PtrTy, IntIdxTy);
1193-
inferLibFuncAttributes(M, FuncName, *TLI);
1191+
FunctionCallee MSP = getOrInsertLibFunc(M, *TLI, LibFunc_memset_pattern16,
1192+
Builder.getVoidTy(), Int8PtrTy, Int8PtrTy, IntIdxTy);
1193+
inferNonMandatoryLibFuncAttrs(M, FuncName, *TLI);
11941194

11951195
// Otherwise we should form a memset_pattern16. PatternValue is known to be
11961196
// an constant array of 16-bytes. Plop the value into a mergable global.

0 commit comments

Comments
 (0)