brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.7 KiB · 59a1cc1 Raw
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