1 ; RUN: opt < %s -basicaa -sink -S | FileCheck %s 2 3 declare i32 @f_load_global() nounwind readonly 4 declare i32 @f_load_arg(i32*) nounwind readonly argmemonly 5 declare void @f_store_global(i32) nounwind 6 declare void @f_store_arg(i32*) nounwind argmemonly 7 declare void @f_readonly_arg(i32* readonly, i32*) nounwind argmemonly 8 declare i32 @f_readnone(i32) nounwind readnone 9 10 @A = external global i32 11 @B = external global i32 12 13 ; Sink readonly call if no stores are in the way. 14 ; 15 ; CHECK-LABEL: @test_sink_no_stores( 16 ; CHECK: true: 17 ; CHECK-NEXT: %l = call i32 @f_load_global 18 ; CHECK-NEXT: ret i32 %l 19 define i32 @test_sink_no_stores(i1 %z) { 20 %l = call i32 @f_load_global() 21 br i1 %z, label %true, label %false 22 true: 23 ret i32 %l 24 false: 25 ret i32 0 26 } 27 28 ; CHECK-LABEL: @test_sink_argmem_store( 29 ; CHECK: true: 30 ; CHECK-NEXT: %l = call i32 @f_load_arg 31 ; CHECK-NEXT: ret i32 %l 32 define i32 @test_sink_argmem_store(i1 %z) { 33 %l = call i32 @f_load_arg(i32* @A) 34 store i32 0, i32* @B 35 br i1 %z, label %true, label %false 36 true: 37 ret i32 %l 38 false: 39 ret i32 0 40 } 41 42 ; CHECK-LABEL: @test_sink_argmem_call( 43 ; CHECK: true: 44 ; CHECK-NEXT: %l = call i32 @f_load_arg 45 ; CHECK-NEXT: ret i32 %l 46 define i32 @test_sink_argmem_call(i1 %z) { 47 %l = call i32 @f_load_arg(i32* @A) 48 call void @f_store_arg(i32* @B) 49 br i1 %z, label %true, label %false 50 true: 51 ret i32 %l 52 false: 53 ret i32 0 54 } 55 56 ; CHECK-LABEL: @test_sink_argmem_multiple( 57 ; CHECK: true: 58 ; CHECK-NEXT: %l = call i32 @f_load_arg 59 ; CHECK-NEXT: ret i32 %l 60 define i32 @test_sink_argmem_multiple(i1 %z) { 61 %l = call i32 @f_load_arg(i32* @A) 62 call void @f_readonly_arg(i32* @A, i32* @B) 63 br i1 %z, label %true, label %false 64 true: 65 ret i32 %l 66 false: 67 ret i32 0 68 } 69 70 ; But don't sink if there is a store. 71 ; 72 ; CHECK-LABEL: @test_nosink_store( 73 ; CHECK: call i32 @f_load_global 74 ; CHECK-NEXT: store i32 75 define i32 @test_nosink_store(i1 %z) { 76 %l = call i32 @f_load_global() 77 store i32 0, i32* @A 78 br i1 %z, label %true, label %false 79 true: 80 ret i32 %l 81 false: 82 ret i32 0 83 } 84 85 ; CHECK-LABEL: @test_nosink_call( 86 ; CHECK: call i32 @f_load_global 87 ; CHECK-NEXT: call void @f_store_global 88 define i32 @test_nosink_call(i1 %z) { 89 %l = call i32 @f_load_global() 90 call void @f_store_global(i32 0) 91 br i1 %z, label %true, label %false 92 true: 93 ret i32 %l 94 false: 95 ret i32 0 96 } 97 98 ; readnone calls are sunk across stores. 99 ; 100 ; CHECK-LABEL: @test_sink_readnone( 101 ; CHECK: true: 102 ; CHECK-NEXT: %l = call i32 @f_readnone( 103 ; CHECK-NEXT: ret i32 %l 104 define i32 @test_sink_readnone(i1 %z) { 105 %l = call i32 @f_readnone(i32 0) 106 store i32 0, i32* @A 107 br i1 %z, label %true, label %false 108 true: 109 ret i32 %l 110 false: 111 ret i32 0 112 } 113