789 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=dse -dse-optimize-memoryssa=false -S %s | FileCheck --check-prefixes=CHECK,UNOPT %s3; RUN: opt -passes=dse -dse-optimize-memoryssa -S %s | FileCheck --check-prefixes=CHECK,OPT %s4; RUN: opt -passes=dse -S %s | FileCheck --check-prefixes=CHECK,OPT %s5 6target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"7 8@a = external global [32 x i8], align 169 10declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)11 12; Test case for PR16520. The store in %if.then is redundant, because the same value13; has been stored earlier to the same location.14define void @test1_pr16520(i1 %b, ptr nocapture %r) {15; CHECK-LABEL: @test1_pr16520(16; CHECK-NEXT: entry:17; CHECK-NEXT: store i8 1, ptr [[R:%.*]], align 118; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]19; CHECK: if.then:20; CHECK-NEXT: tail call void @fn_mayread_or_clobber()21; CHECK-NEXT: br label [[IF_END:%.*]]22; CHECK: if.else:23; CHECK-NEXT: tail call void @fn_mayread_or_clobber()24; CHECK-NEXT: br label [[IF_END]]25; CHECK: if.end:26; CHECK-NEXT: ret void27;28entry:29 store i8 1, ptr %r, align 130 br i1 %b, label %if.then, label %if.else31 32if.then: ; preds = %entry33 store i8 1, ptr %r, align 134 tail call void @fn_mayread_or_clobber()35 br label %if.end36 37if.else: ; preds = %entry38 tail call void @fn_mayread_or_clobber()39 br label %if.end40 41if.end: ; preds = %if.else, %if.then42 ret void43}44 45declare void @fn_mayread_or_clobber()46declare void @fn_readonly() readonly47 48define void @test2(i1 %b, ptr nocapture %r) {49; CHECK-LABEL: @test2(50; CHECK-NEXT: entry:51; CHECK-NEXT: store i8 1, ptr [[R:%.*]], align 152; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]53; CHECK: if.then:54; CHECK-NEXT: tail call void @fn_readonly()55; CHECK-NEXT: br label [[IF_END:%.*]]56; CHECK: if.else:57; CHECK-NEXT: tail call void @fn_readonly()58; CHECK-NEXT: br label [[IF_END]]59; CHECK: if.end:60; CHECK-NEXT: ret void61;62entry:63 store i8 1, ptr %r, align 164 br i1 %b, label %if.then, label %if.else65 66if.then: ; preds = %entry67 tail call void @fn_readonly()68 br label %if.end69 70if.else: ; preds = %entry71 tail call void @fn_readonly()72 br label %if.end73 74if.end: ; preds = %if.else, %if.then75 store i8 1, ptr %r, align 176 ret void77}78 79; Make sure volatile stores are not removed.80define void @test2_volatile(i1 %b, ptr nocapture %r) {81; CHECK-LABEL: @test2_volatile(82; CHECK-NEXT: entry:83; CHECK-NEXT: store volatile i8 1, ptr [[R:%.*]], align 184; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]85; CHECK: if.then:86; CHECK-NEXT: tail call void @fn_readonly()87; CHECK-NEXT: br label [[IF_END:%.*]]88; CHECK: if.else:89; CHECK-NEXT: tail call void @fn_readonly()90; CHECK-NEXT: br label [[IF_END]]91; CHECK: if.end:92; CHECK-NEXT: store volatile i8 1, ptr [[R]], align 193; CHECK-NEXT: ret void94;95entry:96 store volatile i8 1, ptr %r, align 197 br i1 %b, label %if.then, label %if.else98 99if.then: ; preds = %entry100 tail call void @fn_readonly()101 br label %if.end102 103if.else: ; preds = %entry104 tail call void @fn_readonly()105 br label %if.end106 107if.end: ; preds = %if.else, %if.then108 store volatile i8 1, ptr %r, align 1109 ret void110}111 112define void @test3(i1 %b, ptr nocapture %r) {113; CHECK-LABEL: @test3(114; CHECK-NEXT: entry:115; CHECK-NEXT: store i8 1, ptr [[R:%.*]], align 1116; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]117; CHECK: if.then:118; CHECK-NEXT: tail call void @fn_mayread_or_clobber()119; CHECK-NEXT: br label [[IF_END:%.*]]120; CHECK: if.else:121; CHECK-NEXT: tail call void @fn_readonly()122; CHECK-NEXT: br label [[IF_END]]123; CHECK: if.end:124; CHECK-NEXT: store i8 1, ptr [[R]], align 1125; CHECK-NEXT: ret void126;127entry:128 store i8 1, ptr %r, align 1129 br i1 %b, label %if.then, label %if.else130 131if.then: ; preds = %entry132 tail call void @fn_mayread_or_clobber()133 br label %if.end134 135if.else: ; preds = %entry136 tail call void @fn_readonly()137 br label %if.end138 139if.end: ; preds = %if.else, %if.then140 store i8 1, ptr %r, align 1141 ret void142}143 144define void @test4(i1 %b, ptr nocapture %r) {145; CHECK-LABEL: @test4(146; CHECK-NEXT: entry:147; CHECK-NEXT: store i8 1, ptr [[R:%.*]], align 1148; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]149; CHECK: if.then:150; CHECK-NEXT: tail call void @fn_readonly()151; CHECK-NEXT: br label [[IF_END:%.*]]152; CHECK: if.else:153; CHECK-NEXT: tail call void @fn_mayread_or_clobber()154; CHECK-NEXT: br label [[IF_END]]155; CHECK: if.end:156; CHECK-NEXT: store i8 1, ptr [[R]], align 1157; CHECK-NEXT: ret void158;159entry:160 store i8 1, ptr %r, align 1161 br i1 %b, label %if.then, label %if.else162 163if.then: ; preds = %entry164 tail call void @fn_readonly()165 br label %if.end166 167if.else: ; preds = %entry168 tail call void @fn_mayread_or_clobber()169 br label %if.end170 171if.end: ; preds = %if.else, %if.then172 store i8 1, ptr %r, align 1173 ret void174}175 176define void @test5(i1 %b, ptr nocapture %r) {177; CHECK-LABEL: @test5(178; CHECK-NEXT: entry:179; CHECK-NEXT: store i8 1, ptr [[R:%.*]], align 1180; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]181; CHECK: if.then:182; CHECK-NEXT: tail call void @fn_readonly()183; CHECK-NEXT: br label [[IF_END:%.*]]184; CHECK: if.else:185; CHECK-NEXT: tail call void @fn_mayread_or_clobber()186; CHECK-NEXT: br label [[IF_END]]187; CHECK: if.end:188; CHECK-NEXT: store i8 1, ptr [[R]], align 1189; CHECK-NEXT: ret void190;191entry:192 store i8 1, ptr %r, align 1193 br i1 %b, label %if.then, label %if.else194 195if.then: ; preds = %entry196 tail call void @fn_readonly()197 br label %if.end198 199if.else: ; preds = %entry200 tail call void @fn_mayread_or_clobber()201 br label %if.end202 203if.end: ; preds = %if.else, %if.then204 store i8 1, ptr %r, align 1205 ret void206}207 208declare i1 @cond() readnone209 210define void @test6(ptr noalias %P) {211; CHECK-LABEL: @test6(212; CHECK-NEXT: entry:213; CHECK-NEXT: br label [[FOR_HEADER:%.*]]214; CHECK: for.header:215; CHECK-NEXT: store i32 1, ptr [[P:%.*]], align 4216; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()217; CHECK-NEXT: br i1 [[C1]], label [[FOR_BODY:%.*]], label [[END:%.*]]218; CHECK: for.body:219; CHECK-NEXT: [[LV:%.*]] = load i32, ptr [[P]], align 4220; CHECK-NEXT: br label [[FOR_HEADER]]221; CHECK: end:222; CHECK-NEXT: store i32 3, ptr [[P]], align 4223; CHECK-NEXT: ret void224;225entry:226 br label %for.header227 228for.header:229 store i32 1, ptr %P, align 4230 %c1 = call i1 @cond()231 br i1 %c1, label %for.body, label %end232 233for.body:234 store i32 1, ptr %P, align 4235 %lv = load i32, ptr %P236 br label %for.header237 238end:239 store i32 3, ptr %P, align 4240 ret void241}242 243; Make sure the store in %bb3 can be eliminated in the presences of early returns.244define void @test7(ptr noalias %P) {245; CHECK-LABEL: @test7(246; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4247; CHECK-NEXT: br i1 true, label [[BB1:%.*]], label [[BB2:%.*]]248; CHECK: bb1:249; CHECK-NEXT: br label [[BB3:%.*]]250; CHECK: bb2:251; CHECK-NEXT: ret void252; CHECK: bb3:253; CHECK-NEXT: ret void254;255 store i32 0, ptr %P256 br i1 true, label %bb1, label %bb2257bb1:258 br label %bb3259bb2:260 ret void261bb3:262 store i32 0, ptr %P263 ret void264}265 266; Make sure the store in %bb3 won't be eliminated because it may be clobbered before.267define void @test8(ptr %P) {268; CHECK-LABEL: @test8(269; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4270; CHECK-NEXT: br i1 true, label [[BB1:%.*]], label [[BB2:%.*]]271; CHECK: bb1:272; CHECK-NEXT: call void @fn_mayread_or_clobber()273; CHECK-NEXT: br label [[BB3:%.*]]274; CHECK: bb2:275; CHECK-NEXT: ret void276; CHECK: bb3:277; CHECK-NEXT: store i32 0, ptr [[P]], align 4278; CHECK-NEXT: ret void279;280 store i32 0, ptr %P281 br i1 true, label %bb1, label %bb2282bb1:283 call void @fn_mayread_or_clobber()284 br label %bb3285bb2:286 ret void287bb3:288 store i32 0, ptr %P289 ret void290}291 292; Make sure the store in %bb3 will be eliminated because only the early exit path293; may be clobbered.294define void @test9(ptr noalias %P) {295; CHECK-LABEL: @test9(296; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4297; CHECK-NEXT: br i1 true, label [[BB1:%.*]], label [[BB2:%.*]]298; CHECK: bb1:299; CHECK-NEXT: br label [[BB3:%.*]]300; CHECK: bb2:301; CHECK-NEXT: call void @fn_mayread_or_clobber()302; CHECK-NEXT: ret void303; CHECK: bb3:304; CHECK-NEXT: ret void305;306 store i32 0, ptr %P307 br i1 true, label %bb1, label %bb2308bb1:309 br label %bb3310bb2:311 call void @fn_mayread_or_clobber()312 ret void313bb3:314 store i32 0, ptr %P315 ret void316}317 318; The store in bb3 can be eliminated, because the store in bb1 cannot alias it.319define void @test10(ptr noalias %P, ptr %Q, i1 %c) {320; UNOPT-LABEL: @test10(321; UNOPT-NEXT: store i32 0, ptr [[P:%.*]], align 4322; UNOPT-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]323; UNOPT: bb1:324; UNOPT-NEXT: store i32 10, ptr [[Q:%.*]], align 4325; UNOPT-NEXT: br label [[BB3:%.*]]326; UNOPT: bb2:327; UNOPT-NEXT: ret void328; UNOPT: bb3:329; UNOPT-NEXT: store i32 0, ptr [[P]], align 4330; UNOPT-NEXT: ret void331;332; OPT-LABEL: @test10(333; OPT-NEXT: store i32 0, ptr [[P:%.*]], align 4334; OPT-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]335; OPT: bb1:336; OPT-NEXT: store i32 10, ptr [[Q:%.*]], align 4337; OPT-NEXT: br label [[BB3:%.*]]338; OPT: bb2:339; OPT-NEXT: ret void340; OPT: bb3:341; OPT-NEXT: ret void342;343 store i32 0, ptr %P344 br i1 %c, label %bb1, label %bb2345 346bb1:347 store i32 10, ptr %Q348 br label %bb3349 350bb2:351 ret void352 353bb3:354 store i32 0, ptr %P355 ret void356}357 358define void @test11_smaller_later_store(ptr noalias %P, ptr %Q, i1 %c) {359; CHECK-LABEL: @test11_smaller_later_store(360; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4361; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]362; CHECK: bb1:363; CHECK-NEXT: br label [[BB3:%.*]]364; CHECK: bb2:365; CHECK-NEXT: ret void366; CHECK: bb3:367; CHECK-NEXT: store i8 0, ptr [[P]], align 1368; CHECK-NEXT: ret void369;370 store i32 0, ptr %P371 br i1 %c, label %bb1, label %bb2372 373bb1:374 br label %bb3375 376bb2:377 ret void378 379bb3:380 store i8 0, ptr %P381 ret void382}383 384define void @test11_smaller_earlier_store(ptr noalias %P, ptr %Q, i1 %c) {385; CHECK-LABEL: @test11_smaller_earlier_store(386; CHECK-NEXT: store i8 0, ptr [[P:%.*]], align 1387; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]388; CHECK: bb1:389; CHECK-NEXT: br label [[BB3:%.*]]390; CHECK: bb2:391; CHECK-NEXT: ret void392; CHECK: bb3:393; CHECK-NEXT: store i32 0, ptr [[P]], align 4394; CHECK-NEXT: ret void395;396 store i8 0, ptr %P397 br i1 %c, label %bb1, label %bb2398 399bb1:400 br label %bb3401 402bb2:403 ret void404 405bb3:406 store i32 0, ptr %P407 ret void408}409 410declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1411 412define void @test12_memset_simple(ptr %ptr) {413; CHECK-LABEL: @test12_memset_simple(414; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[PTR:%.*]], i8 0, i64 10, i1 false)415; CHECK-NEXT: ret void416;417 call void @llvm.memset.p0.i64(ptr %ptr, i8 0, i64 10, i1 false)418 %ptr.5 = getelementptr i8, ptr %ptr, i64 4419 store i8 0, ptr %ptr.5420 ret void421}422 423define void @test12_memset_other_store_in_between(ptr %ptr) {424; UNOPT-LABEL: @test12_memset_other_store_in_between(425; UNOPT-NEXT: call void @llvm.memset.p0.i64(ptr [[PTR:%.*]], i8 0, i64 10, i1 false)426; UNOPT-NEXT: [[PTR_4:%.*]] = getelementptr i8, ptr [[PTR]], i64 4427; UNOPT-NEXT: store i8 8, ptr [[PTR_4]], align 1428; UNOPT-NEXT: [[PTR_5:%.*]] = getelementptr i8, ptr [[PTR]], i64 5429; UNOPT-NEXT: store i8 0, ptr [[PTR_5]], align 1430; UNOPT-NEXT: ret void431;432; OPT-LABEL: @test12_memset_other_store_in_between(433; OPT-NEXT: call void @llvm.memset.p0.i64(ptr [[PTR:%.*]], i8 0, i64 10, i1 false)434; OPT-NEXT: [[PTR_4:%.*]] = getelementptr i8, ptr [[PTR]], i64 4435; OPT-NEXT: store i8 8, ptr [[PTR_4]], align 1436; OPT-NEXT: ret void437;438 call void @llvm.memset.p0.i64(ptr %ptr, i8 0, i64 10, i1 false)439 %ptr.4 = getelementptr i8, ptr %ptr, i64 4440 store i8 8, ptr %ptr.4441 %ptr.5 = getelementptr i8, ptr %ptr, i64 5442 store i8 0, ptr %ptr.5443 ret void444}445 446declare ptr @__memset_chk(ptr writeonly, i32, i64, i64) argmemonly writeonly nofree nounwind447 448define void @test12_memset_chk_other_store_in_between(ptr %ptr) {449; CHECK-LABEL: @test12_memset_chk_other_store_in_between(450; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @__memset_chk(ptr [[PTR:%.*]], i32 0, i64 10, i64 -1)451; CHECK-NEXT: [[PTR_4:%.*]] = getelementptr i8, ptr [[PTR]], i64 4452; CHECK-NEXT: store i8 8, ptr [[PTR_4]], align 1453; CHECK-NEXT: [[PTR_5:%.*]] = getelementptr i8, ptr [[PTR]], i64 5454; CHECK-NEXT: store i8 0, ptr [[PTR_5]], align 1455; CHECK-NEXT: ret void456;457 %call = tail call ptr @__memset_chk(ptr %ptr, i32 0, i64 10, i64 -1)458 %ptr.4 = getelementptr i8, ptr %ptr, i64 4459 store i8 8, ptr %ptr.4460 %ptr.5 = getelementptr i8, ptr %ptr, i64 5461 store i8 0, ptr %ptr.5462 ret void463}464 465declare void @use(ptr)466 467define void @test12_memset_chk_other_store_in_between_stack_obj_escape_after(i64 %n) {468; CHECK-LABEL: @test12_memset_chk_other_store_in_between_stack_obj_escape_after(469; CHECK-NEXT: [[OBJ:%.*]] = alloca [200 x i8], align 1470; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @__memset_chk(ptr [[OBJ]], i32 0, i64 10, i64 [[N:%.*]])471; CHECK-NEXT: [[PTR_4:%.*]] = getelementptr i8, ptr [[OBJ]], i64 4472; CHECK-NEXT: store i8 8, ptr [[PTR_4]], align 1473; CHECK-NEXT: [[PTR_5:%.*]] = getelementptr i8, ptr [[OBJ]], i64 5474; CHECK-NEXT: store i8 0, ptr [[PTR_5]], align 1475; CHECK-NEXT: call void @use(ptr [[OBJ]])476; CHECK-NEXT: ret void477;478 %obj = alloca [200 x i8]479 %call = tail call ptr @__memset_chk(ptr %obj, i32 0, i64 10, i64 %n)480 %ptr.4 = getelementptr i8, ptr %obj, i64 4481 store i8 8, ptr %ptr.4482 %ptr.5 = getelementptr i8, ptr %obj, i64 5483 store i8 0, ptr %ptr.5484 call void @use(ptr %obj)485 ret void486}487 488define void @test12_memset_chk_other_store_in_between_stack_obj_escape_before(i64 %n) {489; CHECK-LABEL: @test12_memset_chk_other_store_in_between_stack_obj_escape_before(490; CHECK-NEXT: [[OBJ:%.*]] = alloca [200 x i8], align 1491; CHECK-NEXT: call void @use(ptr [[OBJ]])492; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @__memset_chk(ptr [[OBJ]], i32 0, i64 10, i64 [[N:%.*]])493; CHECK-NEXT: [[PTR_4:%.*]] = getelementptr i8, ptr [[OBJ]], i64 4494; CHECK-NEXT: store i8 8, ptr [[PTR_4]], align 1495; CHECK-NEXT: [[PTR_5:%.*]] = getelementptr i8, ptr [[OBJ]], i64 5496; CHECK-NEXT: store i8 0, ptr [[PTR_5]], align 1497; CHECK-NEXT: [[PTR_10:%.*]] = getelementptr i8, ptr [[OBJ]], i64 10498; CHECK-NEXT: store i8 0, ptr [[PTR_10]], align 1499; CHECK-NEXT: call void @use(ptr [[OBJ]])500; CHECK-NEXT: ret void501;502 %obj = alloca [200 x i8]503 call void @use(ptr %obj)504 %call = tail call ptr @__memset_chk(ptr %obj, i32 0, i64 10, i64 %n)505 %ptr.4 = getelementptr i8, ptr %obj, i64 4506 store i8 8, ptr %ptr.4507 %ptr.5 = getelementptr i8, ptr %obj, i64 5508 store i8 0, ptr %ptr.5509 %ptr.10 = getelementptr i8, ptr %obj, i64 10510 store i8 0, ptr %ptr.10511 call void @use(ptr %obj)512 ret void513}514 515define void @test12_memset_other_store_in_between_partial_overlap(ptr %ptr) {516; CHECK-LABEL: @test12_memset_other_store_in_between_partial_overlap(517; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[PTR:%.*]], i8 0, i64 10, i1 false)518; CHECK-NEXT: [[PTR_4:%.*]] = getelementptr i8, ptr [[PTR]], i64 4519; CHECK-NEXT: store i16 8, ptr [[PTR_4]], align 2520; CHECK-NEXT: [[PTR_5:%.*]] = getelementptr i8, ptr [[PTR]], i64 5521; CHECK-NEXT: store i16 0, ptr [[PTR_5]], align 2522; CHECK-NEXT: ret void523;524 call void @llvm.memset.p0.i64(ptr %ptr, i8 0, i64 10, i1 false)525 %ptr.4 = getelementptr i8, ptr %ptr, i64 4526 store i16 8, ptr %ptr.4527 %ptr.5 = getelementptr i8, ptr %ptr, i64 5528 store i16 0, ptr %ptr.5529 ret void530}531 532define void @test12_memset_later_store_exceeds_memset(ptr %ptr) {533; CHECK-LABEL: @test12_memset_later_store_exceeds_memset(534; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[PTR:%.*]], i8 0, i64 8, i1 false)535; CHECK-NEXT: [[PTR_4:%.*]] = getelementptr i8, ptr [[PTR]], i64 4536; CHECK-NEXT: store i8 8, ptr [[PTR_4]], align 1537; CHECK-NEXT: [[PTR_5:%.*]] = getelementptr i8, ptr [[PTR]], i64 8538; CHECK-NEXT: store i64 0, ptr [[PTR_5]], align 8539; CHECK-NEXT: ret void540;541 call void @llvm.memset.p0.i64(ptr %ptr, i8 0, i64 10, i1 false)542 %ptr.4 = getelementptr i8, ptr %ptr, i64 4543 store i8 8, ptr %ptr.4544 %ptr.5 = getelementptr i8, ptr %ptr, i64 8545 store i64 0, ptr %ptr.5546 ret void547}548 549define void @test12_memset_later_store_before_memset(ptr %ptr) {550; CHECK-LABEL: @test12_memset_later_store_before_memset(551; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i64 1552; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[PTR_1]], i64 7553; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 0, i64 3, i1 false)554; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8555; CHECK-NEXT: ret void556;557 %ptr.1 = getelementptr i8, ptr %ptr, i64 1558 call void @llvm.memset.p0.i64(ptr %ptr.1, i8 0, i64 10, i1 false)559 %ptr.4 = getelementptr i8, ptr %ptr, i64 4560 store i8 8, ptr %ptr.4561 store i64 0, ptr %ptr562 ret void563}564 565; The memset will be shortened and the store will not be redundant afterwards.566; It cannot be eliminated.567define void @test13_memset_shortened(ptr %ptr) {568; CHECK-LABEL: @test13_memset_shortened(569; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 8570; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 0, i64 16, i1 false)571; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8572; CHECK-NEXT: ret void573;574 call void @llvm.memset.p0.i64(ptr %ptr, i8 0, i64 24, i1 false)575 store i64 0, ptr %ptr576 ret void577}578 579declare ptr @strcat(ptr, ptr) nounwind argmemonly580 581define void @test14_strcat(ptr noalias %P, ptr noalias %Q) {582; CHECK-LABEL: @test14_strcat(583; CHECK-NEXT: [[CALL1:%.*]] = call ptr @strcat(ptr [[P:%.*]], ptr [[Q:%.*]])584; CHECK-NEXT: [[CALL2:%.*]] = call ptr @strcat(ptr [[P]], ptr [[Q]])585; CHECK-NEXT: ret void586;587 %call1 = call ptr @strcat(ptr %P, ptr %Q)588 ; FIXME: Eliminate the second strcat as a "store of existing value" for this particular case, where both strcat's are identical (same source, not just same dest).589 %call2 = call ptr @strcat(ptr %P, ptr %Q)590 ret void591}592 593define void @pr49927(ptr %q, ptr %p) {594; CHECK-LABEL: @pr49927(595; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4596; CHECK-NEXT: store i32 [[V]], ptr [[Q:%.*]], align 4597; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4598; CHECK-NEXT: ret void599;600 %v = load i32, ptr %p, align 4601 store i32 %v, ptr %q, align 4602 store i32 %v, ptr %p, align 4603 ret void604}605 606define void @pr50339(ptr nocapture readonly %0) {607; CHECK-LABEL: @pr50339(608; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(16) @a, ptr noundef nonnull align 1 dereferenceable(16) [[TMP0:%.*]], i64 16, i1 false)609; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(16) @a, ptr noundef nonnull align 1 dereferenceable(16) [[TMP0]], i64 16, i1 false)610; CHECK-NEXT: ret void611;612 tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(16) @a, ptr noundef nonnull align 1 dereferenceable(16) %0, i64 16, i1 false)613 ; FIXME: Eliminate the second memcpy as a "store of existing value" for this particular case, where both memcpy's are identical (same source, not just same dest).614 tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(16) @a, ptr noundef nonnull align 1 dereferenceable(16) %0, i64 16, i1 false)615 ret void616}617 618; Cannot remove the second memcpy as redundant store, because %src is modified619; in between.620define i8 @memset_optimized_access(ptr noalias %dst, ptr noalias %src) {621; CHECK-LABEL: @memset_optimized_access(622; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr [[SRC:%.*]], i64 16, i1 false)623; CHECK-NEXT: store i8 99, ptr [[SRC]], align 1624; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[DST]], align 1625; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC]], i64 16, i1 false)626; CHECK-NEXT: ret i8 [[L]]627;628 tail call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 16, i1 false)629 store i8 99, ptr %src630 %l = load i8, ptr %dst631 tail call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 16, i1 false)632 ret i8 %l633}634 635; The @use() call is a later non-removable store, but should not affect the636; removal of the store in the if block.637define void @later_non_removable_store(i1 %c, ptr %p) {638; CHECK-LABEL: @later_non_removable_store(639; CHECK-NEXT: store i8 1, ptr [[P:%.*]], align 1640; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[EXIT:%.*]]641; CHECK: if:642; CHECK-NEXT: br label [[EXIT]]643; CHECK: exit:644; CHECK-NEXT: call void @use(ptr [[P]]) #[[ATTR7:[0-9]+]]645; CHECK-NEXT: ret void646;647 store i8 1, ptr %p648 br i1 %c, label %if, label %exit649 650if:651 store i8 1, ptr %p652 br label %exit653 654exit:655 call void @use(ptr %p) argmemonly656 ret void657}658 659define void @scalable_scalable_redundant_store(ptr %ptr) {660; CHECK-LABEL: @scalable_scalable_redundant_store(661; CHECK-NEXT: [[GEP_PTR_2:%.*]] = getelementptr i64, ptr [[PTR:%.*]], i64 2662; CHECK-NEXT: store <vscale x 2 x i64> zeroinitializer, ptr [[GEP_PTR_2]], align 16663; CHECK-NEXT: store <vscale x 4 x i64> zeroinitializer, ptr [[PTR]], align 32664; CHECK-NEXT: ret void665;666 %gep.ptr.2 = getelementptr i64, ptr %ptr, i64 2667 store <vscale x 2 x i64> zeroinitializer, ptr %gep.ptr.2668 store <vscale x 4 x i64> zeroinitializer, ptr %ptr669 ret void670}671 672define void @scalable_scalable_neg(ptr %ptr) {673; CHECK-LABEL: @scalable_scalable_neg(674; CHECK-NEXT: [[GEP_PTR_8:%.*]] = getelementptr i64, ptr [[PTR:%.*]], i64 8675; CHECK-NEXT: store <vscale x 4 x i64> zeroinitializer, ptr [[GEP_PTR_8]], align 32676; CHECK-NEXT: store <vscale x 2 x i64> zeroinitializer, ptr [[PTR]], align 16677; CHECK-NEXT: ret void678;679 %gep.ptr.8 = getelementptr i64, ptr %ptr, i64 8680 store <vscale x 4 x i64> zeroinitializer, ptr %gep.ptr.8681 store <vscale x 2 x i64> zeroinitializer, ptr %ptr682 ret void683}684 685define void @scalable_scalable_nonconst_offset_neg(ptr %ptr, i64 %i) {686; CHECK-LABEL: @scalable_scalable_nonconst_offset_neg(687; CHECK-NEXT: [[GEP_PTR_I:%.*]] = getelementptr i64, ptr [[PTR:%.*]], i64 [[I:%.*]]688; CHECK-NEXT: store <vscale x 2 x i64> zeroinitializer, ptr [[GEP_PTR_I]], align 16689; CHECK-NEXT: store <vscale x 4 x i64> zeroinitializer, ptr [[PTR]], align 32690; CHECK-NEXT: ret void691;692 %gep.ptr.i = getelementptr i64, ptr %ptr, i64 %i693 store <vscale x 2 x i64> zeroinitializer, ptr %gep.ptr.i694 store <vscale x 4 x i64> zeroinitializer, ptr %ptr695 ret void696}697 698define void @scalable_fixed_redundant_store(ptr %ptr) vscale_range(1, 2) {699; CHECK-LABEL: @scalable_fixed_redundant_store(700; CHECK-NEXT: [[GEP_PTR_2:%.*]] = getelementptr i64, ptr [[PTR:%.*]], i64 2701; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr [[GEP_PTR_2]], align 16702; CHECK-NEXT: store <vscale x 4 x i64> zeroinitializer, ptr [[PTR]], align 32703; CHECK-NEXT: ret void704;705 %gep.ptr.2 = getelementptr i64, ptr %ptr, i64 2706 store <2 x i64> zeroinitializer, ptr %gep.ptr.2707 store <vscale x 4 x i64> zeroinitializer, ptr %ptr708 ret void709}710 711define void @scalable_fixed_neg(ptr %ptr) vscale_range(1, 2) {712; CHECK-LABEL: @scalable_fixed_neg(713; CHECK-NEXT: [[GEP_PTR_16:%.*]] = getelementptr i64, ptr [[PTR:%.*]], i64 16714; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr [[GEP_PTR_16]], align 16715; CHECK-NEXT: store <vscale x 4 x i64> zeroinitializer, ptr [[PTR]], align 32716; CHECK-NEXT: ret void717;718 %gep.ptr.16 = getelementptr i64, ptr %ptr, i64 16719 store <2 x i64> zeroinitializer, ptr %gep.ptr.16720 store <vscale x 4 x i64> zeroinitializer, ptr %ptr721 ret void722}723 724define void @fixed_scalable_redundant_store(ptr %ptr) vscale_range(1, 2) {725; CHECK-LABEL: @fixed_scalable_redundant_store(726; CHECK-NEXT: [[GEP_PTR_2:%.*]] = getelementptr i64, ptr [[PTR:%.*]], i64 2727; CHECK-NEXT: store <vscale x 2 x i64> zeroinitializer, ptr [[GEP_PTR_2]], align 16728; CHECK-NEXT: store <8 x i64> zeroinitializer, ptr [[PTR]], align 64729; CHECK-NEXT: ret void730;731 %gep.ptr.2 = getelementptr i64, ptr %ptr, i64 2732 store <vscale x 2 x i64> zeroinitializer, ptr %gep.ptr.2733 store <8 x i64> zeroinitializer, ptr %ptr734 ret void735}736 737define void @fixed_scalable_neg(ptr %ptr) vscale_range(1, 2) {738; CHECK-LABEL: @fixed_scalable_neg(739; CHECK-NEXT: [[GEP_PTR_2:%.*]] = getelementptr i64, ptr [[PTR:%.*]], i64 2740; CHECK-NEXT: store <vscale x 2 x i64> zeroinitializer, ptr [[GEP_PTR_2]], align 16741; CHECK-NEXT: store <4 x i64> zeroinitializer, ptr [[PTR]], align 32742; CHECK-NEXT: ret void743;744 %gep.ptr.2 = getelementptr i64, ptr %ptr, i64 2745 store <vscale x 2 x i64> zeroinitializer, ptr %gep.ptr.2746 store <4 x i64> zeroinitializer, ptr %ptr747 ret void748}749 750define void @memset_different_attributes_1(i1 %c, ptr %ptr) {751; CHECK-LABEL: @memset_different_attributes_1(752; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[PTR:%.*]], i8 0, i64 20, i1 false)753; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[END:%.*]]754; CHECK: if:755; CHECK-NEXT: br label [[END]]756; CHECK: end:757; CHECK-NEXT: ret void758;759 call void @llvm.memset.p0.i64(ptr %ptr, i8 0, i64 20, i1 false)760 br i1 %c, label %if, label %end761 762if:763 call void @llvm.memset.p0.i64(ptr dereferenceable(20) %ptr, i8 0, i64 20, i1 false)764 br label %end765 766end:767 ret void768}769 770define void @memset_different_attributes_2(i1 %c, ptr %ptr) {771; CHECK-LABEL: @memset_different_attributes_2(772; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr dereferenceable(20) [[PTR:%.*]], i8 0, i64 20, i1 false)773; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[END:%.*]]774; CHECK: if:775; CHECK-NEXT: br label [[END]]776; CHECK: end:777; CHECK-NEXT: ret void778;779 call void @llvm.memset.p0.i64(ptr dereferenceable(20) %ptr, i8 0, i64 20, i1 false)780 br i1 %c, label %if, label %end781 782if:783 call void @llvm.memset.p0.i64(ptr %ptr, i8 0, i64 20, i1 false)784 br label %end785 786end:787 ret void788}789