[PATCH] D14769: [FunctionAttrs] Calls to libcalls don't cause a function to potentially recurse
Duncan Exon Smith via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 18 04:53:25 PST 2015
Calls to exit() can recurse because of atexit() handlers. The same might be true of other libcalls?
Also, other noreturn functions can recurse; it's a weird path but I don't think it's malformed:
--
void bar() noreturn;
int foo() {
static bool Return = false;
if (Return) return 5;
Return = true;
bar();
}
void bar() {
sink(foo());
exit();
}
--
> On Nov 18, 2015, at 3:51 AM, James Molloy <james.molloy at arm.com> wrote:
>
> jmolloy created this revision.
> jmolloy added reviewers: joker.eph, manmanren, dexonsmith.
> jmolloy added a subscriber: llvm-commits.
> jmolloy set the repository for this revision to rL LLVM.
>
> If a function calls a library function, that shouldn't be treated as potentially causing a cycle in the CFG. Additionally calls to noreturn functions are norecurse by definition.
>
> Repository:
> rL LLVM
>
> http://reviews.llvm.org/D14769
>
> Files:
> lib/Transforms/IPO/FunctionAttrs.cpp
> test/Transforms/FunctionAttrs/norecurse.ll
>
> Index: test/Transforms/FunctionAttrs/norecurse.ll
> ===================================================================
> --- test/Transforms/FunctionAttrs/norecurse.ll
> +++ test/Transforms/FunctionAttrs/norecurse.ll
> @@ -1,5 +1,7 @@
> ; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
>
> +target triple = "x86_64-linux-gnu"
> +
> ; CHECK: define i32 @leaf() #0
> define i32 @leaf() {
> ret i32 1
> @@ -53,5 +55,24 @@
> ret void
> }
>
> +; CHECK: define i32 @calls_exit() #2
> +define i32 @calls_exit() {
> + call void @exit(i32 2)
> + ret i32 5
> +}
> +
> +declare void @exit(i32) noreturn
> +
> +; CHECK: define i32 @calls_only_libcalls() #2
> +define i32 @calls_only_libcalls() {
> + %a = call double @sin(double 0.0)
> + call void @fclose(i8* null)
> + ret i32 2
> +}
> +
> +declare double @sin(double)
> +declare void @fclose(i8*)
> +
> ; CHECK: attributes #0 = { norecurse readnone }
> ; CHECK: attributes #1 = { readnone }
> +; CHECK: attributes #2 = { norecurse }
> \ No newline at end of file
> Index: lib/Transforms/IPO/FunctionAttrs.cpp
> ===================================================================
> --- lib/Transforms/IPO/FunctionAttrs.cpp
> +++ lib/Transforms/IPO/FunctionAttrs.cpp
> @@ -1795,6 +1795,7 @@
> }
>
> static bool addNoRecurseAttrs(const CallGraphSCC &SCC,
> + const TargetLibraryInfo &TLI,
> SmallVectorImpl<WeakVH> &Revisit) {
> // Try and identify functions that do not recurse.
>
> @@ -1804,16 +1805,29 @@
>
> const CallGraphNode *CGN = *SCC.begin();
> Function *F = CGN->getFunction();
> - if (!F || F->isDeclaration() || F->doesNotRecurse())
> + if (!F || F->doesNotRecurse())
> return false;
>
> - // If all of the calls in F are identifiable and are to norecurse functions, F
> - // is norecurse. This check also detects self-recursion as F is not currently
> - // marked norecurse, so any called from F to F will not be marked norecurse.
> + // A noreturn function by definition cannot recurse.
> + if (F->doesNotReturn())
> + return setDoesNotRecurse(*F);
> +
> + if (F->isDeclaration())
> + return false;
> +
> + auto IsLibCall = [&](Function *F) {
> + LibFunc::Func LF;
> + return TLI.getLibFunc(F->getName(), LF) && TLI.has(LF);
> + };
> +
> + // If all of the calls in F are identifiable and are to norecurse functions or
> + // are libcalls, F is norecurse. This check also detects self-recursion as F
> + // is not currently marked norecurse, so any called from F to F will not be
> + // marked norecurse.
> if (std::all_of(CGN->begin(), CGN->end(),
> - [](const CallGraphNode::CallRecord &CR) {
> + [&](const CallGraphNode::CallRecord &CR) {
> Function *F = CR.second->getFunction();
> - return F && F->doesNotRecurse();
> + return F && (F->doesNotRecurse() || IsLibCall(F));
> }))
> // Function calls a potentially recursive function.
> return setDoesNotRecurse(*F);
> @@ -1890,8 +1904,8 @@
> Changed |= addNoAliasAttrs(SCCNodes);
> Changed |= addNonNullAttrs(SCCNodes, *TLI);
> }
> -
> - Changed |= addNoRecurseAttrs(SCC, Revisit);
> +
> + Changed |= addNoRecurseAttrs(SCC, *TLI, Revisit);
> return Changed;
> }
>
>
>
> <D14769.40490.patch>
More information about the llvm-commits
mailing list