891 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=dse -S | FileCheck %s3; RUN: opt < %s -aa-pipeline=basic-aa -passes=dse -S | FileCheck %s4target 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.p0.i64(ptr nocapture, i8, i64, i1) nounwind7declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr nocapture, i8, i64, i32) nounwind8declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind9declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i32) nounwind10declare void @llvm.init.trampoline(ptr, ptr, ptr)11declare void @llvm.matrix.column.major.store(<6 x float>, ptr, i64, i1, i32, i32)12 13define void @test1(ptr %Q, ptr %P) {14; CHECK-LABEL: @test1(15; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 416; CHECK-NEXT: ret void17;18 %DEAD = load i32, ptr %Q19 store i32 %DEAD, ptr %P20 store i32 0, ptr %P21 ret void22}23 24; PR867725@g = global i32 126 27define i32 @test3(ptr %g_addr) nounwind {28; CHECK-LABEL: @test3(29; CHECK-NEXT: [[G_VALUE:%.*]] = load i32, ptr [[G_ADDR:%.*]], align 430; CHECK-NEXT: store i32 -1, ptr @g, align 431; CHECK-NEXT: store i32 [[G_VALUE]], ptr [[G_ADDR]], align 432; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr @g, align 433; CHECK-NEXT: ret i32 [[TMP3]]34;35 %g_value = load i32, ptr %g_addr, align 436 store i32 -1, ptr @g, align 437 store i32 %g_value, ptr %g_addr, align 438 %tmp3 = load i32, ptr @g, align 439 ret i32 %tmp340}41 42 43define void @test4(ptr %Q) {44; CHECK-LABEL: @test4(45; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[Q:%.*]], align 446; CHECK-NEXT: store volatile i32 [[A]], ptr [[Q]], align 447; CHECK-NEXT: ret void48;49 %a = load i32, ptr %Q50 store volatile i32 %a, ptr %Q51 ret void52}53 54; PR8576 - Should delete store of 10 even though p/q are may aliases.55define void @test2(ptr %p, ptr %q) {56; CHECK-LABEL: @test2(57; CHECK-NEXT: store i32 20, ptr [[Q:%.*]], align 458; CHECK-NEXT: store i32 30, ptr [[P:%.*]], align 459; CHECK-NEXT: ret void60;61 store i32 10, ptr %p, align 462 store i32 20, ptr %q, align 463 store i32 30, ptr %p, align 464 ret void65}66 67; Should delete store of 10 even though memset is a may-store to P (P and Q may68; alias).69define void @test6(ptr %p, ptr %q) {70; CHECK-LABEL: @test6(71; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[Q:%.*]], i8 42, i64 900, i1 false)72; CHECK-NEXT: store i32 30, ptr [[P:%.*]], align 473; CHECK-NEXT: ret void74;75 store i32 10, ptr %p, align 4 ;; dead.76 call void @llvm.memset.p0.i64(ptr %q, i8 42, i64 900, i1 false)77 store i32 30, ptr %p, align 478 ret void79}80 81; Should delete store of 10 even though memset is a may-store to P (P and Q may82; alias).83define void @test6_atomic(ptr align 4 %p, ptr align 4 %q) {84; CHECK-LABEL: @test6_atomic(85; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[Q:%.*]], i8 42, i64 900, i32 4)86; CHECK-NEXT: store atomic i32 30, ptr [[P:%.*]] unordered, align 487; CHECK-NEXT: ret void88;89 store atomic i32 10, ptr %p unordered, align 4 ;; dead.90 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %q, i8 42, i64 900, i32 4)91 store atomic i32 30, ptr %p unordered, align 492 ret void93}94 95; Should delete store of 10 even though memcpy is a may-store to P (P and Q may96; alias).97define void @test7(ptr %p, ptr %q, ptr noalias %r) {98; CHECK-LABEL: @test7(99; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[Q:%.*]], ptr [[R:%.*]], i64 900, i1 false)100; CHECK-NEXT: store i32 30, ptr [[P:%.*]], align 4101; CHECK-NEXT: ret void102;103 store i32 10, ptr %p, align 4 ;; dead.104 call void @llvm.memcpy.p0.p0.i64(ptr %q, ptr %r, i64 900, i1 false)105 store i32 30, ptr %p, align 4106 ret void107}108 109; Should delete store of 10 even though memcpy is a may-store to P (P and Q may110; alias).111define void @test7_atomic(ptr align 4 %p, ptr align 4 %q, ptr noalias align 4 %r) {112; CHECK-LABEL: @test7_atomic(113; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 4 [[Q:%.*]], ptr align 4 [[R:%.*]], i64 900, i32 4)114; CHECK-NEXT: store atomic i32 30, ptr [[P:%.*]] unordered, align 4115; CHECK-NEXT: ret void116;117 store atomic i32 10, ptr %p unordered, align 4 ;; dead.118 call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 4 %q, ptr align 4 %r, i64 900, i32 4)119 store atomic i32 30, ptr %p unordered, align 4120 ret void121}122 123; Do not delete stores that are only partially killed.124define i32 @test8() {125; CHECK-LABEL: @test8(126; CHECK-NEXT: [[V:%.*]] = alloca i32, align 4127; CHECK-NEXT: store i32 1234567, ptr [[V]], align 4128; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[V]], align 4129; CHECK-NEXT: ret i32 [[X]]130;131 %V = alloca i32132 store i32 1234567, ptr %V133 store i8 0, ptr %V134 %X = load i32, ptr %V135 ret i32 %X136 137}138 139; Test for byval handling.140%struct.x = type { i32, i32, i32, i32 }141define void @test9(ptr byval(%struct.x) %a) nounwind {142; CHECK-LABEL: @test9(143; CHECK-NEXT: ret void144;145 store i32 1, ptr %a, align 4146 ret void147}148 149; Test for inalloca handling.150define void @test9_2(ptr inalloca(%struct.x) %a) nounwind {151; CHECK-LABEL: @test9_2(152; CHECK-NEXT: ret void153;154 store i32 1, ptr %a, align 4155 ret void156}157 158; Test for preallocated handling.159define void @test9_3(ptr preallocated(%struct.x) %a) nounwind {160; CHECK-LABEL: @test9_3(161; CHECK-NEXT: ret void162;163 store i32 1, ptr %a, align 4164 ret void165}166 167; va_arg has fuzzy dependence, the store shouldn't be zapped.168define double @test10(ptr %X) {169; CHECK-LABEL: @test10(170; CHECK-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 8171; CHECK-NEXT: store ptr [[X:%.*]], ptr [[X_ADDR]], align 8172; CHECK-NEXT: [[TMP_0:%.*]] = va_arg ptr [[X_ADDR]], double173; CHECK-NEXT: ret double [[TMP_0]]174;175 %X_addr = alloca ptr176 store ptr %X, ptr %X_addr177 %tmp.0 = va_arg ptr %X_addr, double178 ret double %tmp.0179}180 181; DSE should delete the dead trampoline.182declare void @test11f()183define void @test11() {184; CHECK-LABEL: @test11(185; CHECK-NEXT: ret void186;187 %storage = alloca [10 x i8], align 16 ; <ptr> [#uses=1]188 %cast = getelementptr [10 x i8], ptr %storage, i32 0, i32 0 ; <ptr> [#uses=1]189 call void @llvm.init.trampoline( ptr %cast, ptr @test11f, ptr null ) ; <ptr> [#uses=1]190 ret void191}192 193; Specialized store intrinsics should be removed if dead.194define void @test_matrix_store(i64 %stride) {195; CHECK-LABEL: @test_matrix_store(196; CHECK-NEXT: ret void197;198 %a = alloca [6 x float]199 call void @llvm.matrix.column.major.store(<6 x float> zeroinitializer, ptr %a, i64 %stride, i1 false, i32 3, i32 2)200 ret void201}202 203; %P doesn't escape, the DEAD instructions should be removed.204declare void @may_unwind()205define ptr @test_malloc_no_escape_before_return() {206; CHECK-LABEL: @test_malloc_no_escape_before_return(207; CHECK-NEXT: [[PTR:%.*]] = tail call ptr @malloc(i64 4)208; CHECK-NEXT: call void @may_unwind()209; CHECK-NEXT: store i32 0, ptr [[PTR]], align 4210; CHECK-NEXT: ret ptr [[PTR]]211;212 %ptr = tail call ptr @malloc(i64 4)213 %DEAD = load i32, ptr %ptr214 %DEAD2 = add i32 %DEAD, 1215 store i32 %DEAD2, ptr %ptr216 call void @may_unwind()217 store i32 0, ptr %ptr218 ret ptr %ptr219}220 221define ptr @test_custom_malloc_no_escape_before_return() {222; CHECK-LABEL: @test_custom_malloc_no_escape_before_return(223; CHECK-NEXT: [[PTR:%.*]] = tail call ptr @custom_malloc(i32 4)224; CHECK-NEXT: call void @may_unwind()225; CHECK-NEXT: store i32 0, ptr [[PTR]], align 4226; CHECK-NEXT: ret ptr [[PTR]]227;228 %ptr = tail call ptr @custom_malloc(i32 4)229 %DEAD = load i32, ptr %ptr230 %DEAD2 = add i32 %DEAD, 1231 store i32 %DEAD2, ptr %ptr232 call void @may_unwind()233 store i32 0, ptr %ptr234 ret ptr %ptr235}236 237define ptr addrspace(1) @test13_addrspacecast() {238; CHECK-LABEL: @test13_addrspacecast(239; CHECK-NEXT: [[P:%.*]] = tail call ptr @malloc(i64 4)240; CHECK-NEXT: [[P_AC:%.*]] = addrspacecast ptr [[P]] to ptr addrspace(1)241; CHECK-NEXT: call void @may_unwind()242; CHECK-NEXT: store i32 0, ptr addrspace(1) [[P_AC]], align 4243; CHECK-NEXT: ret ptr addrspace(1) [[P_AC]]244;245 %p = tail call ptr @malloc(i64 4)246 %p.ac = addrspacecast ptr %p to ptr addrspace(1)247 %DEAD = load i32, ptr addrspace(1) %p.ac248 %DEAD2 = add i32 %DEAD, 1249 store i32 %DEAD2, ptr addrspace(1) %p.ac250 call void @may_unwind()251 store i32 0, ptr addrspace(1) %p.ac252 ret ptr addrspace(1) %p.ac253}254 255 256declare noalias ptr @malloc(i64) willreturn allockind("alloc,uninitialized")257declare noalias ptr @custom_malloc(i32) willreturn258declare noalias ptr @calloc(i64, i64) willreturn allockind("alloc,zeroed")259 260define void @test14(ptr %Q) {261; CHECK-LABEL: @test14(262; CHECK-NEXT: ret void263;264 %P = alloca i32265 %DEAD = load i32, ptr %Q266 store i32 %DEAD, ptr %P267 ret void268 269}270 271; The store here is not dead because the byval call reads it.272declare void @test19f(ptr byval({i32}) align 4 %P)273 274define void @test19(ptr nocapture byval({i32}) align 4 %arg5) nounwind ssp {275; CHECK-LABEL: @test19(276; CHECK-NEXT: bb:277; CHECK-NEXT: store i32 912, ptr [[ARG5:%.*]], align 4278; CHECK-NEXT: call void @test19f(ptr byval({ i32 }) align 4 [[ARG5]])279; CHECK-NEXT: ret void280;281bb:282 store i32 912, ptr %arg5283 call void @test19f(ptr byval({i32}) align 4 %arg5)284 ret void285 286}287 288define void @malloc_no_escape() {289; CHECK-LABEL: @malloc_no_escape(290; CHECK-NEXT: ret void291;292 %m = call ptr @malloc(i64 24)293 store i8 0, ptr %m294 ret void295}296 297define void @custom_malloc_no_escape() {298; CHECK-LABEL: @custom_malloc_no_escape(299; CHECK-NEXT: [[M:%.*]] = call ptr @custom_malloc(i32 24)300; CHECK-NEXT: ret void301;302 %m = call ptr @custom_malloc(i32 24)303 store i8 0, ptr %m304 ret void305}306 307declare void @use.ptr(ptr)308 309define void @malloc_no_escape_via_attr() {310; CHECK-LABEL: @malloc_no_escape_via_attr(311; CHECK-NEXT: [[M:%.*]] = call ptr @malloc(i64 24)312; CHECK-NEXT: call void @use.ptr(ptr captures(none) [[M]])313; CHECK-NEXT: ret void314;315 %m = call ptr @malloc(i64 24)316 call void @use.ptr(ptr captures(none) %m)317 store i8 0, ptr %m318 ret void319}320 321define void @malloc_address_only_escape() {322; CHECK-LABEL: @malloc_address_only_escape(323; CHECK-NEXT: [[M:%.*]] = call ptr @malloc(i64 24)324; CHECK-NEXT: call void @use.ptr(ptr captures(address) [[M]])325; CHECK-NEXT: ret void326;327 %m = call ptr @malloc(i64 24)328 call void @use.ptr(ptr captures(address) %m)329 store i8 0, ptr %m330 ret void331}332 333define void @malloc_provenance_escape() {334; CHECK-LABEL: @malloc_provenance_escape(335; CHECK-NEXT: [[M:%.*]] = call ptr @malloc(i64 24)336; CHECK-NEXT: call void @use.ptr(ptr captures(provenance) [[M]])337; CHECK-NEXT: store i8 0, ptr [[M]], align 1338; CHECK-NEXT: ret void339;340 %m = call ptr @malloc(i64 24)341 call void @use.ptr(ptr captures(provenance) %m)342 store i8 0, ptr %m343 ret void344}345 346define void @malloc_read_provenance_escape() {347; CHECK-LABEL: @malloc_read_provenance_escape(348; CHECK-NEXT: [[M:%.*]] = call ptr @malloc(i64 24)349; CHECK-NEXT: call void @use.ptr(ptr captures(read_provenance) [[M]])350; CHECK-NEXT: store i8 0, ptr [[M]], align 1351; CHECK-NEXT: ret void352;353 %m = call ptr @malloc(i64 24)354 call void @use.ptr(ptr captures(read_provenance) %m)355 store i8 0, ptr %m356 ret void357}358 359define void @test21() {360; CHECK-LABEL: @test21(361; CHECK-NEXT: ret void362;363 %m = call ptr @calloc(i64 9, i64 7)364 store i8 0, ptr %m365 ret void366}367 368; Currently elimination of stores at the end of a function is limited to a369; single underlying object, for compile-time. This case appears to not be370; very important in practice.371define void @test22(i1 %i, i32 %k, i32 %m) nounwind {372; CHECK-LABEL: @test22(373; CHECK-NEXT: [[K_ADDR:%.*]] = alloca i32, align 4374; CHECK-NEXT: [[M_ADDR:%.*]] = alloca i32, align 4375; CHECK-NEXT: [[K_ADDR_M_ADDR:%.*]] = select i1 [[I:%.*]], ptr [[K_ADDR]], ptr [[M_ADDR]]376; CHECK-NEXT: store i32 0, ptr [[K_ADDR_M_ADDR]], align 4377; CHECK-NEXT: ret void378;379 %k.addr = alloca i32380 %m.addr = alloca i32381 %k.addr.m.addr = select i1 %i, ptr %k.addr, ptr %m.addr382 store i32 0, ptr %k.addr.m.addr, align 4383 ret void384}385 386; PR13547387declare noalias ptr @strdup(ptr nocapture) nounwind388define noalias ptr @test23() nounwind uwtable ssp {389; CHECK-LABEL: @test23(390; CHECK-NEXT: [[X:%.*]] = alloca [2 x i8], align 1391; CHECK-NEXT: store i8 97, ptr [[X]], align 1392; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], ptr [[X]], i64 0, i64 1393; CHECK-NEXT: store i8 0, ptr [[ARRAYIDX1]], align 1394; CHECK-NEXT: [[CALL:%.*]] = call ptr @strdup(ptr [[X]]) #[[ATTR5:[0-9]+]]395; CHECK-NEXT: ret ptr [[CALL]]396;397 %x = alloca [2 x i8], align 1398 store i8 97, ptr %x, align 1399 %arrayidx1 = getelementptr inbounds [2 x i8], ptr %x, i64 0, i64 1400 store i8 0, ptr %arrayidx1, align 1401 %call = call ptr @strdup(ptr %x) nounwind402 ret ptr %call403}404 405; Make sure same sized store to later element is deleted406define void @test24(ptr %a, i32 %b, i32 %c) nounwind {407; CHECK-LABEL: @test24(408; CHECK-NEXT: store i32 [[B:%.*]], ptr [[A:%.*]], align 4409; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i64 0, i64 1410; CHECK-NEXT: store i32 [[C:%.*]], ptr [[TMP1]], align 4411; CHECK-NEXT: ret void412;413 store i32 0, ptr %a, align 4414 %1 = getelementptr inbounds [2 x i32], ptr %a, i64 0, i64 1415 store i32 0, ptr %1, align 4416 store i32 %b, ptr %a, align 4417 %2 = getelementptr inbounds [2 x i32], ptr %a, i64 0, i64 1418 store i32 %c, ptr %2, align 4419 ret void420}421 422; Check another case like PR13547 where strdup is not like malloc.423define ptr @test25(ptr %p) nounwind {424; CHECK-LABEL: @test25(425; CHECK-NEXT: [[P_4:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 4426; CHECK-NEXT: [[TMP:%.*]] = load i8, ptr [[P_4]], align 1427; CHECK-NEXT: store i8 0, ptr [[P_4]], align 1428; CHECK-NEXT: [[Q:%.*]] = call ptr @strdup(ptr [[P]]) #[[ATTR14:[0-9]+]]429; CHECK-NEXT: store i8 [[TMP]], ptr [[P_4]], align 1430; CHECK-NEXT: ret ptr [[Q]]431;432 %p.4 = getelementptr i8, ptr %p, i64 4433 %tmp = load i8, ptr %p.4, align 1434 store i8 0, ptr %p.4, align 1435 %q = call ptr @strdup(ptr %p) nounwind optsize436 store i8 %tmp, ptr %p.4, align 1437 ret ptr %q438}439 440; Don't remove redundant store because of may-aliased store.441define i32 @test28(i1 %c, ptr %p, ptr %p2, i32 %i) {442; CHECK-LABEL: @test28(443; CHECK-NEXT: entry:444; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4445; CHECK-NEXT: store i32 [[I:%.*]], ptr [[P2:%.*]], align 4446; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]447; CHECK: bb1:448; CHECK-NEXT: br label [[BB3:%.*]]449; CHECK: bb2:450; CHECK-NEXT: br label [[BB3]]451; CHECK: bb3:452; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4453; CHECK-NEXT: ret i32 0454;455entry:456 %v = load i32, ptr %p, align 4457 458 ; Might overwrite value at %p459 store i32 %i, ptr %p2, align 4460 br i1 %c, label %bb1, label %bb2461bb1:462 br label %bb3463bb2:464 br label %bb3465bb3:466 store i32 %v, ptr %p, align 4467 ret i32 0468}469 470; Don't remove redundant store because of may-aliased store.471define i32 @test29(i1 %c, ptr %p, ptr %p2, i32 %i) {472; CHECK-LABEL: @test29(473; CHECK-NEXT: entry:474; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4475; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]476; CHECK: bb1:477; CHECK-NEXT: br label [[BB3:%.*]]478; CHECK: bb2:479; CHECK-NEXT: store i32 [[I:%.*]], ptr [[P2:%.*]], align 4480; CHECK-NEXT: br label [[BB3]]481; CHECK: bb3:482; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4483; CHECK-NEXT: ret i32 0484;485entry:486 %v = load i32, ptr %p, align 4487 br i1 %c, label %bb1, label %bb2488bb1:489 br label %bb3490bb2:491 ; Might overwrite value at %p492 store i32 %i, ptr %p2, align 4493 br label %bb3494bb3:495 store i32 %v, ptr %p, align 4496 ret i32 0497}498 499declare void @unknown_func()500 501; Don't remove redundant store because of unknown call.502define i32 @test30(i1 %c, ptr %p, i32 %i) {503; CHECK-LABEL: @test30(504; CHECK-NEXT: entry:505; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4506; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]507; CHECK: bb1:508; CHECK-NEXT: br label [[BB3:%.*]]509; CHECK: bb2:510; CHECK-NEXT: call void @unknown_func()511; CHECK-NEXT: br label [[BB3]]512; CHECK: bb3:513; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4514; CHECK-NEXT: ret i32 0515;516entry:517 %v = load i32, ptr %p, align 4518 br i1 %c, label %bb1, label %bb2519bb1:520 br label %bb3521bb2:522 ; Might overwrite value at %p523 call void @unknown_func()524 br label %bb3525bb3:526 store i32 %v, ptr %p, align 4527 ret i32 0528}529 530; Don't remove redundant store in a loop with a may-alias store.531define i32 @test32(i1 %c, ptr %p, i32 %i, i1 %arg) {532; CHECK-LABEL: @test32(533; CHECK-NEXT: entry:534; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4535; CHECK-NEXT: br label [[BB1:%.*]]536; CHECK: bb1:537; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4538; CHECK-NEXT: call void @unknown_func()539; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB1]], label [[BB2:%.*]]540; CHECK: bb2:541; CHECK-NEXT: ret i32 0542;543entry:544 %v = load i32, ptr %p, align 4545 br label %bb1546bb1:547 store i32 %v, ptr %p, align 4548 ; Might read and overwrite value at %p549 call void @unknown_func()550 br i1 %arg, label %bb1, label %bb2551bb2:552 ret i32 0553}554 555; We cannot remove any stores, because @unknown_func may unwind and the caller556; may read %p while unwinding.557define void @test34(ptr noalias %p) {558; CHECK-LABEL: @test34(559; CHECK-NEXT: store i32 1, ptr [[P:%.*]], align 4560; CHECK-NEXT: call void @unknown_func()561; CHECK-NEXT: store i32 0, ptr [[P]], align 4562; CHECK-NEXT: ret void563;564 store i32 1, ptr %p565 call void @unknown_func()566 store i32 0, ptr %p567 ret void568}569 570; Same as previous case, but with a dead_on_unwind argument.571define void @test34_dead_on_unwind(ptr noalias dead_on_unwind %p) {572; CHECK-LABEL: @test34_dead_on_unwind(573; CHECK-NEXT: call void @unknown_func()574; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4575; CHECK-NEXT: ret void576;577 store i32 1, ptr %p578 call void @unknown_func()579 store i32 0, ptr %p580 ret void581}582 583; Remove redundant store even with an unwinding function in the same block584define void @test35(ptr noalias %p) {585; CHECK-LABEL: @test35(586; CHECK-NEXT: call void @unknown_func()587; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4588; CHECK-NEXT: ret void589;590 call void @unknown_func()591 store i32 1, ptr %p592 store i32 0, ptr %p593 ret void594}595 596; We cannot optimize away the first memmove since %P could overlap with %Q.597define void @test36(ptr %P, ptr %Q) {598; CHECK-LABEL: @test36(599; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)600; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr [[P]], ptr [[Q]], i64 12, i1 false)601; CHECK-NEXT: ret void602;603 604 tail call void @llvm.memmove.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)605 tail call void @llvm.memmove.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)606 ret void607}608 609define void @test36_atomic(ptr %P, ptr %Q) {610; CHECK-LABEL: @test36_atomic(611; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)612; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[Q]], i64 12, i32 1)613; CHECK-NEXT: ret void614;615 616 tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)617 tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)618 ret void619}620 621define void @test37(ptr %P, ptr %Q, ptr %R) {622; CHECK-LABEL: @test37(623; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)624; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr [[P]], ptr [[R:%.*]], i64 12, i1 false)625; CHECK-NEXT: ret void626;627 628 tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)629 tail call void @llvm.memmove.p0.p0.i64(ptr %P, ptr %R, i64 12, i1 false)630 ret void631}632 633define void @test37_atomic(ptr %P, ptr %Q, ptr %R) {634; CHECK-LABEL: @test37_atomic(635; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)636; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[R:%.*]], i64 12, i32 1)637; CHECK-NEXT: ret void638;639 640 tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)641 tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %R, i64 12, i32 1)642 ret void643}644 645; See PR11763 - LLVM allows memcpy's source and destination to be equal (but not646; inequal and overlapping).647define void @test38(ptr %P, ptr %Q, ptr %R) {648; CHECK-LABEL: @test38(649; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)650; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[R:%.*]], i64 12, i1 false)651; CHECK-NEXT: ret void652;653 654 tail call void @llvm.memmove.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)655 tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %R, i64 12, i1 false)656 ret void657}658 659; See PR11763 - LLVM allows memcpy's source and destination to be equal (but not660; inequal and overlapping).661define void @test38_atomic(ptr %P, ptr %Q, ptr %R) {662; CHECK-LABEL: @test38_atomic(663; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)664; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[R:%.*]], i64 12, i32 1)665; CHECK-NEXT: ret void666;667 668 tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)669 tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %R, i64 12, i32 1)670 ret void671}672 673define void @test39(ptr %P, ptr %Q, ptr %R) {674; CHECK-LABEL: @test39(675; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)676; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[R:%.*]], i64 8, i1 false)677; CHECK-NEXT: ret void678;679 680 tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)681 tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %R, i64 8, i1 false)682 ret void683}684 685define void @test39_atomic(ptr %P, ptr %Q, ptr %R) {686; CHECK-LABEL: @test39_atomic(687; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)688; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[R:%.*]], i64 8, i32 1)689; CHECK-NEXT: ret void690;691 692 tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)693 tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %R, i64 8, i32 1)694 ret void695}696 697declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1)698declare void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i32)699 700declare void @llvm.lifetime.start.p0(ptr nocapture) nounwind701declare void @llvm.lifetime.end.p0(ptr nocapture) nounwind702define void @test40(ptr noalias %Pp, ptr noalias %Q) {703; CHECK-LABEL: @test40(704; CHECK-NEXT: entry:705; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4706; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[A]])707; CHECK-NEXT: [[PC:%.*]] = load ptr, ptr [[PP:%.*]], align 8708; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 4 [[A]], ptr align 4 [[Q:%.*]], i64 4, i1 false)709; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[PC]], ptr nonnull align 4 [[A]], i64 4, i1 true)710; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[A]])711; CHECK-NEXT: ret void712;713entry:714 %A = alloca i32, align 4715 call void @llvm.lifetime.start.p0(ptr nonnull %A)716 %Pc = load ptr, ptr %Pp, align 8717 call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 4 %A, ptr align 4 %Q, i64 4, i1 false)718 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %Pc, ptr nonnull align 4 %A, i64 4, i1 true)719 call void @llvm.lifetime.end.p0(ptr nonnull %A)720 ret void721}722 723declare void @free(ptr nocapture) allockind("free")724 725; We cannot remove `store i32 1, ptr %p`, because @unknown_func may unwind726; and the caller may read %p while unwinding.727define void @test41(ptr noalias %P) {728; CHECK-LABEL: @test41(729; CHECK-NEXT: store i32 1, ptr [[P:%.*]], align 4730; CHECK-NEXT: call void @unknown_func()731; CHECK-NEXT: call void @free(ptr [[P]])732; CHECK-NEXT: ret void733;734 store i32 1, ptr %P735 call void @unknown_func()736 store i32 2, ptr %P737 call void @free(ptr %P)738 ret void739}740 741define void @test42(ptr %P, ptr %Q) {742; CHECK-LABEL: @test42(743; CHECK-NEXT: store i32 1, ptr [[P:%.*]], align 4744; CHECK-NEXT: store i32 2, ptr [[Q:%.*]], align 4745; CHECK-NEXT: store i8 3, ptr [[P]], align 1746; CHECK-NEXT: ret void747;748 store i32 1, ptr %P749 store i32 2, ptr %Q750 store i8 3, ptr %P751 ret void752}753 754define void @test42a(ptr %P, ptr %Q) {755; CHECK-LABEL: @test42a(756; CHECK-NEXT: store atomic i32 1, ptr [[P:%.*]] unordered, align 4757; CHECK-NEXT: store atomic i32 2, ptr [[Q:%.*]] unordered, align 4758; CHECK-NEXT: store atomic i8 3, ptr [[P]] unordered, align 4759; CHECK-NEXT: ret void760;761 store atomic i32 1, ptr %P unordered, align 4762 store atomic i32 2, ptr %Q unordered, align 4763 store atomic i8 3, ptr %P unordered, align 4764 ret void765}766 767define void @test43a(ptr %P, ptr noalias %Q) {768; CHECK-LABEL: @test43a(769; CHECK-NEXT: entry:770; CHECK-NEXT: store atomic i32 50331649, ptr [[P:%.*]] unordered, align 4771; CHECK-NEXT: store atomic i32 2, ptr [[Q:%.*]] unordered, align 4772; CHECK-NEXT: ret void773;774entry:775 store atomic i32 1, ptr %P unordered, align 4776 store atomic i32 2, ptr %Q unordered, align 4777 store atomic i8 3, ptr %P unordered, align 4778 ret void779}780 781; Some tests where volatile may block removing a store.782 783; Here we can remove the first non-volatile store. We cannot remove the784; volatile store.785define void @test44_volatile(ptr %P) {786; CHECK-LABEL: @test44_volatile(787; CHECK-NEXT: store volatile i32 2, ptr [[P:%.*]], align 4788; CHECK-NEXT: store i32 3, ptr [[P]], align 4789; CHECK-NEXT: ret void790;791 store i32 1, ptr %P, align 4792 store volatile i32 2, ptr %P, align 4793 store i32 3, ptr %P, align 4794 ret void795}796 797define void @test45_volatile(ptr %P) {798; CHECK-LABEL: @test45_volatile(799; CHECK-NEXT: store volatile i32 2, ptr [[P:%.*]], align 4800; CHECK-NEXT: store volatile i32 3, ptr [[P]], align 4801; CHECK-NEXT: ret void802;803 store i32 1, ptr %P, align 4804 store volatile i32 2, ptr %P, align 4805 store volatile i32 3, ptr %P, align 4806 ret void807}808 809define void @test46_volatile(ptr %P) {810; CHECK-LABEL: @test46_volatile(811; CHECK-NEXT: store volatile i32 2, ptr [[P:%.*]], align 4812; CHECK-NEXT: store volatile i32 3, ptr [[P]], align 4813; CHECK-NEXT: ret void814;815 store volatile i32 2, ptr %P, align 4816 store i32 1, ptr %P, align 4817 store volatile i32 3, ptr %P, align 4818 ret void819}820 821define void @test47_volatile(ptr %P) {822; CHECK-LABEL: @test47_volatile(823; CHECK-NEXT: store volatile i32 2, ptr [[P:%.*]], align 4824; CHECK-NEXT: store volatile i32 3, ptr [[P]], align 4825; CHECK-NEXT: ret void826;827 store volatile i32 2, ptr %P, align 4828 store volatile i32 3, ptr %P, align 4829 ret void830}831 832define i32 @test48(ptr %P, ptr noalias %Q, ptr %R) {833; CHECK-LABEL: @test48(834; CHECK-NEXT: store i32 2, ptr [[P:%.*]], align 4835; CHECK-NEXT: store i32 3, ptr [[Q:%.*]], align 4836; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[R:%.*]], align 4837; CHECK-NEXT: ret i32 [[L]]838;839 store i32 1, ptr %Q840 store i32 2, ptr %P841 store i32 3, ptr %Q842 %l = load i32, ptr %R843 ret i32 %l844}845 846define void @test49() {847; CHECK-LABEL: @test49(848; CHECK-NEXT: bb:849; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr readonly null, i8 0, i64 0, i1 false)850; CHECK-NEXT: store ptr null, ptr null, align 8851; CHECK-NEXT: ret void852;853bb:854 call void @llvm.memset.p0.i64(ptr readonly null, i8 0, i64 0, i1 false)855 store ptr null, ptr null, align 8856 ret void857}858 859define void @test_dead_on_return(ptr dead_on_return %p) {860; CHECK-LABEL: @test_dead_on_return(861; CHECK-NEXT: ret void862;863 store i8 0, ptr %p864 ret void865}866 867define void @test_dead_on_return_maythrow(ptr dead_on_return %p) {868; CHECK-LABEL: @test_dead_on_return_maythrow(869; CHECK-NEXT: call void @maythrow()870; CHECK-NEXT: ret void871;872 store i8 0, ptr %p873 call void @maythrow()874 ret void875}876 877define ptr @test_dead_on_return_ptr_returned(ptr dead_on_return %p) {878; CHECK-LABEL: @test_dead_on_return_ptr_returned(879; CHECK-NEXT: [[LOCAL_VAR:%.*]] = alloca ptr, align 8880; CHECK-NEXT: call void @opaque(ptr [[LOCAL_VAR]])881; CHECK-NEXT: ret ptr [[P:%.*]]882;883 %local.var = alloca ptr884 call void @opaque(ptr %local.var)885 store ptr %local.var, ptr %p886 ret ptr %p887}888 889declare void @opaque(ptr)890declare void @maythrow() memory(none)891