1; RUN: opt < %s -basic-aa -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 call void @llvm.lifetime.end.p0i8(i64 10, i8* %P) 84 ret void 85; CHECK-NEXT: ret void 86} 87 88@G1 = external global i32 89@G2 = external global [4000 x i32] 90 91define i32 @test4(i8* %P) { 92 %tmp = load i32, i32* @G1 93 call void @llvm.memset.p0i8.i32(i8* bitcast ([4000 x i32]* @G2 to i8*), i8 0, i32 4000, i1 false) 94 %tmp2 = load i32, i32* @G1 95 %sub = sub i32 %tmp2, %tmp 96 ret i32 %sub 97; CHECK-LABEL: @test4 98; CHECK-NOT: load 99; CHECK: memset.p0i8.i32 100; CHECK-NOT: load 101; CHECK: ret i32 0 102} 103 104; Verify that basicaa is handling variable length memcpy, knowing it doesn't 105; write to G1. 106define i32 @test5(i8* %P, i32 %Len) { 107 %tmp = load i32, i32* @G1 108 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) 109 %tmp2 = load i32, i32* @G1 110 %sub = sub i32 %tmp2, %tmp 111 ret i32 %sub 112; CHECK: @test5 113; CHECK-NOT: load 114; CHECK: memcpy.p0i8.p0i8.i32 115; CHECK-NOT: load 116; CHECK: ret i32 0 117} 118 119define i8 @test6(i8* %p, i8* noalias %a) { 120 %x = load i8, i8* %a 121 %t = va_arg i8* %p, float 122 %y = load i8, i8* %a 123 %z = add i8 %x, %y 124 ret i8 %z 125; CHECK-LABEL: @test6 126; CHECK: load i8, i8* %a 127; CHECK-NOT: load 128; CHECK: ret 129} 130 131; PR10628 132declare void @test7decl(i32* nocapture %x) 133define i32 @test7() nounwind uwtable ssp { 134entry: 135 %x = alloca i32, align 4 136 store i32 0, i32* %x, align 4 137 %add.ptr = getelementptr inbounds i32, i32* %x, i64 1 138 call void @test7decl(i32* %add.ptr) 139 %tmp = load i32, i32* %x, align 4 140 ret i32 %tmp 141; CHECK-LABEL: @test7( 142; CHECK: store i32 0 143; CHECK: call void @test7decl 144; CHECK: load i32, i32* 145} 146 147;; Check that aa correctly handles functions marked with argmemonly 148;; attribute. 149declare i32 @func_argmemonly(i32 * %P) argmemonly 150 151;; Can not remove redundant load, function may write to it. 152; CHECK-LABEL: @test8( 153define i32 @test8(i32 *%P) { 154 %V1 = load i32, i32* %P 155 call i32 @func_argmemonly(i32* %P) 156 %V2 = load i32, i32* %P 157 %Diff = sub i32 %V1, %V2 158 ret i32 %Diff 159 ; CHECK: load 160 ; CHECK: load 161 ; CHECK: sub 162 ; CHECK: ret i32 %Diff 163} 164 165;; In this case load can be removed, function clobbers only %P2. 166; CHECK-LABEL: @test9( 167define i32 @test9(i32* %P, i32* noalias %P2) { 168 %V1 = load i32, i32* %P 169 call i32 @func_argmemonly(i32* %P2) 170 %V2 = load i32, i32* %P 171 %Diff = sub i32 %V1, %V2 172 ret i32 %Diff 173 ; CHECK-NOT: load 174 ; CHECK: ret i32 0 175} 176 177;; In this case load can *not* be removed. Function clobers only %P2 but it may 178;; alias with %P. 179; CHECK-LABEL: @test10( 180define i32 @test10(i32* %P, i32* %P2) { 181 %V1 = load i32, i32* %P 182 call i32 @func_argmemonly(i32* %P2) 183 %V2 = load i32, i32* %P 184 %Diff = sub i32 %V1, %V2 185 ret i32 %Diff 186 ; CHECK: load 187 ; CHECK: load 188 ; CHECK: sub 189 ; CHECK: ret i32 %Diff 190} 191 192; CHECK-LABEL: @test11( 193define i32 @test11(i32* %P, i32* %P2) { 194 %V1 = load i32, i32* %P 195 call i32 @func_argmemonly(i32* readonly %P2) 196 %V2 = load i32, i32* %P 197 %Diff = sub i32 %V1, %V2 198 ret i32 %Diff 199 ; CHECK-NOT: load 200 ; CHECK: ret i32 0 201} 202 203declare i32 @func_argmemonly_two_args(i32* %P, i32* %P2) argmemonly 204 205; CHECK-LABEL: @test12( 206define i32 @test12(i32* %P, i32* %P2, i32* %P3) { 207 %V1 = load i32, i32* %P 208 call i32 @func_argmemonly_two_args(i32* readonly %P2, i32* %P3) 209 %V2 = load i32, i32* %P 210 %Diff = sub i32 %V1, %V2 211 ret i32 %Diff 212 ; CHECK: load 213 ; CHECK: load 214 ; CHECK: sub 215 ; CHECK: ret i32 %Diff 216} 217 218; CHECK-LABEL: @test13( 219define i32 @test13(i32* %P, i32* %P2) { 220 %V1 = load i32, i32* %P 221 call i32 @func_argmemonly(i32* readnone %P2) 222 %V2 = load i32, i32* %P 223 %Diff = sub i32 %V1, %V2 224 ret i32 %Diff 225 ; CHECK-NOT: load 226 ; CHECK: ret i32 0 227} 228 229declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) nounwind 230declare void @llvm.memset.p0i8.i8(i8* nocapture, i8, i8, i1) nounwind 231declare void @llvm.memcpy.p0i8.p0i8.i8(i8* nocapture, i8* nocapture, i8, i1) nounwind 232declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind 233