diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 11cba991a95..33c04c1d07f 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -429,13 +429,43 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS1, if (CS1B == OnlyReadsMemory && CS2B == OnlyReadsMemory) return NoModRef; + AliasAnalysis::ModRefResult Mask = ModRef; + // If CS1 only reads memory, the only dependence on CS2 can be // from CS1 reading memory written by CS2. if (CS1B == OnlyReadsMemory) - return Ref; + Mask = ModRefResult(Mask & Ref); + // If CS2 only access memory through arguments, accumulate the mod/ref + // information from CS1's references to the memory referenced by + // CS2's arguments. + if (CS2B == AccessesArguments) { + AliasAnalysis::ModRefResult R = NoModRef; + for (ImmutableCallSite::arg_iterator + I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) { + R = ModRefResult((R | getModRefInfo(CS1, *I, UnknownSize)) & Mask); + if (R == Mask) + break; + } + return R; + } + + // If CS1 only accesses memory through arguments, check if CS2 references + // any of the memory referenced by CS1's arguments. If not, return NoModRef. + if (CS1B == AccessesArguments) { + AliasAnalysis::ModRefResult R = NoModRef; + for (ImmutableCallSite::arg_iterator + I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) + if (getModRefInfo(CS2, *I, UnknownSize) != NoModRef) { + R = Mask; + break; + } + if (R == NoModRef) + return R; + } + // Otherwise, fall back to NoAA (mod+ref). - return NoAA::getModRefInfo(CS1, CS2); + return ModRefResult(NoAA::getModRefInfo(CS1, CS2) & Mask); } /// GetIndexDifference - Dest and Src are the variable indices from two diff --git a/test/Analysis/BasicAA/getmodrefinfo-cs-cs.ll b/test/Analysis/BasicAA/getmodrefinfo-cs-cs.ll index f655913f3d1..12b088b1f65 100644 --- a/test/Analysis/BasicAA/getmodrefinfo-cs-cs.ll +++ b/test/Analysis/BasicAA/getmodrefinfo-cs-cs.ll @@ -1,12 +1,26 @@ ; RUN: opt < %s -aa-eval -print-all-alias-modref-info -disable-output |& FileCheck %s + ; CHECK: Just Ref: call void @ro() <-> call void @f0() declare void @f0() declare void @ro() readonly -define void @test() { +define void @test0() { call void @f0() call void @ro() ret void } + +; CHECK: NoModRef: call void @llvm.memset.p0i8.i64(i8* @A, i8 0, i64 1, i32 1, i1 false) <-> call void @llvm.memset.p0i8.i64(i8* @B, i8 0, i64 1, i32 1, i1 false) +; CHECK: NoModRef: call void @llvm.memset.p0i8.i64(i8* @B, i8 0, i64 1, i32 1, i1 false) <-> call void @llvm.memset.p0i8.i64(i8* @A, i8 0, i64 1, i32 1, i1 false) + +declare void @llvm.memset.i64(i8*, i8, i64, i32) + +@A = external global i8 +@B = external global i8 +define void @test1() { + call void @llvm.memset.i64(i8* @A, i8 0, i64 1, i32 1) + call void @llvm.memset.i64(i8* @B, i8 0, i64 1, i32 1) + ret void +}