From 0cb6d37deac94934069d47c7ceaef7288088ea07 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238152 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/FunctionAttrs.cpp | 6 +++++- test/Transforms/FunctionAttrs/readnone.ll | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/Transforms/FunctionAttrs/readnone.ll diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index 0166935e722..92e384a340a 100644 --- a/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/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/test/Transforms/FunctionAttrs/readnone.ll b/test/Transforms/FunctionAttrs/readnone.ll new file mode 100644 index 00000000000..eddcdd2641d --- /dev/null +++ b/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 +}