1168 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -aa-pipeline=basic-aa -passes='dse,verify<memoryssa>' -S | FileCheck %s3target 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"4 5declare void @memset_pattern16(ptr, ptr, i64)6 7declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind8declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr nocapture, i8, i64, i32) nounwind9declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind10declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i32) nounwind11declare void @llvm.init.trampoline(ptr, ptr, ptr)12 13; **** Noop load->store tests **************************************************14 15; We CAN optimize volatile loads.16define void @test_load_volatile(ptr %Q) {17; CHECK-LABEL: @test_load_volatile(18; CHECK-NEXT: [[A:%.*]] = load volatile i32, ptr [[Q:%.*]], align 419; CHECK-NEXT: ret void20;21 %a = load volatile i32, ptr %Q22 store i32 %a, ptr %Q23 ret void24}25 26; We can NOT optimize volatile stores.27define void @test_store_volatile(ptr %Q) {28; CHECK-LABEL: @test_store_volatile(29; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[Q:%.*]], align 430; CHECK-NEXT: store volatile i32 [[A]], ptr [[Q]], align 431; CHECK-NEXT: ret void32;33 %a = load i32, ptr %Q34 store volatile i32 %a, ptr %Q35 ret void36}37 38; PR2599 - load -> store to same address.39define void @test12(ptr %x) nounwind {40; CHECK-LABEL: @test12(41; CHECK-NEXT: [[TEMP7:%.*]] = getelementptr { i32, i32 }, ptr [[X:%.*]], i32 0, i32 142; CHECK-NEXT: [[TEMP8:%.*]] = load i32, ptr [[TEMP7]], align 443; CHECK-NEXT: [[TEMP17:%.*]] = sub i32 0, [[TEMP8]]44; CHECK-NEXT: store i32 [[TEMP17]], ptr [[TEMP7]], align 445; CHECK-NEXT: ret void46;47 %temp4 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 048 %temp5 = load i32, ptr %temp4, align 449 %temp7 = getelementptr { i32, i32 }, ptr %x, i32 0, i32 150 %temp8 = load i32, ptr %temp7, align 451 %temp17 = sub i32 0, %temp852 store i32 %temp5, ptr %temp4, align 453 store i32 %temp17, ptr %temp7, align 454 ret void55}56 57; Remove redundant store if loaded value is in another block.58define i32 @test26(i1 %c, ptr %p) {59; CHECK-LABEL: @test26(60; CHECK-NEXT: entry:61; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]62; CHECK: bb1:63; CHECK-NEXT: br label [[BB3:%.*]]64; CHECK: bb2:65; CHECK-NEXT: br label [[BB3]]66; CHECK: bb3:67; CHECK-NEXT: ret i32 068;69entry:70 %v = load i32, ptr %p, align 471 br i1 %c, label %bb1, label %bb272bb1:73 br label %bb374bb2:75 store i32 %v, ptr %p, align 476 br label %bb377bb3:78 ret i32 079}80 81; Remove redundant store if loaded value is in another block.82define i32 @test27(i1 %c, ptr %p) {83; CHECK-LABEL: @test27(84; CHECK-NEXT: entry:85; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]86; CHECK: bb1:87; CHECK-NEXT: br label [[BB3:%.*]]88; CHECK: bb2:89; CHECK-NEXT: br label [[BB3]]90; CHECK: bb3:91; CHECK-NEXT: ret i32 092;93entry:94 %v = load i32, ptr %p, align 495 br i1 %c, label %bb1, label %bb296bb1:97 br label %bb398bb2:99 br label %bb3100bb3:101 store i32 %v, ptr %p, align 4102 ret i32 0103}104 105; Remove redundant store if loaded value is in another block inside a loop.106define i32 @test31(i1 %c, ptr %p, i32 %i) {107; CHECK-LABEL: @test31(108; CHECK-NEXT: entry:109; CHECK-NEXT: br label [[BB1:%.*]]110; CHECK: bb1:111; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1]], label [[BB2:%.*]]112; CHECK: bb2:113; CHECK-NEXT: ret i32 0114;115entry:116 %v = load i32, ptr %p, align 4117 br label %bb1118bb1:119 store i32 %v, ptr %p, align 4120 br i1 %c, label %bb1, label %bb2121bb2:122 ret i32 0123}124 125; Don't remove "redundant" store if %p is possibly stored to.126define i32 @test46(i1 %c, ptr %p, ptr %p2, i32 %i) {127; CHECK-LABEL: @test46(128; CHECK-NEXT: entry:129; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4130; CHECK-NEXT: br label [[BB1:%.*]]131; CHECK: bb1:132; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4133; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1]], label [[BB2:%.*]]134; CHECK: bb2:135; CHECK-NEXT: store i32 0, ptr [[P2:%.*]], align 4136; CHECK-NEXT: br i1 [[C]], label [[BB3:%.*]], label [[BB1]]137; CHECK: bb3:138; CHECK-NEXT: ret i32 0139;140entry:141 %v = load i32, ptr %p, align 4142 br label %bb1143bb1:144 store i32 %v, ptr %p, align 4145 br i1 %c, label %bb1, label %bb2146bb2:147 store i32 0, ptr %p2, align 4148 br i1 %c, label %bb3, label %bb1149bb3:150 ret i32 0151}152 153declare void @unknown_func()154 155; Remove redundant store, which is in the lame loop as the load.156define i32 @test33(i1 %c, ptr %p, i32 %i) {157; CHECK-LABEL: @test33(158; CHECK-NEXT: entry:159; CHECK-NEXT: br label [[BB1:%.*]]160; CHECK: bb1:161; CHECK-NEXT: br label [[BB2:%.*]]162; CHECK: bb2:163; CHECK-NEXT: call void @unknown_func()164; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1]], label [[BB3:%.*]]165; CHECK: bb3:166; CHECK-NEXT: ret i32 0167;168entry:169 br label %bb1170bb1:171 %v = load i32, ptr %p, align 4172 br label %bb2173bb2:174 store i32 %v, ptr %p, align 4175 ; Might read and overwrite value at %p, but doesn't matter.176 call void @unknown_func()177 br i1 %c, label %bb1, label %bb3178bb3:179 ret i32 0180}181 182declare void @unkown_write(ptr)183 184; We can't remove the "noop" store around an unkown write.185define void @test43(ptr %Q) {186; CHECK-LABEL: @test43(187; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[Q:%.*]], align 4188; CHECK-NEXT: call void @unkown_write(ptr [[Q]])189; CHECK-NEXT: store i32 [[A]], ptr [[Q]], align 4190; CHECK-NEXT: ret void191;192 %a = load i32, ptr %Q193 call void @unkown_write(ptr %Q)194 store i32 %a, ptr %Q195 ret void196}197 198; We CAN remove it when the unkown write comes AFTER.199define void @test44(ptr %Q) {200; CHECK-LABEL: @test44(201; CHECK-NEXT: call void @unkown_write(ptr [[Q:%.*]])202; CHECK-NEXT: ret void203;204 %a = load i32, ptr %Q205 store i32 %a, ptr %Q206 call void @unkown_write(ptr %Q)207 ret void208}209 210define void @test45(ptr %Q) {211; CHECK-LABEL: @test45(212; CHECK-NEXT: ret void213;214 %a = load i32, ptr %Q215 store i32 10, ptr %Q216 store i32 %a, ptr %Q217 ret void218}219 220define i32 @test48(i1 %c, ptr %p) {221; CHECK-LABEL: @test48(222; CHECK-NEXT: entry:223; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4224; CHECK-NEXT: br i1 [[C:%.*]], label [[BB0:%.*]], label [[BB0_0:%.*]]225; CHECK: bb0:226; CHECK-NEXT: store i32 0, ptr [[P]], align 4227; CHECK-NEXT: br i1 [[C]], label [[BB1:%.*]], label [[BB2:%.*]]228; CHECK: bb0.0:229; CHECK-NEXT: br label [[BB1]]230; CHECK: bb1:231; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4232; CHECK-NEXT: br i1 [[C]], label [[BB2]], label [[BB0]]233; CHECK: bb2:234; CHECK-NEXT: ret i32 0235;236entry:237 %v = load i32, ptr %p, align 4238 br i1 %c, label %bb0, label %bb0.0239 240bb0:241 store i32 0, ptr %p242 br i1 %c, label %bb1, label %bb2243 244bb0.0:245 br label %bb1246 247bb1:248 store i32 %v, ptr %p, align 4249 br i1 %c, label %bb2, label %bb0250bb2:251 ret i32 0252}253 254define i32 @test47(i1 %c, ptr %p, i32 %i) {255; CHECK-LABEL: @test47(256; CHECK-NEXT: entry:257; CHECK-NEXT: br label [[BB1:%.*]]258; CHECK: bb1:259; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1]], label [[BB2:%.*]]260; CHECK: bb2:261; CHECK-NEXT: br i1 [[C]], label [[BB3:%.*]], label [[BB1]]262; CHECK: bb3:263; CHECK-NEXT: ret i32 0264;265entry:266 %v = load i32, ptr %p, align 4267 br label %bb1268bb1:269 store i32 %v, ptr %p, align 4270 br i1 %c, label %bb1, label %bb2271bb2:272 store i32 %v, ptr %p, align 4273 br i1 %c, label %bb3, label %bb1274bb3:275 ret i32 0276}277 278; Test case from PR47887.279define void @test_noalias_store_between_load_and_store(ptr noalias %x, ptr noalias %y) {280; CHECK-LABEL: @test_noalias_store_between_load_and_store(281; CHECK-NEXT: entry:282; CHECK-NEXT: store i32 0, ptr [[Y:%.*]], align 4283; CHECK-NEXT: ret void284;285entry:286 %lv = load i32, ptr %x, align 4287 store i32 0, ptr %y, align 4288 store i32 %lv, ptr %x, align 4289 ret void290}291 292; Test case from PR47887. Currently we eliminate the dead `store i32 %inc, ptr %x`,293; but not the no-op `store i32 %lv, ptr %x`. That is because no-op stores are294; eliminated before dead stores for the same def.295define void @test_noalias_store_between_load_and_store_elimin_order(ptr noalias %x, ptr noalias %y) {296; CHECK-LABEL: @test_noalias_store_between_load_and_store_elimin_order(297; CHECK-NEXT: entry:298; CHECK-NEXT: store i32 0, ptr [[Y:%.*]], align 4299; CHECK-NEXT: ret void300;301entry:302 %lv = load i32, ptr %x, align 4303 %inc = add nsw i32 %lv, 1304 store i32 %inc, ptr %x, align 4305 store i32 0, ptr %y, align 4306 store i32 %lv, ptr %x, align 4307 ret void308}309 310declare noalias ptr @malloc(i64)311declare noalias ptr @_Znwm(i64)312declare void @clobber_memory(ptr)313 314; based on pr25892_lite315define ptr @zero_memset_after_malloc(i64 %size) {316; CHECK-LABEL: @zero_memset_after_malloc(317; CHECK-NEXT: [[CALLOC:%.*]] = call ptr @calloc(i64 1, i64 [[SIZE:%.*]])318; CHECK-NEXT: ret ptr [[CALLOC]]319;320 %call = call ptr @malloc(i64 %size) inaccessiblememonly321 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %size, i1 false)322 ret ptr %call323}324 325; based on pr25892_lite326define ptr @zero_memset_after_malloc_with_intermediate_clobbering(i64 %size) {327; CHECK-LABEL: @zero_memset_after_malloc_with_intermediate_clobbering(328; CHECK-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 [[SIZE:%.*]]) #[[ATTR7:[0-9]+]]329; CHECK-NEXT: call void @clobber_memory(ptr [[CALL]])330; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL]], i8 0, i64 [[SIZE]], i1 false)331; CHECK-NEXT: ret ptr [[CALL]]332;333 %call = call ptr @malloc(i64 %size) inaccessiblememonly334 call void @clobber_memory(ptr %call)335 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %size, i1 false)336 ret ptr %call337}338 339; based on pr25892_lite340define ptr @zero_memset_after_malloc_with_different_sizes(i64 %size) {341; CHECK-LABEL: @zero_memset_after_malloc_with_different_sizes(342; CHECK-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 [[SIZE:%.*]]) #[[ATTR7]]343; CHECK-NEXT: [[SIZE2:%.*]] = add nsw i64 [[SIZE]], -1344; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL]], i8 0, i64 [[SIZE2]], i1 false)345; CHECK-NEXT: ret ptr [[CALL]]346;347 %call = call ptr @malloc(i64 %size) inaccessiblememonly348 %size2 = add nsw i64 %size, -1349 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %size2, i1 false)350 ret ptr %call351}352 353; based on pr25892_lite354define ptr @zero_memset_after_new(i64 %size) {355; CHECK-LABEL: @zero_memset_after_new(356; CHECK-NEXT: [[CALL:%.*]] = call ptr @_Znwm(i64 [[SIZE:%.*]])357; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL]], i8 0, i64 [[SIZE]], i1 false)358; CHECK-NEXT: ret ptr [[CALL]]359;360 %call = call ptr @_Znwm(i64 %size)361 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %size, i1 false)362 ret ptr %call363}364 365; This should not create a calloc and should not crash the compiler.366define ptr @notmalloc_memset(i64 %size, ptr %notmalloc) {367; CHECK-LABEL: @notmalloc_memset(368; CHECK-NEXT: [[CALL1:%.*]] = call ptr [[NOTMALLOC:%.*]](i64 [[SIZE:%.*]])369; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL1]], i8 0, i64 [[SIZE]], i1 false)370; CHECK-NEXT: ret ptr [[CALL1]]371;372 %call1 = call ptr %notmalloc(i64 %size)373 call void @llvm.memset.p0.i64(ptr %call1, i8 0, i64 %size, i1 false)374 ret ptr %call1375}376 377; This should create a customalloc_zeroed call and eliminate the memset378define ptr @customalloc_memset(i64 %size, i64 %align) {379; CHECK-LABEL: @customalloc_memset380; CHECK-NEXT: [[CALL:%.*]] = call ptr @customalloc_zeroed(i64 [[SIZE:%.*]], i64 [[ALIGN:%.*]])381; CHECK-NEXT: ret ptr [[CALL]]382 %call = call ptr @customalloc(i64 %size, i64 %align)383 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %size, i1 false)384 ret ptr %call385}386 387declare ptr @customalloc(i64, i64) allockind("alloc") "alloc-family"="customalloc" "alloc-variant-zeroed"="customalloc_zeroed"388declare ptr @customalloc_zeroed(i64, i64) allockind("alloc,zeroed") "alloc-family"="customalloc"389 390; This should not create recursive call to calloc.391define ptr @calloc(i64 %nmemb, i64 %size) inaccessiblememonly {392; CHECK-LABEL: @calloc(393; CHECK-NEXT: entry:394; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[SIZE:%.*]], [[NMEMB:%.*]]395; CHECK-NEXT: [[CALL:%.*]] = tail call noalias align 16 ptr @malloc(i64 [[MUL]])396; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[CALL]], null397; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]398; CHECK: if.then:399; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr nonnull align 16 [[CALL]], i8 0, i64 [[MUL]], i1 false)400; CHECK-NEXT: br label [[IF_END]]401; CHECK: if.end:402; CHECK-NEXT: ret ptr [[CALL]]403;404entry:405 %mul = mul i64 %size, %nmemb406 %call = tail call noalias align 16 ptr @malloc(i64 %mul)407 %tobool.not = icmp eq ptr %call, null408 br i1 %tobool.not, label %if.end, label %if.then409 410if.then: ; preds = %entry411 tail call void @llvm.memset.p0.i64(ptr nonnull align 16 %call, i8 0, i64 %mul, i1 false)412 br label %if.end413 414if.end: ; preds = %if.then, %entry415 ret ptr %call416}417 418define ptr @pr25892(i64 %size) {419; CHECK-LABEL: @pr25892(420; CHECK-NEXT: entry:421; CHECK-NEXT: [[CALLOC:%.*]] = call ptr @calloc(i64 1, i64 [[SIZE:%.*]])422; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[CALLOC]], null423; CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[IF_END:%.*]]424; CHECK: if.end:425; CHECK-NEXT: br label [[CLEANUP]]426; CHECK: cleanup:427; CHECK-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[CALLOC]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ]428; CHECK-NEXT: ret ptr [[RETVAL_0]]429;430entry:431 %call = call ptr @malloc(i64 %size) inaccessiblememonly432 %cmp = icmp eq ptr %call, null433 br i1 %cmp, label %cleanup, label %if.end434if.end:435 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %size, i1 false)436 br label %cleanup437cleanup:438 %retval.0 = phi ptr [ %call, %if.end ], [ null, %entry ]439 ret ptr %retval.0440}441 442define ptr @pr25892_with_extra_store(i64 %size) {443; CHECK-LABEL: @pr25892_with_extra_store(444; CHECK-NEXT: entry:445; CHECK-NEXT: [[CALLOC:%.*]] = call ptr @calloc(i64 1, i64 [[SIZE:%.*]])446; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[CALLOC]], null447; CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[IF_END:%.*]]448; CHECK: if.end:449; CHECK-NEXT: br label [[CLEANUP]]450; CHECK: cleanup:451; CHECK-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[CALLOC]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ]452; CHECK-NEXT: ret ptr [[RETVAL_0]]453;454entry:455 %call = call ptr @malloc(i64 %size) inaccessiblememonly456 %cmp = icmp eq ptr %call, null457 br i1 %cmp, label %cleanup, label %if.end458if.end:459 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %size, i1 false)460 store i8 0, ptr %call, align 1461 br label %cleanup462cleanup:463 %retval.0 = phi ptr [ %call, %if.end ], [ null, %entry ]464 ret ptr %retval.0465}466 467; This should not create a calloc468define ptr @malloc_with_no_nointer_null_check(i64 %0, i32 %1) {469; CHECK-LABEL: @malloc_with_no_nointer_null_check(470; CHECK-NEXT: entry:471; CHECK-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 [[TMP0:%.*]]) #[[ATTR7]]472; CHECK-NEXT: [[A:%.*]] = and i32 [[TMP1:%.*]], 32473; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0474; CHECK-NEXT: br i1 [[CMP]], label [[CLEANUP:%.*]], label [[IF_END:%.*]]475; CHECK: if.end:476; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL]], i8 0, i64 [[TMP0]], i1 false)477; CHECK-NEXT: br label [[CLEANUP]]478; CHECK: cleanup:479; CHECK-NEXT: ret ptr [[CALL]]480;481entry:482 %call = call ptr @malloc(i64 %0) inaccessiblememonly483 %a = and i32 %1, 32484 %cmp = icmp eq i32 %a, 0485 br i1 %cmp, label %cleanup, label %if.end486if.end:487 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 %0, i1 false)488 br label %cleanup489cleanup:490 ret ptr %call491}492 493; PR50143494define ptr @store_zero_after_calloc_inaccessiblememonly() {495; CHECK-LABEL: @store_zero_after_calloc_inaccessiblememonly(496; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 1, i64 10) #[[ATTR7]]497; CHECK-NEXT: ret ptr [[CALL]]498;499 %call = tail call ptr @calloc(i64 1, i64 10) inaccessiblememonly500 store i8 0, ptr %call501 ret ptr %call502}503 504define ptr @zero_memset_after_calloc() {505; CHECK-LABEL: @zero_memset_after_calloc(506; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)507; CHECK-NEXT: ret ptr [[CALL]]508;509 %call = tail call ptr @calloc(i64 10000, i64 4)510 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 40000, i1 false)511 ret ptr %call512}513 514define ptr @volatile_zero_memset_after_calloc() {515; CHECK-LABEL: @volatile_zero_memset_after_calloc(516; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)517; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL]], i8 0, i64 40000, i1 true)518; CHECK-NEXT: ret ptr [[CALL]]519;520 %call = tail call ptr @calloc(i64 10000, i64 4)521 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 40000, i1 true)522 ret ptr %call523}524 525define ptr @zero_memset_and_store_after_calloc(i8 %v) {526; CHECK-LABEL: @zero_memset_and_store_after_calloc(527; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)528; CHECK-NEXT: ret ptr [[CALL]]529;530 %call = tail call ptr @calloc(i64 10000, i64 4)531 store i8 %v, ptr %call532 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 40000, i1 false)533 ret ptr %call534}535 536define ptr @partial_zero_memset_after_calloc() {537; CHECK-LABEL: @partial_zero_memset_after_calloc(538; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)539; CHECK-NEXT: ret ptr [[CALL]]540;541 %call = tail call ptr @calloc(i64 10000, i64 4)542 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 20, i1 false)543 ret ptr %call544}545 546define ptr @partial_zero_memset_and_store_after_calloc(i8 %v) {547; CHECK-LABEL: @partial_zero_memset_and_store_after_calloc(548; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)549; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 30550; CHECK-NEXT: store i8 [[V:%.*]], ptr [[GEP]], align 1551; CHECK-NEXT: ret ptr [[CALL]]552;553 %call = tail call ptr @calloc(i64 10000, i64 4)554 %gep = getelementptr inbounds i8, ptr %call, i64 30555 store i8 %v, ptr %gep556 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 20, i1 false)557 ret ptr %call558}559 560define ptr @zero_memset_and_store_with_dyn_index_after_calloc(i8 %v, i64 %idx) {561; CHECK-LABEL: @zero_memset_and_store_with_dyn_index_after_calloc(562; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)563; CHECK-NEXT: ret ptr [[CALL]]564;565 %call = tail call ptr @calloc(i64 10000, i64 4)566 %gep = getelementptr inbounds i8, ptr %call, i64 %idx567 store i8 %v, ptr %gep568 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 40000, i1 false)569 ret ptr %call570}571 572define ptr @partial_zero_memset_and_store_with_dyn_index_after_calloc(i8 %v, i64 %idx) {573; CHECK-LABEL: @partial_zero_memset_and_store_with_dyn_index_after_calloc(574; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)575; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 [[IDX:%.*]]576; CHECK-NEXT: store i8 [[V:%.*]], ptr [[GEP]], align 1577; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL]], i8 0, i64 20, i1 false)578; CHECK-NEXT: ret ptr [[CALL]]579;580 %call = tail call ptr @calloc(i64 10000, i64 4)581 %gep = getelementptr inbounds i8, ptr %call, i64 %idx582 store i8 %v, ptr %gep583 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 20, i1 false)584 ret ptr %call585}586 587define ptr @zero_memset_after_calloc_inaccessiblememonly() {588; CHECK-LABEL: @zero_memset_after_calloc_inaccessiblememonly(589; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4) #[[ATTR7]]590; CHECK-NEXT: ret ptr [[CALL]]591;592 %call = tail call ptr @calloc(i64 10000, i64 4) inaccessiblememonly593 call void @llvm.memset.p0.i64(ptr %call, i8 0, i64 40000, i1 false)594 ret ptr %call595}596 597define ptr @cst_nonzero_memset_after_calloc() {598; CHECK-LABEL: @cst_nonzero_memset_after_calloc(599; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)600; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL]], i8 1, i64 40000, i1 false)601; CHECK-NEXT: ret ptr [[CALL]]602;603 %call = tail call ptr @calloc(i64 10000, i64 4)604 call void @llvm.memset.p0.i64(ptr %call, i8 1, i64 40000, i1 false)605 ret ptr %call606}607 608define ptr @nonzero_memset_after_calloc(i8 %v) {609; CHECK-LABEL: @nonzero_memset_after_calloc(610; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)611; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL]], i8 [[V:%.*]], i64 40000, i1 false)612; CHECK-NEXT: ret ptr [[CALL]]613;614 %call = tail call ptr @calloc(i64 10000, i64 4)615 call void @llvm.memset.p0.i64(ptr %call, i8 %v, i64 40000, i1 false)616 ret ptr %call617}618 619; PR11896620; The first memset is dead, because calloc provides zero-filled memory.621; TODO: This could be replaced with a call to malloc + memset_pattern16.622define ptr @memset_pattern16_after_calloc(ptr %pat) {623; CHECK-LABEL: @memset_pattern16_after_calloc(624; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @calloc(i64 10000, i64 4)625; CHECK-NEXT: call void @memset_pattern16(ptr [[CALL]], ptr [[PAT:%.*]], i64 40000)626; CHECK-NEXT: ret ptr [[CALL]]627;628 %call = tail call ptr @calloc(i64 10000, i64 4) #1629 call void @llvm.memset.p0.i64(ptr align 4 %call, i8 0, i64 40000, i1 false)630 call void @memset_pattern16(ptr %call, ptr %pat, i64 40000) #1631 ret ptr %call632}633 634@n = global i32 0, align 4635@a = external global i32, align 4636@b = external global ptr, align 8637 638; GCC calloc-1.c test case should create calloc639define ptr @test_malloc_memset_to_calloc(ptr %0) {640; CHECK-LABEL: @test_malloc_memset_to_calloc(641; CHECK-NEXT: entry:642; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @n, align 4643; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64644; CHECK-NEXT: [[CALLOC:%.*]] = call ptr @calloc(i64 1, i64 [[TMP2]])645; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP0:%.*]], align 8646; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[TMP3]], 1647; CHECK-NEXT: store i64 [[TMP4]], ptr [[TMP0]], align 8648; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[CALLOC]], null649; CHECK-NEXT: br i1 [[TMP5]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]650; CHECK: if.then:651; CHECK-NEXT: [[TMP6:%.*]] = add nsw i64 [[TMP3]], 2652; CHECK-NEXT: store i64 [[TMP6]], ptr [[TMP0]], align 8653; CHECK-NEXT: store i32 2, ptr @a, align 4654; CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr @b, align 8655; CHECK-NEXT: store i32 3, ptr [[TMP7]], align 4656; CHECK-NEXT: br label [[IF_END]]657; CHECK: if.end:658; CHECK-NEXT: ret ptr [[CALLOC]]659;660entry:661 %1 = load i32, ptr @n, align 4662 %2 = sext i32 %1 to i64663 %3 = tail call ptr @malloc(i64 %2) inaccessiblememonly664 %4 = load i64, ptr %0, align 8665 %5 = add nsw i64 %4, 1666 store i64 %5, ptr %0, align 8667 %6 = icmp eq ptr %3, null668 br i1 %6, label %if.end, label %if.then669 670if.then:671 %7 = add nsw i64 %4, 2672 store i64 %7, ptr %0, align 8673 store i32 2, ptr @a, align 4674 tail call void @llvm.memset.p0.i64(ptr align 4 %3, i8 0, i64 %2, i1 false)675 %8 = load ptr, ptr @b, align 8676 store i32 3, ptr %8, align 4677 br label %if.end678 679if.end:680 ret ptr %3681}682 683define ptr @readnone_malloc() {684; CHECK-LABEL: @readnone_malloc(685; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16) #[[ATTR8:[0-9]+]]686; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[ALLOC]], i8 0, i64 16, i1 false)687; CHECK-NEXT: ret ptr [[ALLOC]]688;689 %alloc = call ptr @malloc(i64 16) memory(none)690 call void @llvm.memset.p0.i64(ptr %alloc, i8 0, i64 16, i1 false)691 ret ptr %alloc692}693 694define void @store_same_i32_to_mayalias_loc(ptr %q, ptr %p) {695; CHECK-LABEL: @store_same_i32_to_mayalias_loc(696; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 4697; CHECK-NEXT: store i32 [[V]], ptr [[Q:%.*]], align 4698; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4699; CHECK-NEXT: ret void700;701 %v = load i32, ptr %p, align 4702 store i32 %v, ptr %q, align 4703 store i32 %v, ptr %p, align 4704 ret void705}706 707define void @store_same_i32_to_mayalias_loc_unalign(ptr %q, ptr %p) {708; CHECK-LABEL: @store_same_i32_to_mayalias_loc_unalign(709; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 1710; CHECK-NEXT: store i32 [[V]], ptr [[Q:%.*]], align 1711; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 1712; CHECK-NEXT: ret void713;714 %v = load i32, ptr %p, align 1715 store i32 %v, ptr %q, align 1716 store i32 %v, ptr %p, align 1717 ret void718}719 720define void @store_same_i12_to_mayalias_loc(ptr %q, ptr %p) {721; CHECK-LABEL: @store_same_i12_to_mayalias_loc(722; CHECK-NEXT: [[V:%.*]] = load i12, ptr [[P:%.*]], align 2723; CHECK-NEXT: store i12 [[V]], ptr [[Q:%.*]], align 2724; CHECK-NEXT: store i12 [[V]], ptr [[P]], align 2725; CHECK-NEXT: ret void726;727 %v = load i12, ptr %p, align 2728 store i12 %v, ptr %q, align 2729 store i12 %v, ptr %p, align 2730 ret void731}732 733define void @store_same_i12_to_mayalias_loc_unalign(ptr %q, ptr %p) {734; CHECK-LABEL: @store_same_i12_to_mayalias_loc_unalign(735; CHECK-NEXT: [[V:%.*]] = load i12, ptr [[P:%.*]], align 1736; CHECK-NEXT: store i12 [[V]], ptr [[Q:%.*]], align 1737; CHECK-NEXT: store i12 [[V]], ptr [[P]], align 1738; CHECK-NEXT: ret void739;740 %v = load i12, ptr %p, align 1741 store i12 %v, ptr %q, align 1742 store i12 %v, ptr %p, align 1743 ret void744}745 746define void @store_same_ptr_to_mayalias_loc(ptr %q, ptr %p) {747; CHECK-LABEL: @store_same_ptr_to_mayalias_loc(748; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8749; CHECK-NEXT: store ptr [[V]], ptr [[Q:%.*]], align 8750; CHECK-NEXT: store ptr [[V]], ptr [[P]], align 8751; CHECK-NEXT: ret void752;753 %v = load ptr, ptr %p, align 8754 store ptr %v, ptr %q, align 8755 store ptr %v, ptr %p, align 8756 ret void757}758 759define void @store_same_scalable_to_mayalias_loc(ptr %q, ptr %p) {760; CHECK-LABEL: @store_same_scalable_to_mayalias_loc(761; CHECK-NEXT: [[V:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 4762; CHECK-NEXT: store <vscale x 4 x i32> [[V]], ptr [[Q:%.*]], align 4763; CHECK-NEXT: store <vscale x 4 x i32> [[V]], ptr [[P]], align 4764; CHECK-NEXT: ret void765;766 %v = load <vscale x 4 x i32>, ptr %p, align 4767 store <vscale x 4 x i32> %v, ptr %q, align 4768 store <vscale x 4 x i32> %v, ptr %p, align 4769 ret void770}771 772define void @store_same_i32_to_mayalias_loc_inconsistent_align(ptr %q, ptr %p) {773; CHECK-LABEL: @store_same_i32_to_mayalias_loc_inconsistent_align(774; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 2775; CHECK-NEXT: store i32 [[V]], ptr [[Q:%.*]], align 4776; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4777; CHECK-NEXT: ret void778;779 %v = load i32, ptr %p, align 2780 store i32 %v, ptr %q, align 4781 store i32 %v, ptr %p, align 4782 ret void783}784 785define void @do_not_crash_on_liveonentrydef(i1 %c, ptr %p, ptr noalias %q) {786; CHECK-LABEL: @do_not_crash_on_liveonentrydef(787; CHECK-NEXT: entry:788; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]789; CHECK: if:790; CHECK-NEXT: store i8 0, ptr [[Q:%.*]], align 1791; CHECK-NEXT: br label [[JOIN]]792; CHECK: join:793; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[Q]], align 1794; CHECK-NEXT: store i8 0, ptr [[P:%.*]], align 1795; CHECK-NEXT: store i8 [[V]], ptr [[Q]], align 1796; CHECK-NEXT: ret void797;798entry:799 br i1 %c, label %if, label %join800 801if:802 store i8 0, ptr %q, align 1803 br label %join804 805join:806 %v = load i8, ptr %q, align 1807 store i8 0, ptr %p, align 1808 store i8 %v, ptr %q, align 1809 ret void810}811 812; Dominating condition implies value already exists, optimize store813define void @remove_tautological_store_eq(ptr %x) {814; CHECK-LABEL: @remove_tautological_store_eq(815; CHECK-NEXT: entry:816; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 4817; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 4818; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[END:%.*]]819; CHECK: if.eq:820; CHECK-NEXT: br label [[END]]821; CHECK: end:822; CHECK-NEXT: ret void823;824entry:825 %val = load i32, ptr %x, align 4826 %cmp = icmp eq i32 %val, 4827 br i1 %cmp, label %if.eq, label %end828 829if.eq:830 store i32 4, ptr %x, align 4831 br label %end832 833end:834 ret void835}836 837; Dominating condition implies value already exists, optimize store838define void @remove_tautological_store_var(ptr %x, ptr %y) {839; CHECK-LABEL: @remove_tautological_store_var(840; CHECK-NEXT: entry:841; CHECK-NEXT: [[VALX:%.*]] = load i32, ptr [[X:%.*]], align 4842; CHECK-NEXT: [[VALY:%.*]] = load i32, ptr [[Y:%.*]], align 4843; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VALX]], [[VALY]]844; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[END:%.*]]845; CHECK: if.eq:846; CHECK-NEXT: br label [[END]]847; CHECK: end:848; CHECK-NEXT: ret void849;850entry:851 %valx = load i32, ptr %x, align 4852 %valy = load i32, ptr %y, align 4853 %cmp = icmp eq i32 %valx, %valy854 br i1 %cmp, label %if.eq, label %end855 856if.eq:857 store i32 %valy, ptr %x, align 4858 br label %end859 860end:861 ret void862}863 864; Dominating condition implies value already exists, optimize store865define void @remove_tautological_store_ne(ptr %x) {866; CHECK-LABEL: @remove_tautological_store_ne(867; CHECK-NEXT: entry:868; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 4869; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[VAL]], 4870; CHECK-NEXT: br i1 [[CMP]], label [[IF_NE:%.*]], label [[IF_ELSE:%.*]]871; CHECK: if.ne:872; CHECK-NEXT: br label [[END:%.*]]873; CHECK: if.else:874; CHECK-NEXT: br label [[END]]875; CHECK: end:876; CHECK-NEXT: ret void877;878entry:879 %val = load i32, ptr %x, align 4880 %cmp = icmp ne i32 %val, 4881 br i1 %cmp, label %if.ne, label %if.else882 883if.ne:884 br label %end885 886if.else:887 store i32 4, ptr %x, align 4888 br label %end889 890end:891 ret void892}893 894; Dominating condition implies value already exists, optimize store895; Optimizes unordered atomic stores896define void @remove_tautological_store_atomic_unordered(ptr %x) {897; CHECK-LABEL: @remove_tautological_store_atomic_unordered(898; CHECK-NEXT: entry:899; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 4900; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 4901; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[END:%.*]]902; CHECK: if.eq:903; CHECK-NEXT: br label [[END]]904; CHECK: end:905; CHECK-NEXT: ret void906;907entry:908 %val = load i32, ptr %x, align 4909 %cmp = icmp eq i32 %val, 4910 br i1 %cmp, label %if.eq, label %end911 912if.eq:913 store atomic i32 4, ptr %x unordered, align 4914 br label %end915 916end:917 ret void918}919 920; Should not optimize ordered atomic stores921define void @remove_tautological_store_atomic_monotonic(ptr %x) {922; CHECK-LABEL: @remove_tautological_store_atomic_monotonic(923; CHECK-NEXT: entry:924; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 4925; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 4926; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[END:%.*]]927; CHECK: if.eq:928; CHECK-NEXT: store atomic i32 4, ptr [[X]] monotonic, align 4929; CHECK-NEXT: br label [[END]]930; CHECK: end:931; CHECK-NEXT: ret void932;933entry:934 %val = load i32, ptr %x, align 4935 %cmp = icmp eq i32 %val, 4936 br i1 %cmp, label %if.eq, label %end937 938if.eq:939 store atomic i32 4, ptr %x monotonic, align 4940 br label %end941 942end:943 ret void944}945 946; Should not optimize since the store is in incorrect branch947define void @remove_tautological_store_eq_wrong_branch(ptr %x, ptr %y) {948; CHECK-LABEL: @remove_tautological_store_eq_wrong_branch(949; CHECK-NEXT: entry:950; CHECK-NEXT: [[VALX:%.*]] = load i32, ptr [[X:%.*]], align 4951; CHECK-NEXT: [[VALY:%.*]] = load i32, ptr [[Y:%.*]], align 4952; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VALX]], [[VALY]]953; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[END:%.*]]954; CHECK: if.eq:955; CHECK-NEXT: br label [[END]]956; CHECK: end:957; CHECK-NEXT: store i32 [[VALY]], ptr [[X]], align 4958; CHECK-NEXT: ret void959;960entry:961 %valx = load i32, ptr %x, align 4962 %valy = load i32, ptr %y, align 4963 %cmp = icmp eq i32 %valx, %valy964 br i1 %cmp, label %if.eq, label %end965 966if.eq:967 br label %end968 969end:970 store i32 %valy, ptr %x, align 4971 ret void972}973 974; Should not optimize since the store is in incorrect branch975define void @remove_tautological_store_ne_wrong_branch(ptr %x) {976; CHECK-LABEL: @remove_tautological_store_ne_wrong_branch(977; CHECK-NEXT: entry:978; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 4979; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[VAL]], 4980; CHECK-NEXT: br i1 [[CMP]], label [[IF_NE:%.*]], label [[END:%.*]]981; CHECK: if.ne:982; CHECK-NEXT: store i32 4, ptr [[X]], align 4983; CHECK-NEXT: br label [[END]]984; CHECK: end:985; CHECK-NEXT: ret void986;987entry:988 %val = load i32, ptr %x, align 4989 %cmp = icmp ne i32 %val, 4990 br i1 %cmp, label %if.ne, label %end991 992if.ne:993 store i32 4, ptr %x, align 4994 br label %end995 996end:997 ret void998}999 1000; Dominating condition implies value already exists, optimize store1001; Should not optimize since we cannot determine if we should when both1002; branches are the same1003define void @remove_tautological_store_same_branch(ptr %x) {1004; CHECK-LABEL: @remove_tautological_store_same_branch(1005; CHECK-NEXT: entry:1006; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 41007; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 41008; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[IF_EQ]]1009; CHECK: if.eq:1010; CHECK-NEXT: store i32 4, ptr [[X]], align 41011; CHECK-NEXT: ret void1012;1013entry:1014 %val = load i32, ptr %x, align 41015 %cmp = icmp eq i32 %val, 41016 br i1 %cmp, label %if.eq, label %if.eq1017 1018if.eq:1019 store i32 4, ptr %x, align 41020 ret void1021}1022 1023; Dominating condition implies value already exists, optimize store1024; Should not optimize since value being stored is different from cond check1025define void @remove_tautological_store_wrong_value(ptr %x) {1026; CHECK-LABEL: @remove_tautological_store_wrong_value(1027; CHECK-NEXT: entry:1028; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 41029; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 41030; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[END:%.*]]1031; CHECK: if.eq:1032; CHECK-NEXT: store i32 5, ptr [[X]], align 41033; CHECK-NEXT: br label [[END]]1034; CHECK: end:1035; CHECK-NEXT: ret void1036;1037entry:1038 %val = load i32, ptr %x, align 41039 %cmp = icmp eq i32 %val, 41040 br i1 %cmp, label %if.eq, label %end1041 1042if.eq:1043 store i32 5, ptr %x, align 41044 br label %end1045 1046end:1047 ret void1048}1049 1050; Should not optimize since there is a clobbering acc after load1051define void @remove_tautological_store_clobber(ptr %x) {1052; CHECK-LABEL: @remove_tautological_store_clobber(1053; CHECK-NEXT: entry:1054; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 41055; CHECK-NEXT: store i32 5, ptr [[X]], align 41056; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 41057; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[END:%.*]]1058; CHECK: if.eq:1059; CHECK-NEXT: store i32 4, ptr [[X]], align 41060; CHECK-NEXT: br label [[END]]1061; CHECK: end:1062; CHECK-NEXT: ret void1063;1064entry:1065 %val = load i32, ptr %x, align 41066 store i32 5, ptr %x, align 41067 %cmp = icmp eq i32 %val, 41068 br i1 %cmp, label %if.eq, label %end1069 1070if.eq:1071 store i32 4, ptr %x, align 41072 br label %end1073 1074end:1075 ret void1076}1077 1078; Should not optimize since the condition does not dominate the store1079define void @remove_tautological_store_no_dom(ptr %x) {1080; CHECK-LABEL: @remove_tautological_store_no_dom(1081; CHECK-NEXT: entry:1082; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 41083; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 41084; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[IF_ELSE:%.*]]1085; CHECK: if.eq:1086; CHECK-NEXT: br label [[END:%.*]]1087; CHECK: if.else:1088; CHECK-NEXT: br label [[END]]1089; CHECK: end:1090; CHECK-NEXT: store i32 4, ptr [[X]], align 41091; CHECK-NEXT: ret void1092;1093entry:1094 %val = load i32, ptr %x, align 41095 store i32 5, ptr %x, align 41096 %cmp = icmp eq i32 %val, 41097 br i1 %cmp, label %if.eq, label %if.else1098 1099if.eq:1100 br label %end1101 1102if.else:1103 br label %end1104 1105end:1106 store i32 4, ptr %x, align 41107 ret void1108}1109 1110; Should not optimize volatile stores1111define void @remove_tautological_store_volatile(ptr %x) {1112; CHECK-LABEL: @remove_tautological_store_volatile(1113; CHECK-NEXT: entry:1114; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[X:%.*]], align 41115; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL]], 41116; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[END:%.*]]1117; CHECK: if.eq:1118; CHECK-NEXT: store volatile i32 4, ptr [[X]], align 41119; CHECK-NEXT: br label [[END]]1120; CHECK: end:1121; CHECK-NEXT: ret void1122;1123entry:1124 %val = load i32, ptr %x, align 41125 %cmp = icmp eq i32 %val, 41126 br i1 %cmp, label %if.eq, label %end1127 1128if.eq:1129 store volatile i32 4, ptr %x, align 41130 br label %end1131 1132end:1133 ret void1134}1135 1136; Should not optimize stores where the edge from branch inst to1137; conditional block does not dominate the conditional block.1138; (A conditional block post dominates the branch inst.)1139define void @remove_tautological_store_no_edge_domination(ptr %x) {1140; CHECK-LABEL: @remove_tautological_store_no_edge_domination(1141; CHECK-NEXT: entry:1142; CHECK-NEXT: [[X1:%.*]] = load ptr, ptr [[X:%.*]], align 81143; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[X1]], null1144; CHECK-NEXT: br i1 [[CMP]], label [[IF_EQ:%.*]], label [[IF_ELSE:%.*]]1145; CHECK: if.eq:1146; CHECK-NEXT: store ptr null, ptr [[X]], align 81147; CHECK-NEXT: br label [[END:%.*]]1148; CHECK: if.else:1149; CHECK-NEXT: br label [[IF_EQ]]1150; CHECK: end:1151; CHECK-NEXT: ret void1152;1153entry:1154 %x1 = load ptr, ptr %x, align 81155 %cmp = icmp eq ptr %x1, null1156 br i1 %cmp, label %if.eq, label %if.else1157 1158if.eq:1159 store ptr null, ptr %x, align 81160 br label %end1161 1162if.else:1163 br label %if.eq1164 1165end:1166 ret void1167}1168