184 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=sink -S | FileCheck %s3 4declare i32 @f_load_global() nounwind willreturn readonly5declare i32 @f_load_global_throwable() willreturn readonly6declare i32 @f_load_global_may_not_return() nounwind readonly7declare i32 @f_load_arg(ptr) nounwind willreturn readonly argmemonly8declare void @f_store_global(i32) nounwind willreturn9declare void @f_store_arg(ptr) nounwind willreturn argmemonly10declare void @f_readonly_arg(ptr readonly, ptr) nounwind willreturn argmemonly11declare i32 @f_readnone(i32) nounwind willreturn readnone12 13@A = external global i3214@B = external global i3215 16; Sink readonly call if no stores are in the way.17;18define i32 @test_sink_no_stores(i1 %z) {19; CHECK-LABEL: @test_sink_no_stores(20; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]21; CHECK: true:22; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global()23; CHECK-NEXT: ret i32 [[L]]24; CHECK: false:25; CHECK-NEXT: ret i32 026;27 %l = call i32 @f_load_global()28 br i1 %z, label %true, label %false29true:30 ret i32 %l31false:32 ret i32 033}34 35define i32 @test_throwable_no_stores(i1 %z) {36; CHECK-LABEL: @test_throwable_no_stores(37; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global_throwable()38; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]39; CHECK: true:40; CHECK-NEXT: ret i32 [[L]]41; CHECK: false:42; CHECK-NEXT: ret i32 043;44 %l = call i32 @f_load_global_throwable()45 br i1 %z, label %true, label %false46true:47 ret i32 %l48false:49 ret i32 050}51 52define i32 @test_may_not_return_no_stores(i1 %z) {53; CHECK-LABEL: @test_may_not_return_no_stores(54; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global_may_not_return()55; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]56; CHECK: true:57; CHECK-NEXT: ret i32 [[L]]58; CHECK: false:59; CHECK-NEXT: ret i32 060;61 %l = call i32 @f_load_global_may_not_return()62 br i1 %z, label %true, label %false63true:64 ret i32 %l65false:66 ret i32 067}68 69define i32 @test_sink_argmem_store(i1 %z) {70; CHECK-LABEL: @test_sink_argmem_store(71; CHECK-NEXT: store i32 0, ptr @B, align 472; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]73; CHECK: true:74; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(ptr @A)75; CHECK-NEXT: ret i32 [[L]]76; CHECK: false:77; CHECK-NEXT: ret i32 078;79 %l = call i32 @f_load_arg(ptr @A)80 store i32 0, ptr @B81 br i1 %z, label %true, label %false82true:83 ret i32 %l84false:85 ret i32 086}87 88define i32 @test_sink_argmem_call(i1 %z) {89; CHECK-LABEL: @test_sink_argmem_call(90; CHECK-NEXT: call void @f_store_arg(ptr @B)91; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]92; CHECK: true:93; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(ptr @A)94; CHECK-NEXT: ret i32 [[L]]95; CHECK: false:96; CHECK-NEXT: ret i32 097;98 %l = call i32 @f_load_arg(ptr @A)99 call void @f_store_arg(ptr @B)100 br i1 %z, label %true, label %false101true:102 ret i32 %l103false:104 ret i32 0105}106 107define i32 @test_sink_argmem_multiple(i1 %z) {108; CHECK-LABEL: @test_sink_argmem_multiple(109; CHECK-NEXT: call void @f_readonly_arg(ptr @A, ptr @B)110; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]111; CHECK: true:112; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(ptr @A)113; CHECK-NEXT: ret i32 [[L]]114; CHECK: false:115; CHECK-NEXT: ret i32 0116;117 %l = call i32 @f_load_arg(ptr @A)118 call void @f_readonly_arg(ptr @A, ptr @B)119 br i1 %z, label %true, label %false120true:121 ret i32 %l122false:123 ret i32 0124}125 126; But don't sink if there is a store.127define i32 @test_nosink_store(i1 %z) {128; CHECK-LABEL: @test_nosink_store(129; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global()130; CHECK-NEXT: store i32 0, ptr @A, align 4131; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]132; CHECK: true:133; CHECK-NEXT: ret i32 [[L]]134; CHECK: false:135; CHECK-NEXT: ret i32 0136;137 %l = call i32 @f_load_global()138 store i32 0, ptr @A139 br i1 %z, label %true, label %false140true:141 ret i32 %l142false:143 ret i32 0144}145 146define i32 @test_nosink_call(i1 %z) {147; CHECK-LABEL: @test_nosink_call(148; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global()149; CHECK-NEXT: call void @f_store_global(i32 0)150; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]151; CHECK: true:152; CHECK-NEXT: ret i32 [[L]]153; CHECK: false:154; CHECK-NEXT: ret i32 0155;156 %l = call i32 @f_load_global()157 call void @f_store_global(i32 0)158 br i1 %z, label %true, label %false159true:160 ret i32 %l161false:162 ret i32 0163}164 165; readnone calls are sunk across stores.166define i32 @test_sink_readnone(i1 %z) {167; CHECK-LABEL: @test_sink_readnone(168; CHECK-NEXT: store i32 0, ptr @A, align 4169; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]170; CHECK: true:171; CHECK-NEXT: [[L:%.*]] = call i32 @f_readnone(i32 0)172; CHECK-NEXT: ret i32 [[L]]173; CHECK: false:174; CHECK-NEXT: ret i32 0175;176 %l = call i32 @f_readnone(i32 0)177 store i32 0, ptr @A178 br i1 %z, label %true, label %false179true:180 ret i32 %l181false:182 ret i32 0183}184