Index: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h =================================================================== --- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h +++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h @@ -759,8 +759,12 @@ } FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) { - if (const Function *F = CS.getCalledFunction()) - return getBestAAResults().getModRefBehavior(F); + if (!CS.hasOperandBundles()) + // If CS has operand bundles then aliasing attributes from the function it + // calls do not directly apply to the CallSite. This can be made more + // precise in the future. + if (const Function *F = CS.getCalledFunction()) + return getBestAAResults().getModRefBehavior(F); return FMRB_UnknownModRefBehavior; } Index: llvm/trunk/include/llvm/IR/InstrTypes.h =================================================================== --- llvm/trunk/include/llvm/IR/InstrTypes.h +++ llvm/trunk/include/llvm/IR/InstrTypes.h @@ -1255,8 +1255,8 @@ /// \brief Is the function attribute S disallowed by some operand bundle on /// this operand bundle user? bool isFnAttrDisallowedByOpBundle(StringRef S) const { - // Operand bundles only possibly disallow readnone and readonly attributes. - // All String attributes are fine. + // Operand bundles only possibly disallow readnone, readonly and argmenonly + // attributes. All String attributes are fine. return false; } @@ -1267,6 +1267,9 @@ default: return false; + case Attribute::ArgMemOnly: + return hasReadingOperandBundles(); + case Attribute::ReadNone: return hasReadingOperandBundles(); Index: llvm/trunk/test/Feature/OperandBundles/basic-aa-argmemonly.ll =================================================================== --- llvm/trunk/test/Feature/OperandBundles/basic-aa-argmemonly.ll +++ llvm/trunk/test/Feature/OperandBundles/basic-aa-argmemonly.ll @@ -0,0 +1,28 @@ +; RUN: opt -S -basicaa -gvn < %s | FileCheck %s + +declare void @argmemonly_function(i32 *) argmemonly + +define i32 @test0(i32* %P, i32* noalias %P2) { +; CHECK-LABEL: @test0( + %v1 = load i32, i32* %P +; CHECK: %v1 = load i32, i32* %P + call void @argmemonly_function(i32* %P2) [ "tag"() ] +; CHECK: call void @argmemonly_function( + %v2 = load i32, i32* %P +; CHECK: %v2 = load i32, i32* %P + %diff = sub i32 %v1, %v2 +; CHECK: %diff = sub i32 %v1, %v2 + ret i32 %diff +; CHECK: ret i32 %diff +} + +define i32 @test1(i32* %P, i32* noalias %P2) { +; CHECK-LABEL: @test1( + %v1 = load i32, i32* %P + call void @argmemonly_function(i32* %P2) argmemonly [ "tag"() ] +; CHECK: call void @argmemonly_function( + %v2 = load i32, i32* %P + %diff = sub i32 %v1, %v2 + ret i32 %diff +; CHECK: ret i32 0 +}