From 236446cd4c32233f42f513a552bbcc29de020ff4 Mon Sep 17 00:00:00 2001 From: Bjorn Steinbrink Date: Mon, 25 May 2015 19:46:38 +0000 Subject: [PATCH] Remove conflicting attributes before adding deduced readonly/readnone Summary: In case of functions that have a pointer argument and only pass it to each other, the function attributes pass deduces that the pointer should get the readnone attribute, but fails to remove a readonly attribute that may already have been present. Reviewers: nlewycky Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D9995 llvm-svn: 238152 --- llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 6 +++++- llvm/test/Transforms/FunctionAttrs/readnone.ll | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/FunctionAttrs/readnone.ll diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 0166935e7228..92e384a340a7 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -703,10 +703,14 @@ bool FunctionAttrs::AddArgumentAttrs(const CallGraphSCC &SCC) { } if (ReadAttr != Attribute::None) { - AttrBuilder B; + AttrBuilder B, R; B.addAttribute(ReadAttr); + R.addAttribute(Attribute::ReadOnly) + .addAttribute(Attribute::ReadNone); for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) { Argument *A = ArgumentSCC[i]->Definition; + // Clear out existing readonly/readnone attributes + A->removeAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, R)); A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B)); ReadAttr == Attribute::ReadOnly ? ++NumReadOnlyArg : ++NumReadNoneArg; Changed = true; diff --git a/llvm/test/Transforms/FunctionAttrs/readnone.ll b/llvm/test/Transforms/FunctionAttrs/readnone.ll new file mode 100644 index 000000000000..eddcdd2641d5 --- /dev/null +++ b/llvm/test/Transforms/FunctionAttrs/readnone.ll @@ -0,0 +1,13 @@ +; RUN: opt < %s -functionattrs -S | FileCheck %s + +; CHECK: define void @bar(i8* nocapture readnone) +define void @bar(i8* readonly) { + call void @foo(i8* %0) + ret void +} + +; CHECK: define void @foo(i8* nocapture readnone) +define void @foo(i8* readonly) { + call void @bar(i8* %0) + ret void +}