diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1451,6 +1451,12 @@ setAttributes(PAL); } + void removeAttributes(unsigned i, const AttrBuilder &Attrs) { + AttributeList PAL = getAttributes(); + PAL = PAL.removeAttributes(getContext(), i, Attrs); + setAttributes(PAL); + } + /// Removes the attribute from the given argument void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { assert(ArgNo < getNumArgOperands() && "Out of bounds"); diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -3584,14 +3584,15 @@ // will become a non-readonly function after it is instrumented by us. To // prevent this code from being optimized out, mark that function // non-readonly in advance. + AttrBuilder B; + B.addAttribute(Attribute::ReadOnly) + .addAttribute(Attribute::ReadNone) + .addAttribute(Attribute::WriteOnly) + .addAttribute(Attribute::ArgMemOnly) + .addAttribute(Attribute::Speculatable); + + Call->removeAttributes(AttributeList::FunctionIndex, B); if (Function *Func = Call->getCalledFunction()) { - // Clear out readonly/readnone attributes. - AttrBuilder B; - B.addAttribute(Attribute::ReadOnly) - .addAttribute(Attribute::ReadNone) - .addAttribute(Attribute::WriteOnly) - .addAttribute(Attribute::ArgMemOnly) - .addAttribute(Attribute::Speculatable); Func->removeAttributes(AttributeList::FunctionIndex, B); } diff --git a/llvm/test/Instrumentation/MemorySanitizer/attributes.ll b/llvm/test/Instrumentation/MemorySanitizer/attributes.ll --- a/llvm/test/Instrumentation/MemorySanitizer/attributes.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/attributes.ll @@ -13,24 +13,28 @@ define void @a() sanitize_memory readnone { entry: call void @a_() + call void @a_() readnone ret void } define void @b() sanitize_memory readonly { entry: call void @b_() + call void @b_() readonly ret void } define void @c() sanitize_memory writeonly { entry: call void @c_() + call void @c_() writeonly ret void } define void @d(i32* %p) sanitize_memory writeonly argmemonly { entry: call void @d_(i32* %p) + call void @d_(i32* %p) writeonly argmemonly ret void }