Index: llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp +++ llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp @@ -703,10 +703,14 @@ } 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; Index: llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll =================================================================== --- llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll +++ llvm/trunk/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 +}