diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index 93cf0d27e9a73..0feb536620e59 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -888,13 +888,14 @@ class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject, /// other than direct calls or invokes to it, or blockaddress expressions. /// Optionally passes back an offending user for diagnostic purposes, /// ignores callback uses, assume like pointer annotation calls, references in - /// llvm.used and llvm.compiler.used variables, and operand bundle - /// "clang.arc.attachedcall". - bool hasAddressTaken(const User ** = nullptr, - bool IgnoreCallbackUses = false, + /// llvm.used and llvm.compiler.used variables, operand bundle + /// "clang.arc.attachedcall", and direct calls with a different call site + /// signature (the function is implicitly casted). + bool hasAddressTaken(const User ** = nullptr, bool IgnoreCallbackUses = false, bool IgnoreAssumeLikeCalls = true, bool IngoreLLVMUsed = false, - bool IgnoreARCAttachedCall = false) const; + bool IgnoreARCAttachedCall = false, + bool IgnoreCastedDirectCall = false) const; /// isDefTriviallyDead - Return true if it is trivially safe to remove /// this function definition from the module (because it isn't externally diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index a9beb0be3de0a..b1b8404157c3b 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1752,7 +1752,8 @@ std::optional Intrinsic::remangleIntrinsicFunction(Function *F) { bool Function::hasAddressTaken(const User **PutOffender, bool IgnoreCallbackUses, bool IgnoreAssumeLikeCalls, bool IgnoreLLVMUsed, - bool IgnoreARCAttachedCall) const { + bool IgnoreARCAttachedCall, + bool IgnoreCastedDirectCall) const { for (const Use &U : uses()) { const User *FU = U.getUser(); if (isa(FU)) @@ -1801,7 +1802,8 @@ bool Function::hasAddressTaken(const User **PutOffender, continue; } - if (!Call->isCallee(&U) || Call->getFunctionType() != getFunctionType()) { + if (!Call->isCallee(&U) || (!IgnoreCastedDirectCall && + Call->getFunctionType() != getFunctionType())) { if (IgnoreARCAttachedCall && Call->isOperandBundleOfType(LLVMContext::OB_clang_arc_attachedcall, U.getOperandNo())) diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 86a9f22ea32e2..029f314b96901 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -1072,7 +1072,9 @@ Attributor::Attributor(SetVector &Functions, if (Fn->hasAddressTaken(/*PutOffender=*/nullptr, /*IgnoreCallbackUses=*/false, /*IgnoreAssumeLikeCalls=*/true, - /*IgnoreLLVMUsed=*/true)) + /*IgnoreLLVMUsed=*/true, + /*IgnoreARCAttachedCall=*/false, + /*IgnoreCastedDirectCall=*/true)) InfoCache.IndirectlyCallableFunctions.push_back(Fn); } diff --git a/llvm/test/Transforms/Attributor/callgraph.ll b/llvm/test/Transforms/Attributor/callgraph.ll index 547137046ca93..08a294318f8bc 100644 --- a/llvm/test/Transforms/Attributor/callgraph.ll +++ b/llvm/test/Transforms/Attributor/callgraph.ll @@ -459,6 +459,19 @@ define i32 @non_matching_unknown(i1 %c, ptr %fn) { ret i32 %call } +; This function is used in a "direct" call but with a different signature. +; We check that it does not show up above in any of the if-cascades because +; the address is not actually taken. +declare void @usedOnlyInCastedDirectCall(i32) +define void @usedOnlyInCastedDirectCallCaller() { +; CHECK-LABEL: @usedOnlyInCastedDirectCallCaller( +; CHECK-NEXT: call void @usedOnlyInCastedDirectCall() +; CHECK-NEXT: ret void +; + call void @usedOnlyInCastedDirectCall() + ret void +} + define void @broker(ptr %unknown) !callback !0 { ; OWRDL-LABEL: @broker( ; OWRDL-NEXT: call void [[UNKNOWN:%.*]]()