Index: lib/Analysis/CFLAliasAnalysis.cpp =================================================================== --- lib/Analysis/CFLAliasAnalysis.cpp +++ lib/Analysis/CFLAliasAnalysis.cpp @@ -986,9 +986,17 @@ auto AttrsA = Sets.getLink(SetA.Index).Attrs; auto AttrsB = Sets.getLink(SetB.Index).Attrs; - auto CombinedAttrs = AttrsA | AttrsB; - if (CombinedAttrs.any()) - return AliasAnalysis::PartialAlias; + // Stratified set attributes are used as markets to signify whether a member + // of a StratifiedSet (or a member of a set above the current set) has + // interacted with either arguments or globals. "Interacted with" meaning + // its value may be different depending on the value of an argument or + // global. The thought behind this is that, because arguments and globals + // may alias each other, if AttrsA and AttrsB have touched args/globals, + // we must conservatively say that they alias. However, if at least one of + // the sets has no values that could legally be altered by changing the value + // of an argument or global, then we don't have to be as conservative. + if (AttrsA.any() && AttrsB.any()) + return AliasAnalysis::MayAlias; return AliasAnalysis::NoAlias; } Index: test/Analysis/CFLAliasAnalysis/arguments-globals.ll =================================================================== --- /dev/null +++ test/Analysis/CFLAliasAnalysis/arguments-globals.ll @@ -0,0 +1,20 @@ +; This testcase ensures that CFL AA gives conservative answers on variables +; that involve arguments. +; (Everything should alias everything, because args can alias globals, so the +; aliasing sets should of args+alloca+global should be combined) + +; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s + +; CHECK: Function: test + +@g = external global i32 + +define void @test(i1 %c, i32* %arg1, i32* %arg2) { + ; CHECK: 15 Total Alias Queries Performed + ; CHECK: 0 no alias responses + %A = alloca i32, align 4 + %B = select i1 %c, i32* %arg1, i32* %arg2 + %C = select i1 %c, i32* @g, i32* %A + + ret void +} Index: test/Analysis/CFLAliasAnalysis/arguments.ll =================================================================== --- /dev/null +++ test/Analysis/CFLAliasAnalysis/arguments.ll @@ -0,0 +1,15 @@ +; This testcase ensures that CFL AA gives conservative answers on variables +; that involve arguments. + +; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s + +; CHECK: Function: test + +define void @test(i1 %c, i32* %arg1, i32* %arg2) { + ; CHECK: 6 Total Alias Queries Performed + ; CHECK: 3 no alias responses + %a = alloca i32, align 4 + %b = select i1 %c, i32* %arg1, i32* %arg2 + + ret void +} Index: test/Analysis/CFLAliasAnalysis/basic-interproc-ret.ll =================================================================== --- /dev/null +++ test/Analysis/CFLAliasAnalysis/basic-interproc-ret.ll @@ -0,0 +1,26 @@ +; This testcase ensures that CFL AA gives conservative answers on variables +; that involve arguments. + +; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s + +; CHECK: Function: test +; CHECK: 4 Total Alias Queries Performed +; CHECK: 3 no alias responses +; ^ The 1 MayAlias is due to %arg1. Sadly, we don't currently have machinery +; in place to check whether %arg1 aliases %a, because BasicAA takes care of +; that for us. + +define i32* @test2(i32* %arg1) { + store i32 0, i32* %arg1 + + %a = alloca i32, align 4 + ret i32* %a +} + +define void @test() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %c = call i32* @test2(i32* %a) + + ret void +} Index: test/Analysis/CFLAliasAnalysis/basic-interproc.ll =================================================================== --- /dev/null +++ test/Analysis/CFLAliasAnalysis/basic-interproc.ll @@ -0,0 +1,24 @@ +; This testcase ensures that CFL AA gives conservative answers on variables +; that involve arguments. + +; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s + +; CHECK: Function: test +; CHECK: 2 Total Alias Queries Performed +; CHECK: 1 no alias responses +; ^^ In @test2, %arg1 and %arg2 may alias + +define void @test2(i32* %arg1, i32* %arg2) { + store i32 0, i32* %arg1 + store i32 0, i32* %arg2 + + ret void +} + +define void @test() { + %a = alloca i32, align 4 + %b = alloca i32, align 4 + call void @test2(i32* %a, i32* %b) + + ret void +} Index: test/Analysis/CFLAliasAnalysis/multilevel-combine.ll =================================================================== --- /dev/null +++ test/Analysis/CFLAliasAnalysis/multilevel-combine.ll @@ -0,0 +1,31 @@ +; This testcase ensures that CFL AA responds conservatively when we union +; groups of pointers together through ternary/conditional operations +; Derived from: +; void foo(bool c) { +; char a, b; +; char *m = c ? &a : &b; +; *m; +; } +; + +; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s + +%T = type { i32, [10 x i8] } + +; CHECK: Function: test + +define void @test(i1 %C) { +; CHECK: 10 Total Alias Queries Performed +; CHECK: 4 no alias responses + %M = alloca %T*, align 8 ; NoAlias with %A, %B, %MS, %AP + %A = alloca %T, align 8 + %B = alloca %T, align 8 + + %MS = select i1 %C, %T* %B, %T* %A + + store %T* %MS, %T** %M + + %AP = load %T** %M ; PartialAlias with %A, %B + + ret void +} Index: test/Analysis/CFLAliasAnalysis/multilevel.ll =================================================================== --- /dev/null +++ test/Analysis/CFLAliasAnalysis/multilevel.ll @@ -0,0 +1,30 @@ +; This testcase ensures that CFL AA handles trivial cases with storing +; pointers in pointers appropriately. +; Derived from: +; char a, b; +; char *m = &a, *n = &b; +; *m; +; *n; + +; RUN: opt < %s -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s + +%T = type { i32, [10 x i8] } + +; CHECK: Function: test + +define void @test() { +; CHECK: 15 Total Alias Queries Performed +; CHECK: 13 no alias responses + %M = alloca %T*, align 8 + %N = alloca %T*, align 8 + %A = alloca %T, align 8 + %B = alloca %T, align 8 + + store %T* %A, %T** %M + store %T* %B, %T** %N + + %AP = load %T** %M ; PartialAlias with %A + %BP = load %T** %N ; PartialAlias with %B + + ret void +}