1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -basicaa -dse -S | FileCheck %s 3; RUN: opt < %s -aa-pipeline=basic-aa -passes=dse -S | FileCheck %s 4target 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" 5 6declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind 7declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture, i8, i64, i32) nounwind 8declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind 9declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind 10declare void @llvm.init.trampoline(i8*, i8*, i8*) 11 12define void @test1(i32* %Q, i32* %P) { 13; CHECK-LABEL: @test1( 14; CHECK-NEXT: store i32 0, i32* [[P:%.*]] 15; CHECK-NEXT: ret void 16; 17 %DEAD = load i32, i32* %Q 18 store i32 %DEAD, i32* %P 19 store i32 0, i32* %P 20 ret void 21} 22 23; PR8576 - Should delete store of 10 even though p/q are may aliases. 24define void @test2(i32 *%p, i32 *%q) { 25; CHECK-LABEL: @test2( 26; CHECK-NEXT: store i32 20, i32* [[Q:%.*]], align 4 27; CHECK-NEXT: store i32 30, i32* [[P:%.*]], align 4 28; CHECK-NEXT: ret void 29; 30 store i32 10, i32* %p, align 4 31 store i32 20, i32* %q, align 4 32 store i32 30, i32* %p, align 4 33 ret void 34} 35 36 37; PR8677 38@g = global i32 1 39 40define i32 @test3(i32* %g_addr) nounwind { 41; CHECK-LABEL: @test3( 42; CHECK-NEXT: [[G_VALUE:%.*]] = load i32, i32* [[G_ADDR:%.*]], align 4 43; CHECK-NEXT: store i32 -1, i32* @g, align 4 44; CHECK-NEXT: store i32 [[G_VALUE]], i32* [[G_ADDR]], align 4 45; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* @g, align 4 46; CHECK-NEXT: ret i32 [[TMP3]] 47; 48 %g_value = load i32, i32* %g_addr, align 4 49 store i32 -1, i32* @g, align 4 50 store i32 %g_value, i32* %g_addr, align 4 51 %tmp3 = load i32, i32* @g, align 4 52 ret i32 %tmp3 53} 54 55 56define void @test4(i32* %Q) { 57; CHECK-LABEL: @test4( 58; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[Q:%.*]] 59; CHECK-NEXT: store volatile i32 [[A]], i32* [[Q]] 60; CHECK-NEXT: ret void 61; 62 %a = load i32, i32* %Q 63 store volatile i32 %a, i32* %Q 64 ret void 65} 66 67define void @test5(i32* %Q) { 68; CHECK-LABEL: @test5( 69; CHECK-NEXT: [[A:%.*]] = load volatile i32, i32* [[Q:%.*]] 70; CHECK-NEXT: ret void 71; 72 %a = load volatile i32, i32* %Q 73 store i32 %a, i32* %Q 74 ret void 75} 76 77; Should delete store of 10 even though memset is a may-store to P (P and Q may 78; alias). 79define void @test6(i32 *%p, i8 *%q) { 80; CHECK-LABEL: @test6( 81; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[Q:%.*]], i8 42, i64 900, i1 false) 82; CHECK-NEXT: store i32 30, i32* [[P:%.*]], align 4 83; CHECK-NEXT: ret void 84; 85 store i32 10, i32* %p, align 4 ;; dead. 86 call void @llvm.memset.p0i8.i64(i8* %q, i8 42, i64 900, i1 false) 87 store i32 30, i32* %p, align 4 88 ret void 89} 90 91; Should delete store of 10 even though memset is a may-store to P (P and Q may 92; alias). 93define void @test6_atomic(i32* align 4 %p, i8* align 4 %q) { 94; CHECK-LABEL: @test6_atomic( 95; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[Q:%.*]], i8 42, i64 900, i32 4) 96; CHECK-NEXT: store atomic i32 30, i32* [[P:%.*]] unordered, align 4 97; CHECK-NEXT: ret void 98; 99 store atomic i32 10, i32* %p unordered, align 4 ;; dead. 100 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %q, i8 42, i64 900, i32 4) 101 store atomic i32 30, i32* %p unordered, align 4 102 ret void 103} 104 105; Should delete store of 10 even though memcpy is a may-store to P (P and Q may 106; alias). 107define void @test7(i32 *%p, i8 *%q, i8* noalias %r) { 108; CHECK-LABEL: @test7( 109; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[Q:%.*]], i8* [[R:%.*]], i64 900, i1 false) 110; CHECK-NEXT: store i32 30, i32* [[P:%.*]], align 4 111; CHECK-NEXT: ret void 112; 113 store i32 10, i32* %p, align 4 ;; dead. 114 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %q, i8* %r, i64 900, i1 false) 115 store i32 30, i32* %p, align 4 116 ret void 117} 118 119; Should delete store of 10 even though memcpy is a may-store to P (P and Q may 120; alias). 121define void @test7_atomic(i32* align 4 %p, i8* align 4 %q, i8* noalias align 4 %r) { 122; CHECK-LABEL: @test7_atomic( 123; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 4 [[Q:%.*]], i8* align 4 [[R:%.*]], i64 900, i32 4) 124; CHECK-NEXT: store atomic i32 30, i32* [[P:%.*]] unordered, align 4 125; CHECK-NEXT: ret void 126; 127 store atomic i32 10, i32* %p unordered, align 4 ;; dead. 128 call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 4 %q, i8* align 4 %r, i64 900, i32 4) 129 store atomic i32 30, i32* %p unordered, align 4 130 ret void 131} 132 133; Do not delete stores that are only partially killed. 134define i32 @test8() { 135; CHECK-LABEL: @test8( 136; CHECK-NEXT: [[V:%.*]] = alloca i32 137; CHECK-NEXT: store i32 1234567, i32* [[V]] 138; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[V]] 139; CHECK-NEXT: ret i32 [[X]] 140; 141 %V = alloca i32 142 store i32 1234567, i32* %V 143 %V2 = bitcast i32* %V to i8* 144 store i8 0, i8* %V2 145 %X = load i32, i32* %V 146 ret i32 %X 147 148} 149 150 151; Test for byval handling. 152%struct.x = type { i32, i32, i32, i32 } 153define void @test9(%struct.x* byval %a) nounwind { 154; CHECK-LABEL: @test9( 155; CHECK-NEXT: ret void 156; 157 %tmp2 = getelementptr %struct.x, %struct.x* %a, i32 0, i32 0 158 store i32 1, i32* %tmp2, align 4 159 ret void 160} 161 162; Test for inalloca handling. 163define void @test9_2(%struct.x* inalloca %a) nounwind { 164; CHECK-LABEL: @test9_2( 165; CHECK-NEXT: ret void 166; 167 %tmp2 = getelementptr %struct.x, %struct.x* %a, i32 0, i32 0 168 store i32 1, i32* %tmp2, align 4 169 ret void 170} 171 172; va_arg has fuzzy dependence, the store shouldn't be zapped. 173define double @test10(i8* %X) { 174; CHECK-LABEL: @test10( 175; CHECK-NEXT: [[X_ADDR:%.*]] = alloca i8* 176; CHECK-NEXT: store i8* [[X:%.*]], i8** [[X_ADDR]] 177; CHECK-NEXT: [[TMP_0:%.*]] = va_arg i8** [[X_ADDR]], double 178; CHECK-NEXT: ret double [[TMP_0]] 179; 180 %X_addr = alloca i8* 181 store i8* %X, i8** %X_addr 182 %tmp.0 = va_arg i8** %X_addr, double 183 ret double %tmp.0 184} 185 186 187; DSE should delete the dead trampoline. 188declare void @test11f() 189define void @test11() { 190; CHECK-LABEL: @test11( 191; CHECK-NEXT: ret void 192; 193 %storage = alloca [10 x i8], align 16 ; <[10 x i8]*> [#uses=1] 194 %cast = getelementptr [10 x i8], [10 x i8]* %storage, i32 0, i32 0 ; <i8*> [#uses=1] 195 call void @llvm.init.trampoline( i8* %cast, i8* bitcast (void ()* @test11f to i8*), i8* null ) ; <i8*> [#uses=1] 196 ret void 197} 198 199 200; PR2599 - load -> store to same address. 201define void @test12({ i32, i32 }* %x) nounwind { 202; CHECK-LABEL: @test12( 203; CHECK-NEXT: [[TMP7:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[X:%.*]], i32 0, i32 1 204; CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP7]], align 4 205; CHECK-NEXT: [[TMP17:%.*]] = sub i32 0, [[TMP8]] 206; CHECK-NEXT: store i32 [[TMP17]], i32* [[TMP7]], align 4 207; CHECK-NEXT: ret void 208; 209 %tmp4 = getelementptr { i32, i32 }, { i32, i32 }* %x, i32 0, i32 0 210 %tmp5 = load i32, i32* %tmp4, align 4 211 %tmp7 = getelementptr { i32, i32 }, { i32, i32 }* %x, i32 0, i32 1 212 %tmp8 = load i32, i32* %tmp7, align 4 213 %tmp17 = sub i32 0, %tmp8 214 store i32 %tmp5, i32* %tmp4, align 4 215 store i32 %tmp17, i32* %tmp7, align 4 216 ret void 217} 218 219 220; %P doesn't escape, the DEAD instructions should be removed. 221declare void @test13f() 222define i32* @test13() { 223; CHECK-LABEL: @test13( 224; CHECK-NEXT: [[PTR:%.*]] = tail call i8* @malloc(i32 4) 225; CHECK-NEXT: [[P:%.*]] = bitcast i8* [[PTR]] to i32* 226; CHECK-NEXT: call void @test13f() 227; CHECK-NEXT: store i32 0, i32* [[P]] 228; CHECK-NEXT: ret i32* [[P]] 229; 230 %ptr = tail call i8* @malloc(i32 4) 231 %P = bitcast i8* %ptr to i32* 232 %DEAD = load i32, i32* %P 233 %DEAD2 = add i32 %DEAD, 1 234 store i32 %DEAD2, i32* %P 235 call void @test13f( ) 236 store i32 0, i32* %P 237 ret i32* %P 238} 239 240define i32 addrspace(1)* @test13_addrspacecast() { 241; CHECK-LABEL: @test13_addrspacecast( 242; CHECK-NEXT: [[P:%.*]] = tail call i8* @malloc(i32 4) 243; CHECK-NEXT: [[P_BC:%.*]] = bitcast i8* [[P]] to i32* 244; CHECK-NEXT: [[P:%.*]] = addrspacecast i32* [[P_BC]] to i32 addrspace(1)* 245; CHECK-NEXT: call void @test13f() 246; CHECK-NEXT: store i32 0, i32 addrspace(1)* [[P]] 247; CHECK-NEXT: ret i32 addrspace(1)* [[P]] 248; 249 %p = tail call i8* @malloc(i32 4) 250 %p.bc = bitcast i8* %p to i32* 251 %P = addrspacecast i32* %p.bc to i32 addrspace(1)* 252 %DEAD = load i32, i32 addrspace(1)* %P 253 %DEAD2 = add i32 %DEAD, 1 254 store i32 %DEAD2, i32 addrspace(1)* %P 255 call void @test13f( ) 256 store i32 0, i32 addrspace(1)* %P 257 ret i32 addrspace(1)* %P 258} 259 260declare noalias i8* @malloc(i32) 261declare noalias i8* @calloc(i32, i32) 262declare noalias i8* @aligned_alloc(i32, i32) 263declare void @free(i8*) 264 265 266define void @test14(i32* %Q) { 267; CHECK-LABEL: @test14( 268; CHECK-NEXT: ret void 269; 270 %P = alloca i32 271 %DEAD = load i32, i32* %Q 272 store i32 %DEAD, i32* %P 273 ret void 274 275} 276 277; Dead store on an aligned_alloc: should know that %M doesn't alias with %A. 278define i32 @test14a(i8* %M, i8 %value) { 279; CHECK-LABEL: @test14a( 280; CHECK-NOT: store 281; CHECK: ret i32 0 282; 283 %A = tail call i8* @aligned_alloc(i32 32, i32 1024) 284 store i8 %value, i8* %A 285 tail call void @free(i8* %A) 286 ret i32 0 287} 288 289; PR8701 290 291;; Fully dead overwrite of memcpy. 292define void @test15(i8* %P, i8* %Q) nounwind ssp { 293; CHECK-LABEL: @test15( 294; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) 295; CHECK-NEXT: ret void 296; 297 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 298 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 299 ret void 300} 301 302;; Fully dead overwrite of memcpy. 303define void @test15_atomic(i8* %P, i8* %Q) nounwind ssp { 304; CHECK-LABEL: @test15_atomic( 305; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 306; CHECK-NEXT: ret void 307; 308 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 309 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 310 ret void 311} 312 313;; Fully dead overwrite of memcpy. 314define void @test15_atomic_weaker(i8* %P, i8* %Q) nounwind ssp { 315; CHECK-LABEL: @test15_atomic_weaker( 316; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 317; CHECK-NEXT: ret void 318; 319 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i1 false) 320 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 321 ret void 322} 323 324;; Fully dead overwrite of memcpy. 325define void @test15_atomic_weaker_2(i8* %P, i8* %Q) nounwind ssp { 326; CHECK-LABEL: @test15_atomic_weaker_2( 327; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i1 false) 328; CHECK-NEXT: ret void 329; 330 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 331 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i1 false) 332 ret void 333} 334 335;; Full overwrite of smaller memcpy. 336define void @test16(i8* %P, i8* %Q) nounwind ssp { 337; CHECK-LABEL: @test16( 338; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) 339; CHECK-NEXT: ret void 340; 341 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 8, i1 false) 342 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 343 ret void 344} 345 346;; Full overwrite of smaller memcpy. 347define void @test16_atomic(i8* %P, i8* %Q) nounwind ssp { 348; CHECK-LABEL: @test16_atomic( 349; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 350; CHECK-NEXT: ret void 351; 352 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 8, i32 1) 353 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 354 ret void 355} 356 357;; Full overwrite of smaller memory where overwrite has stronger atomicity 358define void @test16_atomic_weaker(i8* %P, i8* %Q) nounwind ssp { 359; CHECK-LABEL: @test16_atomic_weaker( 360; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 361; CHECK-NEXT: ret void 362; 363 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 8, i1 false) 364 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 365 ret void 366} 367 368;; Full overwrite of smaller memory where overwrite has weaker atomicity. 369define void @test16_atomic_weaker_2(i8* %P, i8* %Q) nounwind ssp { 370; CHECK-LABEL: @test16_atomic_weaker_2( 371; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i1 false) 372; CHECK-NEXT: ret void 373; 374 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 8, i32 1) 375 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i1 false) 376 ret void 377} 378 379;; Overwrite of memset by memcpy. 380define void @test17(i8* %P, i8* noalias %Q) nounwind ssp { 381; CHECK-LABEL: @test17( 382; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) 383; CHECK-NEXT: ret void 384; 385 tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 false) 386 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 387 ret void 388} 389 390;; Overwrite of memset by memcpy. 391define void @test17_atomic(i8* %P, i8* noalias %Q) nounwind ssp { 392; CHECK-LABEL: @test17_atomic( 393; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 394; CHECK-NEXT: ret void 395; 396 tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %P, i8 42, i64 8, i32 1) 397 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 398 ret void 399} 400 401;; Overwrite of memset by memcpy. Overwrite is stronger atomicity. We can 402;; remove the memset. 403define void @test17_atomic_weaker(i8* %P, i8* noalias %Q) nounwind ssp { 404; CHECK-LABEL: @test17_atomic_weaker( 405; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 406; CHECK-NEXT: ret void 407; 408 tail call void @llvm.memset.p0i8.i64(i8* align 1 %P, i8 42, i64 8, i1 false) 409 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 410 ret void 411} 412 413;; Overwrite of memset by memcpy. Overwrite is weaker atomicity. We can remove 414;; the memset. 415define void @test17_atomic_weaker_2(i8* %P, i8* noalias %Q) nounwind ssp { 416; CHECK-LABEL: @test17_atomic_weaker_2( 417; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i1 false) 418; CHECK-NEXT: ret void 419; 420 tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %P, i8 42, i64 8, i32 1) 421 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i1 false) 422 ret void 423} 424 425; Should not delete the volatile memset. 426define void @test17v(i8* %P, i8* %Q) nounwind ssp { 427; CHECK-LABEL: @test17v( 428; CHECK-NEXT: tail call void @llvm.memset.p0i8.i64(i8* [[P:%.*]], i8 42, i64 8, i1 true) 429; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P]], i8* [[Q:%.*]], i64 12, i1 false) 430; CHECK-NEXT: ret void 431; 432 tail call void @llvm.memset.p0i8.i64(i8* %P, i8 42, i64 8, i1 true) 433 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 434 ret void 435} 436 437; PR8728 438; Do not delete instruction where possible situation is: 439; A = B 440; A = A 441; 442; NB! See PR11763 - currently LLVM allows memcpy's source and destination to be 443; equal (but not inequal and overlapping). 444define void @test18(i8* %P, i8* %Q, i8* %R) nounwind ssp { 445; CHECK-LABEL: @test18( 446; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) 447; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P]], i8* [[R:%.*]], i64 12, i1 false) 448; CHECK-NEXT: ret void 449; 450 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 451 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false) 452 ret void 453} 454 455define void @test18_atomic(i8* %P, i8* %Q, i8* %R) nounwind ssp { 456; CHECK-LABEL: @test18_atomic( 457; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 458; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[R:%.*]], i64 12, i32 1) 459; CHECK-NEXT: ret void 460; 461 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 462 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %R, i64 12, i32 1) 463 ret void 464} 465 466 467; The store here is not dead because the byval call reads it. 468declare void @test19f({i32}* byval align 4 %P) 469 470define void @test19({i32} * nocapture byval align 4 %arg5) nounwind ssp { 471; CHECK-LABEL: @test19( 472; CHECK-NEXT: bb: 473; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds { i32 }, { i32 }* [[ARG5:%.*]], i32 0, i32 0 474; CHECK-NEXT: store i32 912, i32* [[TMP7]] 475; CHECK-NEXT: call void @test19f({ i32 }* byval align 4 [[ARG5]]) 476; CHECK-NEXT: ret void 477; 478bb: 479 %tmp7 = getelementptr inbounds {i32}, {i32}* %arg5, i32 0, i32 0 480 store i32 912, i32* %tmp7 481 call void @test19f({i32}* byval align 4 %arg5) 482 ret void 483 484} 485 486define void @test20() { 487; CHECK-LABEL: @test20( 488; CHECK-NEXT: ret void 489; 490 %m = call i8* @malloc(i32 24) 491 store i8 0, i8* %m 492 ret void 493} 494 495define void @test21() { 496; CHECK-LABEL: @test21( 497; CHECK-NEXT: ret void 498; 499 %m = call i8* @calloc(i32 9, i32 7) 500 store i8 0, i8* %m 501 ret void 502} 503 504define void @test22(i1 %i, i32 %k, i32 %m) nounwind { 505; CHECK-LABEL: @test22( 506; CHECK-NEXT: ret void 507; 508 %k.addr = alloca i32 509 %m.addr = alloca i32 510 %k.addr.m.addr = select i1 %i, i32* %k.addr, i32* %m.addr 511 store i32 0, i32* %k.addr.m.addr, align 4 512 ret void 513} 514 515; PR13547 516declare noalias i8* @strdup(i8* nocapture) nounwind 517define noalias i8* @test23() nounwind uwtable ssp { 518; CHECK-LABEL: @test23( 519; CHECK-NEXT: [[X:%.*]] = alloca [2 x i8], align 1 520; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i8], [2 x i8]* [[X]], i64 0, i64 0 521; CHECK-NEXT: store i8 97, i8* [[ARRAYIDX]], align 1 522; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], [2 x i8]* [[X]], i64 0, i64 1 523; CHECK-NEXT: store i8 0, i8* [[ARRAYIDX1]], align 1 524; CHECK-NEXT: [[CALL:%.*]] = call i8* @strdup(i8* [[ARRAYIDX]]) #3 525; CHECK-NEXT: ret i8* [[CALL]] 526; 527 %x = alloca [2 x i8], align 1 528 %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %x, i64 0, i64 0 529 store i8 97, i8* %arrayidx, align 1 530 %arrayidx1 = getelementptr inbounds [2 x i8], [2 x i8]* %x, i64 0, i64 1 531 store i8 0, i8* %arrayidx1, align 1 532 %call = call i8* @strdup(i8* %arrayidx) nounwind 533 ret i8* %call 534} 535 536; Make sure same sized store to later element is deleted 537define void @test24([2 x i32]* %a, i32 %b, i32 %c) nounwind { 538; CHECK-LABEL: @test24( 539; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[A:%.*]], i64 0, i64 0 540; CHECK-NEXT: store i32 [[B:%.*]], i32* [[TMP1]], align 4 541; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[A]], i64 0, i64 1 542; CHECK-NEXT: store i32 [[C:%.*]], i32* [[TMP2]], align 4 543; CHECK-NEXT: ret void 544; 545 %1 = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 0, i64 0 546 store i32 0, i32* %1, align 4 547 %2 = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 0, i64 1 548 store i32 0, i32* %2, align 4 549 %3 = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 0, i64 0 550 store i32 %b, i32* %3, align 4 551 %4 = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 0, i64 1 552 store i32 %c, i32* %4, align 4 553 ret void 554} 555 556; Check another case like PR13547 where strdup is not like malloc. 557define i8* @test25(i8* %p) nounwind { 558; CHECK-LABEL: @test25( 559; CHECK-NEXT: [[P_4:%.*]] = getelementptr i8, i8* [[P:%.*]], i64 4 560; CHECK-NEXT: [[TMP:%.*]] = load i8, i8* [[P_4]], align 1 561; CHECK-NEXT: store i8 0, i8* [[P_4]], align 1 562; CHECK-NEXT: [[Q:%.*]] = call i8* @strdup(i8* [[P]]) #6 563; CHECK-NEXT: store i8 [[TMP]], i8* [[P_4]], align 1 564; CHECK-NEXT: ret i8* [[Q]] 565; 566 %p.4 = getelementptr i8, i8* %p, i64 4 567 %tmp = load i8, i8* %p.4, align 1 568 store i8 0, i8* %p.4, align 1 569 %q = call i8* @strdup(i8* %p) nounwind optsize 570 store i8 %tmp, i8* %p.4, align 1 571 ret i8* %q 572} 573 574; Remove redundant store if loaded value is in another block. 575define i32 @test26(i1 %c, i32* %p) { 576; CHECK-LABEL: @test26( 577; CHECK-NEXT: entry: 578; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 579; CHECK: bb1: 580; CHECK-NEXT: br label [[BB3:%.*]] 581; CHECK: bb2: 582; CHECK-NEXT: br label [[BB3]] 583; CHECK: bb3: 584; CHECK-NEXT: ret i32 0 585; 586entry: 587 %v = load i32, i32* %p, align 4 588 br i1 %c, label %bb1, label %bb2 589bb1: 590 br label %bb3 591bb2: 592 store i32 %v, i32* %p, align 4 593 br label %bb3 594bb3: 595 ret i32 0 596} 597 598; Remove redundant store if loaded value is in another block. 599define i32 @test27(i1 %c, i32* %p) { 600; CHECK-LABEL: @test27( 601; CHECK-NEXT: entry: 602; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 603; CHECK: bb1: 604; CHECK-NEXT: br label [[BB3:%.*]] 605; CHECK: bb2: 606; CHECK-NEXT: br label [[BB3]] 607; CHECK: bb3: 608; CHECK-NEXT: ret i32 0 609; 610entry: 611 %v = load i32, i32* %p, align 4 612 br i1 %c, label %bb1, label %bb2 613bb1: 614 br label %bb3 615bb2: 616 br label %bb3 617bb3: 618 store i32 %v, i32* %p, align 4 619 ret i32 0 620} 621 622; Don't remove redundant store because of may-aliased store. 623define i32 @test28(i1 %c, i32* %p, i32* %p2, i32 %i) { 624; CHECK-LABEL: @test28( 625; CHECK-NEXT: entry: 626; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[P:%.*]], align 4 627; CHECK-NEXT: store i32 [[I:%.*]], i32* [[P2:%.*]], align 4 628; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 629; CHECK: bb1: 630; CHECK-NEXT: br label [[BB3:%.*]] 631; CHECK: bb2: 632; CHECK-NEXT: br label [[BB3]] 633; CHECK: bb3: 634; CHECK-NEXT: store i32 [[V]], i32* [[P]], align 4 635; CHECK-NEXT: ret i32 0 636; 637entry: 638 %v = load i32, i32* %p, align 4 639 640 ; Might overwrite value at %p 641 store i32 %i, i32* %p2, align 4 642 br i1 %c, label %bb1, label %bb2 643bb1: 644 br label %bb3 645bb2: 646 br label %bb3 647bb3: 648 store i32 %v, i32* %p, align 4 649 ret i32 0 650} 651 652; Don't remove redundant store because of may-aliased store. 653define i32 @test29(i1 %c, i32* %p, i32* %p2, i32 %i) { 654; CHECK-LABEL: @test29( 655; CHECK-NEXT: entry: 656; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[P:%.*]], align 4 657; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 658; CHECK: bb1: 659; CHECK-NEXT: br label [[BB3:%.*]] 660; CHECK: bb2: 661; CHECK-NEXT: store i32 [[I:%.*]], i32* [[P2:%.*]], align 4 662; CHECK-NEXT: br label [[BB3]] 663; CHECK: bb3: 664; CHECK-NEXT: store i32 [[V]], i32* [[P]], align 4 665; CHECK-NEXT: ret i32 0 666; 667entry: 668 %v = load i32, i32* %p, align 4 669 br i1 %c, label %bb1, label %bb2 670bb1: 671 br label %bb3 672bb2: 673 ; Might overwrite value at %p 674 store i32 %i, i32* %p2, align 4 675 br label %bb3 676bb3: 677 store i32 %v, i32* %p, align 4 678 ret i32 0 679} 680 681declare void @unknown_func() 682 683; Don't remove redundant store because of unknown call. 684define i32 @test30(i1 %c, i32* %p, i32 %i) { 685; CHECK-LABEL: @test30( 686; CHECK-NEXT: entry: 687; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[P:%.*]], align 4 688; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 689; CHECK: bb1: 690; CHECK-NEXT: br label [[BB3:%.*]] 691; CHECK: bb2: 692; CHECK-NEXT: call void @unknown_func() 693; CHECK-NEXT: br label [[BB3]] 694; CHECK: bb3: 695; CHECK-NEXT: store i32 [[V]], i32* [[P]], align 4 696; CHECK-NEXT: ret i32 0 697; 698entry: 699 %v = load i32, i32* %p, align 4 700 br i1 %c, label %bb1, label %bb2 701bb1: 702 br label %bb3 703bb2: 704 ; Might overwrite value at %p 705 call void @unknown_func() 706 br label %bb3 707bb3: 708 store i32 %v, i32* %p, align 4 709 ret i32 0 710} 711 712; Remove redundant store if loaded value is in another block inside a loop. 713define i32 @test31(i1 %c, i32* %p, i32 %i) { 714; CHECK-LABEL: @test31( 715; CHECK-NEXT: entry: 716; CHECK-NEXT: br label [[BB1:%.*]] 717; CHECK: bb1: 718; CHECK-NEXT: br i1 undef, label [[BB1]], label [[BB2:%.*]] 719; CHECK: bb2: 720; CHECK-NEXT: ret i32 0 721; 722entry: 723 %v = load i32, i32* %p, align 4 724 br label %bb1 725bb1: 726 store i32 %v, i32* %p, align 4 727 br i1 undef, label %bb1, label %bb2 728bb2: 729 ret i32 0 730} 731 732; Don't remove redundant store in a loop with a may-alias store. 733define i32 @test32(i1 %c, i32* %p, i32 %i) { 734; CHECK-LABEL: @test32( 735; CHECK-NEXT: entry: 736; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[P:%.*]], align 4 737; CHECK-NEXT: br label [[BB1:%.*]] 738; CHECK: bb1: 739; CHECK-NEXT: store i32 [[V]], i32* [[P]], align 4 740; CHECK-NEXT: call void @unknown_func() 741; CHECK-NEXT: br i1 undef, label [[BB1]], label [[BB2:%.*]] 742; CHECK: bb2: 743; CHECK-NEXT: ret i32 0 744; 745entry: 746 %v = load i32, i32* %p, align 4 747 br label %bb1 748bb1: 749 store i32 %v, i32* %p, align 4 750 ; Might read and overwrite value at %p 751 call void @unknown_func() 752 br i1 undef, label %bb1, label %bb2 753bb2: 754 ret i32 0 755} 756 757; Remove redundant store, which is in the lame loop as the load. 758define i32 @test33(i1 %c, i32* %p, i32 %i) { 759; CHECK-LABEL: @test33( 760; CHECK-NEXT: entry: 761; CHECK-NEXT: br label [[BB1:%.*]] 762; CHECK: bb1: 763; CHECK-NEXT: br label [[BB2:%.*]] 764; CHECK: bb2: 765; CHECK-NEXT: call void @unknown_func() 766; CHECK-NEXT: br i1 undef, label [[BB1]], label [[BB3:%.*]] 767; CHECK: bb3: 768; CHECK-NEXT: ret i32 0 769; 770entry: 771 br label %bb1 772bb1: 773 %v = load i32, i32* %p, align 4 774 br label %bb2 775bb2: 776 store i32 %v, i32* %p, align 4 777 ; Might read and overwrite value at %p, but doesn't matter. 778 call void @unknown_func() 779 br i1 undef, label %bb1, label %bb3 780bb3: 781 ret i32 0 782} 783 784; Don't remove redundant store: unknown_func could unwind 785define void @test34(i32* noalias %p) { 786; CHECK-LABEL: @test34( 787; CHECK-NEXT: store i32 1, i32* [[P:%.*]] 788; CHECK-NEXT: call void @unknown_func() 789; CHECK-NEXT: store i32 0, i32* [[P]] 790; CHECK-NEXT: ret void 791; 792 store i32 1, i32* %p 793 call void @unknown_func() 794 store i32 0, i32* %p 795 ret void 796} 797 798; Remove redundant store even with an unwinding function in the same block 799define void @test35(i32* noalias %p) { 800; CHECK-LABEL: @test35( 801; CHECK-NEXT: call void @unknown_func() 802; CHECK-NEXT: store i32 0, i32* [[P:%.*]] 803; CHECK-NEXT: ret void 804; 805 call void @unknown_func() 806 store i32 1, i32* %p 807 store i32 0, i32* %p 808 ret void 809} 810 811; We cannot optimize away the first memmove since %P could overlap with %Q. 812define void @test36(i8* %P, i8* %Q) { 813; CHECK-LABEL: @test36( 814; CHECK-NEXT: tail call void @llvm.memmove.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) 815; CHECK-NEXT: tail call void @llvm.memmove.p0i8.p0i8.i64(i8* [[P]], i8* [[Q]], i64 12, i1 false) 816; CHECK-NEXT: ret void 817; 818 819 tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 820 tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 821 ret void 822} 823 824define void @test36_atomic(i8* %P, i8* %Q) { 825; CHECK-LABEL: @test36_atomic( 826; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 827; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[Q]], i64 12, i32 1) 828; CHECK-NEXT: ret void 829; 830 831 tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 832 tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 833 ret void 834} 835 836define void @test37(i8* %P, i8* %Q, i8* %R) { 837; CHECK-LABEL: @test37( 838; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) 839; CHECK-NEXT: tail call void @llvm.memmove.p0i8.p0i8.i64(i8* [[P]], i8* [[R:%.*]], i64 12, i1 false) 840; CHECK-NEXT: ret void 841; 842 843 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 844 tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false) 845 ret void 846} 847 848define void @test37_atomic(i8* %P, i8* %Q, i8* %R) { 849; CHECK-LABEL: @test37_atomic( 850; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 851; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[R:%.*]], i64 12, i32 1) 852; CHECK-NEXT: ret void 853; 854 855 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 856 tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %R, i64 12, i32 1) 857 ret void 858} 859 860; Same caveat about memcpy as in @test18 applies here. 861define void @test38(i8* %P, i8* %Q, i8* %R) { 862; CHECK-LABEL: @test38( 863; CHECK-NEXT: tail call void @llvm.memmove.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) 864; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P]], i8* [[R:%.*]], i64 12, i1 false) 865; CHECK-NEXT: ret void 866; 867 868 tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 869 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 12, i1 false) 870 ret void 871} 872 873define void @test38_atomic(i8* %P, i8* %Q, i8* %R) { 874; CHECK-LABEL: @test38_atomic( 875; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 876; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[R:%.*]], i64 12, i32 1) 877; CHECK-NEXT: ret void 878; 879 880 tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 881 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %R, i64 12, i32 1) 882 ret void 883} 884 885define void @test39(i8* %P, i8* %Q, i8* %R) { 886; CHECK-LABEL: @test39( 887; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P:%.*]], i8* [[Q:%.*]], i64 12, i1 false) 888; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[P]], i8* [[R:%.*]], i64 8, i1 false) 889; CHECK-NEXT: ret void 890; 891 892 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) 893 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %R, i64 8, i1 false) 894 ret void 895} 896 897define void @test39_atomic(i8* %P, i8* %Q, i8* %R) { 898; CHECK-LABEL: @test39_atomic( 899; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P:%.*]], i8* align 1 [[Q:%.*]], i64 12, i32 1) 900; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 [[P]], i8* align 1 [[R:%.*]], i64 8, i32 1) 901; CHECK-NEXT: ret void 902; 903 904 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %Q, i64 12, i32 1) 905 tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %P, i8* align 1 %R, i64 8, i32 1) 906 ret void 907} 908 909define i32 @test40() { 910; CHECK-LABEL: @test40( 911; CHECK-NEXT: entry: 912; CHECK-NEXT: [[M:%.*]] = call i8* @calloc(i32 9, i32 20) 913; CHECK-NEXT: br label [[LOOP:%.*]] 914; CHECK: loop: 915; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] 916; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 917; CHECK-NEXT: [[P_NEXT:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV_NEXT]] 918; CHECK-NEXT: store i8 1, i8* [[P_NEXT]] 919; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV]] 920; CHECK-NEXT: store i8 0, i8* [[P]] 921; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i64 [[INDVARS_IV]], 15 922; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[RETURN:%.*]] 923; CHECK: return: 924; CHECK-NEXT: ret i32 0 925; 926entry: 927 %m = call i8* @calloc(i32 9, i32 20) 928 br label %loop 929loop: 930 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ] 931 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 932 %p.next = getelementptr inbounds i8, i8* %m, i64 %indvars.iv.next 933 store i8 1, i8* %p.next 934 %p = getelementptr inbounds i8, i8* %m, i64 %indvars.iv 935 store i8 0, i8* %p 936 %continue = icmp ugt i64 %indvars.iv, 15 937 br i1 %continue, label %loop, label %return 938return: 939 ret i32 0 940} 941 942define i32 @test41() { 943; CHECK-LABEL: @test41( 944; CHECK-NEXT: entry: 945; CHECK-NEXT: [[M:%.*]] = call i8* @calloc(i32 9, i32 20) 946; CHECK-NEXT: br label [[LOOP:%.*]] 947; CHECK: loop: 948; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[CONT:%.*]] ] 949; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 950; CHECK-NEXT: [[P_NEXT:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV_NEXT]] 951; CHECK-NEXT: store i8 1, i8* [[P_NEXT]] 952; CHECK-NEXT: br label [[CONT]] 953; CHECK: cont: 954; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV]] 955; CHECK-NEXT: store i8 0, i8* [[P]] 956; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i64 [[INDVARS_IV]], 15 957; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[RETURN:%.*]] 958; CHECK: return: 959; CHECK-NEXT: ret i32 0 960; 961entry: 962 %m = call i8* @calloc(i32 9, i32 20) 963 br label %loop 964loop: 965 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %cont ] 966 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 967 %p.next = getelementptr inbounds i8, i8* %m, i64 %indvars.iv.next 968 store i8 1, i8* %p.next 969 br label %cont 970 971cont: 972 %p = getelementptr inbounds i8, i8* %m, i64 %indvars.iv 973 store i8 0, i8* %p 974 %continue = icmp ugt i64 %indvars.iv, 15 975 br i1 %continue, label %loop, label %return 976 977return: 978 ret i32 0 979} 980 981; The store is redundant here, but currently we fail to eliminate it. 982; We are walking from the store up to the calloc and translate phis as 983; needed. In this case we fail to translate %p while going over the 984; backedge. Because of that we conservatively assume that zero initialized 985; memory is clobbered. 986define i32 @test42() { 987; CHECK-LABEL: @test42( 988; CHECK-NEXT: entry: 989; CHECK-NEXT: [[M:%.*]] = call i8* @calloc(i32 9, i32 20) 990; CHECK-NEXT: br label [[LOOP:%.*]] 991; CHECK: loop: 992; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[CONT:%.*]] ] 993; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 994; CHECK-NEXT: br label [[CONT]] 995; CHECK: cont: 996; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV]] 997; CHECK-NEXT: store i8 0, i8* [[P]] 998; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i64 [[INDVARS_IV]], 15 999; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[RETURN:%.*]] 1000; CHECK: return: 1001; CHECK-NEXT: ret i32 0 1002; 1003entry: 1004 %m = call i8* @calloc(i32 9, i32 20) 1005 br label %loop 1006loop: 1007 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %cont ] 1008 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 1009 br label %cont 1010 1011cont: 1012 %p = getelementptr inbounds i8, i8* %m, i64 %indvars.iv 1013 store i8 0, i8* %p 1014 %continue = icmp ugt i64 %indvars.iv, 15 1015 br i1 %continue, label %loop, label %return 1016 1017return: 1018 ret i32 0 1019} 1020 1021define i32 @test43() { 1022; CHECK-LABEL: @test43( 1023; CHECK-NEXT: entry: 1024; CHECK-NEXT: [[M:%.*]] = call i8* @calloc(i32 9, i32 20) 1025; CHECK-NEXT: br label [[LOOP:%.*]] 1026; CHECK: loop: 1027; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[CONT_2:%.*]] ] 1028; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 1029; CHECK-NEXT: [[P_NEXT:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV_NEXT]] 1030; CHECK-NEXT: store i8 1, i8* [[P_NEXT]] 1031; CHECK-NEXT: br label [[CONT:%.*]] 1032; CHECK: cont: 1033; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV]] 1034; CHECK-NEXT: store i8 0, i8* [[P]] 1035; CHECK-NEXT: br label [[CONT_2]] 1036; CHECK: cont.2: 1037; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i64 [[INDVARS_IV]], 15 1038; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[RETURN:%.*]] 1039; CHECK: return: 1040; CHECK-NEXT: ret i32 0 1041; 1042entry: 1043 %m = call i8* @calloc(i32 9, i32 20) 1044 br label %loop 1045loop: 1046 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %cont.2 ] 1047 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 1048 %p.next = getelementptr inbounds i8, i8* %m, i64 %indvars.iv.next 1049 store i8 1, i8* %p.next 1050 br label %cont 1051 1052cont: 1053 %p = getelementptr inbounds i8, i8* %m, i64 %indvars.iv 1054 store i8 0, i8* %p 1055 br label %cont.2 1056 1057cont.2: 1058 %continue = icmp ugt i64 %indvars.iv, 15 1059 br i1 %continue, label %loop, label %return 1060 1061return: 1062 ret i32 0 1063} 1064 1065define i32 @test44() { 1066; CHECK-LABEL: @test44( 1067; CHECK-NEXT: entry: 1068; CHECK-NEXT: [[M:%.*]] = call i8* @calloc(i32 9, i32 20) 1069; CHECK-NEXT: br label [[LOOP:%.*]] 1070; CHECK: loop: 1071; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[CONT_2:%.*]] ] 1072; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 1073; CHECK-NEXT: [[P_NEXT:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV_NEXT]] 1074; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[INDVARS_IV]] 1075; CHECK-NEXT: store i8 0, i8* [[P]] 1076; CHECK-NEXT: br label [[CONT:%.*]] 1077; CHECK: cont: 1078; CHECK-NEXT: store i8 1, i8* [[P_NEXT]] 1079; CHECK-NEXT: br label [[CONT_2]] 1080; CHECK: cont.2: 1081; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i64 [[INDVARS_IV]], 15 1082; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[RETURN:%.*]] 1083; CHECK: return: 1084; CHECK-NEXT: ret i32 0 1085; 1086entry: 1087 %m = call i8* @calloc(i32 9, i32 20) 1088 br label %loop 1089loop: 1090 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %cont.2 ] 1091 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 1092 %p.next = getelementptr inbounds i8, i8* %m, i64 %indvars.iv.next 1093 %p = getelementptr inbounds i8, i8* %m, i64 %indvars.iv 1094 store i8 0, i8* %p 1095 br label %cont 1096 1097cont: 1098 store i8 1, i8* %p.next 1099 br label %cont.2 1100 1101cont.2: 1102 %continue = icmp ugt i64 %indvars.iv, 15 1103 br i1 %continue, label %loop, label %return 1104 1105return: 1106 ret i32 0 1107} 1108 1109; This is an example which can potentially benefit from PHI translation. 1110; Current implementation doesn't handle this case though. This is because 1111; we don't visit the same block with different addresses while looking for 1112; clobbering instructions. 1113define i32 @test45(i1 %c) { 1114; CHECK-LABEL: @test45( 1115; CHECK-NEXT: entry: 1116; CHECK-NEXT: [[M:%.*]] = call i8* @calloc(i32 9, i32 20) 1117; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] 1118; CHECK: true: 1119; CHECK-NEXT: [[P_1:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 1 1120; CHECK-NEXT: store i8 1, i8* [[P_1]] 1121; CHECK-NEXT: br label [[CONT:%.*]] 1122; CHECK: false: 1123; CHECK-NEXT: [[P_2:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 2 1124; CHECK-NEXT: store i8 1, i8* [[P_2]] 1125; CHECK-NEXT: br label [[CONT]] 1126; CHECK: cont: 1127; CHECK-NEXT: [[OFFSET:%.*]] = phi i64 [ 2, [[TRUE]] ], [ 1, [[FALSE]] ] 1128; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 [[OFFSET]] 1129; CHECK-NEXT: store i8 0, i8* [[P]] 1130; CHECK-NEXT: br label [[RETURN:%.*]] 1131; CHECK: return: 1132; CHECK-NEXT: ret i32 0 1133; 1134entry: 1135 %m = call i8* @calloc(i32 9, i32 20) 1136 br i1 %c, label %true, label %false 1137 1138true: 1139 %p.1 = getelementptr inbounds i8, i8* %m, i64 1 1140 store i8 1, i8* %p.1 1141 br label %cont 1142 1143false: 1144 %p.2 = getelementptr inbounds i8, i8* %m, i64 2 1145 store i8 1, i8* %p.2 1146 br label %cont 1147 1148cont: 1149 %offset = phi i64 [ 2, %true ], [ 1, %false ] 1150 %p = getelementptr inbounds i8, i8* %m, i64 %offset 1151 store i8 0, i8* %p 1152 br label %return 1153 1154return: 1155 ret i32 0 1156} 1157 1158; This is test45 modified in a way to demonstrate PHI translation 1159; improving the accuracy of the analysis (on a slightly convoluted 1160; case though). 1161define i32 @test46(i1 %c) { 1162; CHECK-LABEL: @test46( 1163; CHECK-NEXT: entry: 1164; CHECK-NEXT: [[M:%.*]] = call i8* @calloc(i32 9, i32 20) 1165; CHECK-NEXT: [[P_1:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 1 1166; CHECK-NEXT: [[P_2:%.*]] = getelementptr inbounds i8, i8* [[M]], i64 2 1167; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] 1168; CHECK: true: 1169; CHECK-NEXT: store i8 1, i8* [[P_1]] 1170; CHECK-NEXT: br label [[CONT:%.*]] 1171; CHECK: false: 1172; CHECK-NEXT: store i8 1, i8* [[P_1]] 1173; CHECK-NEXT: br label [[CONT]] 1174; CHECK: cont: 1175; CHECK-NEXT: br label [[RETURN:%.*]] 1176; CHECK: return: 1177; CHECK-NEXT: ret i32 0 1178; 1179entry: 1180 %m = call i8* @calloc(i32 9, i32 20) 1181 %p.1 = getelementptr inbounds i8, i8* %m, i64 1 1182 %p.2 = getelementptr inbounds i8, i8* %m, i64 2 1183 br i1 %c, label %true, label %false 1184 1185true: 1186 store i8 1, i8* %p.1 1187 br label %cont 1188 1189false: 1190 store i8 1, i8* %p.1 1191 br label %cont 1192 1193cont: 1194 %offset = phi i64 [ 2, %true ], [ 2, %false ] 1195 %p = getelementptr inbounds i8, i8* %m, i64 %offset 1196 store i8 0, i8* %p 1197 br label %return 1198 1199return: 1200 ret i32 0 1201} 1202 1203declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) 1204declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32) 1205