1; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s 2; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s 3 4; %ptr can't alias %local, so we should be able to optimize the use of %local to 5; point to the store to %local. 6; CHECK-LABEL: define void @check 7define void @check(i8* %ptr, i1 %bool) { 8entry: 9 %local = alloca i8, align 1 10; CHECK: 1 = MemoryDef(liveOnEntry) 11; CHECK-NEXT: store i8 0, i8* %local, align 1 12 store i8 0, i8* %local, align 1 13 br i1 %bool, label %if.then, label %if.end 14 15if.then: 16 %p2 = getelementptr inbounds i8, i8* %ptr, i32 1 17; CHECK: 2 = MemoryDef(1) 18; CHECK-NEXT: store i8 0, i8* %p2, align 1 19 store i8 0, i8* %p2, align 1 20 br label %if.end 21 22if.end: 23; CHECK: 3 = MemoryPhi({entry,1},{if.then,2}) 24; CHECK: MemoryUse(1) 25; CHECK-NEXT: load i8, i8* %local, align 1 26 load i8, i8* %local, align 1 27 ret void 28} 29 30; CHECK-LABEL: define void @check2 31define void @check2(i1 %val1, i1 %val2, i1 %val3) { 32entry: 33 %local = alloca i8, align 1 34 %local2 = alloca i8, align 1 35 36; CHECK: 1 = MemoryDef(liveOnEntry) 37; CHECK-NEXT: store i8 0, i8* %local 38 store i8 0, i8* %local 39 br i1 %val1, label %if.then, label %phi.3 40 41if.then: 42; CHECK: 2 = MemoryDef(1) 43; CHECK-NEXT: store i8 2, i8* %local2 44 store i8 2, i8* %local2 45 br i1 %val2, label %phi.2, label %phi.3 46 47phi.3: 48; CHECK: 6 = MemoryPhi({entry,1},{if.then,2}) 49; CHECK: 3 = MemoryDef(6) 50; CHECK-NEXT: store i8 3, i8* %local2 51 store i8 3, i8* %local2 52 br i1 %val3, label %phi.2, label %phi.1 53 54phi.2: 55; CHECK: 5 = MemoryPhi({if.then,2},{phi.3,3}) 56; CHECK: 4 = MemoryDef(5) 57; CHECK-NEXT: store i8 4, i8* %local2 58 store i8 4, i8* %local2 59 br label %phi.1 60 61phi.1: 62; Order matters here; phi.2 needs to come before phi.3, because that's the order 63; they're visited in. 64; CHECK: 7 = MemoryPhi({phi.2,4},{phi.3,3}) 65; CHECK: MemoryUse(1) 66; CHECK-NEXT: load i8, i8* %local 67 load i8, i8* %local 68 ret void 69} 70 71; CHECK-LABEL: define void @cross_phi 72define void @cross_phi(i8* noalias %p1, i8* noalias %p2) { 73; CHECK: 1 = MemoryDef(liveOnEntry) 74; CHECK-NEXT: store i8 0, i8* %p1 75 store i8 0, i8* %p1 76; CHECK: MemoryUse(1) 77; CHECK-NEXT: load i8, i8* %p1 78 load i8, i8* %p1 79 br i1 undef, label %a, label %b 80 81a: 82; CHECK: 2 = MemoryDef(1) 83; CHECK-NEXT: store i8 0, i8* %p2 84 store i8 0, i8* %p2 85 br i1 undef, label %c, label %d 86 87b: 88; CHECK: 3 = MemoryDef(1) 89; CHECK-NEXT: store i8 1, i8* %p2 90 store i8 1, i8* %p2 91 br i1 undef, label %c, label %d 92 93c: 94; CHECK: 6 = MemoryPhi({a,2},{b,3}) 95; CHECK: 4 = MemoryDef(6) 96; CHECK-NEXT: store i8 2, i8* %p2 97 store i8 2, i8* %p2 98 br label %e 99 100d: 101; CHECK: 7 = MemoryPhi({a,2},{b,3}) 102; CHECK: 5 = MemoryDef(7) 103; CHECK-NEXT: store i8 3, i8* %p2 104 store i8 3, i8* %p2 105 br label %e 106 107e: 108; 8 = MemoryPhi({c,4},{d,5}) 109; CHECK: MemoryUse(1) 110; CHECK-NEXT: load i8, i8* %p1 111 load i8, i8* %p1 112 ret void 113} 114 115; CHECK-LABEL: define void @looped 116define void @looped(i8* noalias %p1, i8* noalias %p2) { 117; CHECK: 1 = MemoryDef(liveOnEntry) 118; CHECK-NEXT: store i8 0, i8* %p1 119 store i8 0, i8* %p1 120 br label %loop.1 121 122loop.1: 123; CHECK: 7 = MemoryPhi({%0,1},{loop.3,4}) 124; CHECK: 2 = MemoryDef(7) 125; CHECK-NEXT: store i8 0, i8* %p2 126 store i8 0, i8* %p2 127 br i1 undef, label %loop.2, label %loop.3 128 129loop.2: 130; CHECK: 6 = MemoryPhi({loop.1,2},{loop.3,4}) 131; CHECK: 3 = MemoryDef(6) 132; CHECK-NEXT: store i8 1, i8* %p2 133 store i8 1, i8* %p2 134 br label %loop.3 135 136loop.3: 137; CHECK: 5 = MemoryPhi({loop.1,2},{loop.2,3}) 138; CHECK: 4 = MemoryDef(5) 139; CHECK-NEXT: store i8 2, i8* %p2 140 store i8 2, i8* %p2 141; FIXME: This should be MemoryUse(1) 142; CHECK: MemoryUse(5) 143; CHECK-NEXT: load i8, i8* %p1 144 load i8, i8* %p1 145 br i1 undef, label %loop.2, label %loop.1 146} 147 148; CHECK-LABEL: define void @looped_visitedonlyonce 149define void @looped_visitedonlyonce(i8* noalias %p1, i8* noalias %p2) { 150 br label %while.cond 151 152while.cond: 153; CHECK: 5 = MemoryPhi({%0,liveOnEntry},{if.end,3}) 154; CHECK-NEXT: br i1 undef, label %if.then, label %if.end 155 br i1 undef, label %if.then, label %if.end 156 157if.then: 158; CHECK: 1 = MemoryDef(5) 159; CHECK-NEXT: store i8 0, i8* %p1 160 store i8 0, i8* %p1 161 br i1 undef, label %if.end, label %if.then2 162 163if.then2: 164; CHECK: 2 = MemoryDef(1) 165; CHECK-NEXT: store i8 1, i8* %p2 166 store i8 1, i8* %p2 167 br label %if.end 168 169if.end: 170; CHECK: 4 = MemoryPhi({while.cond,5},{if.then,1},{if.then2,2}) 171; CHECK: MemoryUse(4) 172; CHECK-NEXT: load i8, i8* %p1 173 load i8, i8* %p1 174; CHECK: 3 = MemoryDef(4) 175; CHECK-NEXT: store i8 2, i8* %p2 176 store i8 2, i8* %p2 177; CHECK: MemoryUse(4) 178; CHECK-NEXT: load i8, i8* %p1 179 load i8, i8* %p1 180 br label %while.cond 181} 182 183