1; RUN: opt < %s -basicaa -sink -S | FileCheck %s 2 3declare i32 @f_load_global() nounwind readonly 4declare i32 @f_load_arg(i32*) nounwind readonly argmemonly 5declare void @f_store_global(i32) nounwind 6declare void @f_store_arg(i32*) nounwind argmemonly 7declare void @f_readonly_arg(i32* readonly, i32*) nounwind argmemonly 8declare 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 19define i32 @test_sink_no_stores(i1 %z) { 20 %l = call i32 @f_load_global() 21 br i1 %z, label %true, label %false 22true: 23 ret i32 %l 24false: 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 32define 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 36true: 37 ret i32 %l 38false: 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 46define 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 50true: 51 ret i32 %l 52false: 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 60define 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 64true: 65 ret i32 %l 66false: 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 75define 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 79true: 80 ret i32 %l 81false: 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 88define 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 92true: 93 ret i32 %l 94false: 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 104define 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 108true: 109 ret i32 %l 110false: 111 ret i32 0 112} 113