Skip to content

Commit

Permalink
Reapply "[BuildLibCalls] Introduce getOrInsertLibFunc() for use when …
Browse files Browse the repository at this point in the history
…building

libcalls." (was 0f8c626). This reverts commit 14d9390.

The patch previously failed to recognize cases where user had defined a
function alias with an identical name as that of the library
function. Module::getFunction() would then return nullptr which is what the
sanitizer discovered.

In this updated version a new function isLibFuncEmittable() has as well been
introduced which is now used instead of TLI->has() anytime a library function
is to be emitted . It additionally also makes sure there is e.g. no function
alias with the same name in the module.

Reviewed By: Eli Friedman

Differential Revision: https://reviews.llvm.org/D123198
  • Loading branch information
JonPsson committed May 2, 2022
1 parent c685f82 commit 304378f
Show file tree
Hide file tree
Showing 14 changed files with 494 additions and 196 deletions.
7 changes: 7 additions & 0 deletions llvm/include/llvm/Analysis/TargetLibraryInfo.h
Expand Up @@ -280,6 +280,13 @@ class TargetLibraryInfo {
return B == OverrideAsUnavailable;
}

/// Return true if the function type FTy is valid for the library function
/// F, regardless of whether the function is available.
bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
const Module &M) const {
return Impl->isValidProtoForLibFunc(FTy, F, M);
}

/// Searches for a particular function name.
///
/// If it is one of the known library functions, return true and set F to the
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/Module.h
Expand Up @@ -363,6 +363,8 @@ class LLVM_EXTERNAL_VISIBILITY Module {
/// In all cases, the returned value is a FunctionCallee wrapper around the
/// 'FunctionType *T' passed in, as well as a 'Value*' either of the Function or
/// the bitcast to the function.
///
/// Note: For library calls getOrInsertLibFunc() should be used instead.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T,
AttributeList AttributeList);

Expand Down
65 changes: 54 additions & 11 deletions llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
Expand Up @@ -22,23 +22,63 @@ namespace llvm {
class IRBuilderBase;

/// Analyze the name and prototype of the given function and set any
/// applicable attributes.
/// applicable attributes. Note that this merely helps optimizations on an
/// already existing function but does not consider mandatory attributes.
///
/// If the library function is unavailable, this doesn't modify it.
///
/// Returns true if any attributes were set and false otherwise.
bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI);
bool inferLibFuncAttributes(Module *M, StringRef Name, const TargetLibraryInfo &TLI);
bool inferNonMandatoryLibFuncAttrs(Module *M, StringRef Name,
const TargetLibraryInfo &TLI);
bool inferNonMandatoryLibFuncAttrs(Function &F, const TargetLibraryInfo &TLI);

/// Calls getOrInsertFunction() and then makes sure to add mandatory
/// argument attributes.
FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
LibFunc TheLibFunc, FunctionType *T,
AttributeList AttributeList);
FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
LibFunc TheLibFunc, FunctionType *T);
template <typename... ArgsTy>
FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
LibFunc TheLibFunc, AttributeList AttributeList,
Type *RetTy, ArgsTy... Args) {
SmallVector<Type*, sizeof...(ArgsTy)> ArgTys{Args...};
return getOrInsertLibFunc(M, TLI, TheLibFunc,
FunctionType::get(RetTy, ArgTys, false),
AttributeList);
}
/// Same as above, but without the attributes.
template <typename... ArgsTy>
FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
LibFunc TheLibFunc, Type *RetTy, ArgsTy... Args) {
return getOrInsertLibFunc(M, TLI, TheLibFunc, AttributeList{}, RetTy,
Args...);
}
// Avoid an incorrect ordering that'd otherwise compile incorrectly.
template <typename... ArgsTy>
FunctionCallee
getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
LibFunc TheLibFunc, AttributeList AttributeList,
FunctionType *Invalid, ArgsTy... Args) = delete;

/// Check whether the library function is available on target and also that
/// it in the current Module is a Function with the right type.
bool isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI,
LibFunc TheLibFunc);
bool isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI,
StringRef Name);

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

