From: Johannes Doerfert Date: Mon, 15 Jul 2019 17:31:26 +0000 (+0000) Subject: [FunctionAttrs] Remove readonly and writeonly assertion X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e0b4696b74ca9436e4e48c2ccfef3be91925e388;p=llvm [FunctionAttrs] Remove readonly and writeonly assertion There are scenarios where mutually recursive functions may cause the SCC to contain both read only and write only functions. This removes an assertion when adding read attributes which caused a crash with a the provided test case, and instead just doesn't add the attributes. Patch by Luke Lau Differential Revision: https://reviews.llvm.org/D60761 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366090 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index cfae267c2f6..5ccd8bc4b0f 100644 --- a/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/lib/Transforms/IPO/FunctionAttrs.cpp @@ -261,12 +261,15 @@ static bool addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter) { } } + // If the SCC contains both functions that read and functions that write, then + // we cannot add readonly attributes. + if (ReadsMemory && WritesMemory) + return false; + // Success! Functions in this SCC do not access memory, or only read memory. // Give them the appropriate attribute. bool MadeChange = false; - assert(!(ReadsMemory && WritesMemory) && - "Function marked read-only and write-only"); for (Function *F : SCCNodes) { if (F->doesNotAccessMemory()) // Already perfect! diff --git a/test/Transforms/FunctionAttrs/read-write-scc.ll b/test/Transforms/FunctionAttrs/read-write-scc.ll new file mode 100644 index 00000000000..319aaf01362 --- /dev/null +++ b/test/Transforms/FunctionAttrs/read-write-scc.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -functionattrs < %s | FileCheck %s +; RUN: opt -S -passes=function-attrs < %s | FileCheck %s + +@i = global i32 0 + +define void @foo() { +; CHECK-LABEL: define void @foo() #0 { + store i32 1, i32* @i + call void @bar() + ret void +} + +define void @bar() { +; CHECK-LABEL: define void @bar() #0 { + %i = load i32, i32* @i + call void @foo() + ret void +} + +; CHECK: attributes #0 = { nofree nounwind }