1; RUN: opt < %s -basicaa -gvn -dse -S | FileCheck %s 2target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" 3 4declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) 5 6declare void @external(i32*) 7 8define i32 @test0(i8* %P) { 9 %A = alloca i32 10 call void @external(i32* %A) 11 12 store i32 0, i32* %A 13 14 call void @llvm.memset.p0i8.i32(i8* %P, i8 0, i32 42, i1 false) 15 16 %B = load i32, i32* %A 17 ret i32 %B 18 19; CHECK-LABEL: @test0 20; CHECK: ret i32 0 21} 22 23define i8 @test1() { 24; CHECK-LABEL: @test1 25 %A = alloca i8 26 %B = alloca i8 27 28 store i8 2, i8* %B ;; Not written to by memcpy 29 30 call void @llvm.memcpy.p0i8.p0i8.i8(i8* %A, i8* %B, i8 -1, i1 false) 31 32 %C = load i8, i8* %B 33 ret i8 %C 34; CHECK: ret i8 2 35} 36 37define i8 @test2(i8* %P) { 38; CHECK-LABEL: @test2 39 %P2 = getelementptr i8, i8* %P, i32 127 40 store i8 1, i8* %P2 ;; Not dead across memset 41 call void @llvm.memset.p0i8.i8(i8* %P, i8 2, i8 127, i1 false) 42 %A = load i8, i8* %P2 43 ret i8 %A 44; CHECK: ret i8 1 45} 46 47define i8 @test2a(i8* %P) { 48; CHECK-LABEL: @test2 49 %P2 = getelementptr i8, i8* %P, i32 126 50 51 ;; FIXME: DSE isn't zapping this dead store. 52 store i8 1, i8* %P2 ;; Dead, clobbered by memset. 53 54 call void @llvm.memset.p0i8.i8(i8* %P, i8 2, i8 127, i1 false) 55 %A = load i8, i8* %P2 56 ret i8 %A 57; CHECK-NOT: load 58; CHECK: ret i8 2 59} 60 61define void @test3(i8* %P, i8 %X) { 62; CHECK-LABEL: @test3 63; CHECK-NOT: store 64; CHECK-NOT: %Y 65 %Y = add i8 %X, 1 ;; Dead, because the only use (the store) is dead. 66 67 %P2 = getelementptr i8, i8* %P, i32 2 68 store i8 %Y, i8* %P2 ;; Not read by lifetime.end, should be removed. 69; CHECK: store i8 2, i8* %P2 70 call void @llvm.lifetime.end.p0i8(i64 1, i8* %P) 71 store i8 2, i8* %P2 72; CHECK-NOT: store 73 ret void 74; CHECK: ret void 75} 76 77define void @test3a(i8* %P, i8 %X) { 78; CHECK-LABEL: @test3a 79 %Y = add i8 %X, 1 ;; Dead, because the only use (the store) is dead. 80 81 %P2 = getelementptr i8, i8* %P, i32 2 82 store i8 %Y, i8* %P2 83; CHECK-NEXT: call void @llvm.lifetime.end 84 call void @llvm.lifetime.end.p0i8(i64 10, i8* %P) 85 ret void 86; CHECK-NEXT: ret void 87} 88 89@G1 = external global i32 90@G2 = external global [4000 x i32] 91 92define i32 @test4(i8* %P) { 93 %tmp = load i32, i32* @G1 94 call void @llvm.memset.p0i8.i32(i8* bitcast ([4000 x i32]* @G2 to i8*), i8 0, i32 4000, i1 false) 95 %tmp2 = load i32, i32* @G1 96 %sub = sub i32 %tmp2, %tmp 97 ret i32 %sub 98; CHECK-LABEL: @test4 99; CHECK-NOT: load 100; CHECK: memset.p0i8.i32 101; CHECK-NOT: load 102; CHECK: ret i32 0 103} 104 105; Verify that basicaa is handling variable length memcpy, knowing it doesn't 106; write to G1. 107define i32 @test5(i8* %P, i32 %Len) { 108 %tmp = load i32, i32* @G1 109 call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast ([4000 x i32]* @G2 to i8*), i8* bitcast (i32* @G1 to i8*), i32 %Len, i1 false) 110 %tmp2 = load i32, i32* @G1 111 %sub = sub i32 %tmp2, %tmp 112 ret i32 %sub 113; CHECK: @test5 114; CHECK-NOT: load 115; CHECK: memcpy.p0i8.p0i8.i32 116; CHECK-NOT: load 117; CHECK: ret i32 0 118} 119 120define i8 @test6(i8* %p, i8* noalias %a) { 121 %x = load i8, i8* %a 122 %t = va_arg i8* %p, float 123 %y = load i8, i8* %a 124 %z = add i8 %x, %y 125 ret i8 %z 126; CHECK-LABEL: @test6 127; CHECK: load i8, i8* %a 128; CHECK-NOT: load 129; CHECK: ret 130} 131 132; PR10628 133declare void @test7decl(i32* nocapture %x) 134define i32 @test7() nounwind uwtable ssp { 135entry: 136 %x = alloca i32, align 4 137 store i32 0, i32* %x, align 4 138 %add.ptr = getelementptr inbounds i32, i32* %x, i64 1 139 call void @test7decl(i32* %add.ptr) 140 %tmp = load i32, i32* %x, align 4 141 ret i32 %tmp 142; CHECK-LABEL: @test7( 143; CHECK: store i32 0 144; CHECK: call void @test7decl 145; CHECK: load i32, i32* 146} 147 148;; Check that aa correctly handles functions marked with argmemonly 149;; attribute. 150declare i32 @func_argmemonly(i32 * %P) argmemonly 151 152;; Can not remove redundant load, function may write to it. 153; CHECK-LABEL: @test8( 154define i32 @test8(i32 *%P) { 155 %V1 = load i32, i32* %P 156 call i32 @func_argmemonly(i32* %P) 157 %V2 = load i32, i32* %P 158 %Diff = sub i32 %V1, %V2 159 ret i32 %Diff 160 ; CHECK: load 161 ; CHECK: load 162 ; CHECK: sub 163 ; CHECK: ret i32 %Diff 164} 165 166;; In this case load can be removed, function clobbers only %P2. 167; CHECK-LABEL: @test9( 168define i32 @test9(i32* %P, i32* noalias %P2) { 169 %V1 = load i32, i32* %P 170 call i32 @func_argmemonly(i32* %P2) 171 %V2 = load i32, i32* %P 172 %Diff = sub i32 %V1, %V2 173 ret i32 %Diff 174 ; CHECK-NOT: load 175 ; CHECK: ret i32 0 176} 177 178;; In this case load can *not* be removed. Function clobers only %P2 but it may 179;; alias with %P. 180; CHECK-LABEL: @test10( 181define i32 @test10(i32* %P, i32* %P2) { 182 %V1 = load i32, i32* %P 183 call i32 @func_argmemonly(i32* %P2) 184 %V2 = load i32, i32* %P 185 %Diff = sub i32 %V1, %V2 186 ret i32 %Diff 187 ; CHECK: load 188 ; CHECK: load 189 ; CHECK: sub 190 ; CHECK: ret i32 %Diff 191} 192 193; CHECK-LABEL: @test11( 194define i32 @test11(i32* %P, i32* %P2) { 195 %V1 = load i32, i32* %P 196 call i32 @func_argmemonly(i32* readonly %P2) 197 %V2 = load i32, i32* %P 198 %Diff = sub i32 %V1, %V2 199 ret i32 %Diff 200 ; CHECK-NOT: load 201 ; CHECK: ret i32 0 202} 203 204declare i32 @func_argmemonly_two_args(i32* %P, i32* %P2) argmemonly 205 206; CHECK-LABEL: @test12( 207define i32 @test12(i32* %P, i32* %P2, i32* %P3) { 208 %V1 = load i32, i32* %P 209 call i32 @func_argmemonly_two_args(i32* readonly %P2, i32* %P3) 210 %V2 = load i32, i32* %P 211 %Diff = sub i32 %V1, %V2 212 ret i32 %Diff 213 ; CHECK: load 214 ; CHECK: load 215 ; CHECK: sub 216 ; CHECK: ret i32 %Diff 217} 218 219; CHECK-LABEL: @test13( 220define i32 @test13(i32* %P, i32* %P2) { 221 %V1 = load i32, i32* %P 222 call i32 @func_argmemonly(i32* readnone %P2) 223 %V2 = load i32, i32* %P 224 %Diff = sub i32 %V1, %V2 225 ret i32 %Diff 226 ; CHECK-NOT: load 227 ; CHECK: ret i32 0 228} 229 230declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) nounwind 231declare void @llvm.memset.p0i8.i8(i8* nocapture, i8, i8, i1) nounwind 232declare void @llvm.memcpy.p0i8.p0i8.i8(i8* nocapture, i8* nocapture, i8, i1) nounwind 233declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind 234