/// Get the name of the overloaded floating point function
/// corresponding to \a Ty.
StringRef getFloatFnName(const TargetLibraryInfo *TLI, Type *Ty,
LibFunc DoubleFn, LibFunc FloatFn,
LibFunc LongDoubleFn);
/// corresponding to \a Ty. Return the LibFunc in \a TheLibFunc.
StringRef getFloatFn(const Module *M, const TargetLibraryInfo *TLI, Type *Ty,
LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn,
LibFunc &TheLibFunc);

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

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

/// Emit a call to the binary function DoubleFn, FloatFn or LongDoubleFn,
/// depending of the type of Op1.
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
Expand Up @@ -235,7 +235,7 @@ class LibCallSimplifier {

/// hasFloatVersion - Checks if there is a float version of the specified
/// function by checking for an existing function with name FuncName + f
bool hasFloatVersion(StringRef FuncName);
bool hasFloatVersion(const Module *M, StringRef FuncName);

/// Shared code to optimize strlen+wcslen and strnlen+wcsnlen.
Value *optimizeStringLength(CallInst *CI, IRBuilderBase &B, unsigned CharSize,
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp
Expand Up @@ -29,7 +29,7 @@ static bool inferAllPrototypeAttributes(
// explicitly visited by CGSCC passes in the new pass manager.)
if (F.isDeclaration() && !F.hasOptNone()) {
if (!F.hasFnAttribute(Attribute::NoBuiltin))
Changed |= inferLibFuncAttributes(F, GetTLI(F));
Changed |= inferNonMandatoryLibFuncAttrs(F, GetTLI(F));
Changed |= inferAttributesFromOthers(F);
}

Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
Expand Up @@ -1298,6 +1298,8 @@ static Instruction *foldFDivPowDivisor(BinaryOperator &I,
}

Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
Module *M = I.getModule();

if (Value *V = SimplifyFDivInst(I.getOperand(0), I.getOperand(1),
I.getFastMathFlags(),
SQ.getWithInstruction(&I)))
Expand Down Expand Up @@ -1363,8 +1365,8 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
!IsTan && match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));

if ((IsTan || IsCot) &&
hasFloatFn(&TLI, I.getType(), LibFunc_tan, LibFunc_tanf, LibFunc_tanl)) {
if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
LibFunc_tanf, LibFunc_tanl)) {
IRBuilder<> B(&I);
IRBuilder<>::FastMathFlagGuard FMFGuard(B);
B.setFastMathFlags(I.getFastMathFlags());
Expand Down
14 changes: 8 additions & 6 deletions llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
Expand Up @@ -1100,6 +1100,7 @@ bool LoopIdiomRecognize::processLoopStridedStore(
Value *StoredVal, Instruction *TheStore,
SmallPtrSetImpl<Instruction *> &Stores, const SCEVAddRecExpr *Ev,
const SCEV *BECount, bool IsNegStride, bool IsLoopMemset) {
Module *M = TheStore->getModule();
Value *SplatValue = isBytewiseValue(StoredVal, *DL);
Constant *PatternValue = nullptr;

Expand Down Expand Up @@ -1182,15 +1183,14 @@ bool LoopIdiomRecognize::processLoopStridedStore(
NewCall = Builder.CreateMemSet(
BasePtr, SplatValue, NumBytes, MaybeAlign(StoreAlignment),
/*isVolatile=*/false, AATags.TBAA, AATags.Scope, AATags.NoAlias);
} else {
} else if (isLibFuncEmittable(M, TLI, LibFunc_memset_pattern16)) {
// Everything is emitted in default address space
Type *Int8PtrTy = DestInt8PtrTy;

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

// Otherwise we should form a memset_pattern16. PatternValue is known to be
// an constant array of 16-bytes. Plop the value into a mergable global.
Expand All @@ -1201,7 +1201,9 @@ bool LoopIdiomRecognize::processLoopStridedStore(
GV->setAlignment(Align(16));
Value *PatternPtr = ConstantExpr::getBitCast(GV, Int8PtrTy);
NewCall = Builder.CreateCall(MSP, {BasePtr, PatternPtr, NumBytes});
}
} else
return Changed;

NewCall->setDebugLoc(TheStore->getDebugLoc());

if (MSSAU) {
Expand Down

0 comments on commit 304378f

Please sign in to comment.