diff options
author | Nikita Popov <npopov@redhat.com> | 2022-04-07 16:21:23 +0200 |
---|---|---|
committer | Nikita Popov <npopov@redhat.com> | 2022-04-07 16:35:05 +0200 |
commit | 7d452742632dc0d14e45bac72a2874c75d64e15e (patch) | |
tree | 25f6dc4eb06404c2d9959170db1b1d772a66c4cd | |
parent | afa1ae9e0c0bb7bacca65ebd43ecb21d3848bbe4 (diff) | |
download | llvm-7d452742632dc0d14e45bac72a2874c75d64e15e.zip llvm-7d452742632dc0d14e45bac72a2874c75d64e15e.tar.gz llvm-7d452742632dc0d14e45bac72a2874c75d64e15e.tar.bz2 |
[Sink] Add willreturn test
Explicitly test the nounwind/willreturn combinations.
-rw-r--r-- | llvm/test/Transforms/Sink/call.ll | 124 |
1 files changed, 91 insertions, 33 deletions
diff --git a/llvm/test/Transforms/Sink/call.ll b/llvm/test/Transforms/Sink/call.ll index 1e80aee..2da58eb 100644 --- a/llvm/test/Transforms/Sink/call.ll +++ b/llvm/test/Transforms/Sink/call.ll @@ -1,7 +1,9 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -basic-aa -sink -S | FileCheck %s -declare i32 @f_load_global() nounwind readonly -declare i32 @f_load_global_throwable() readonly +declare i32 @f_load_global() nounwind willreturn readonly +declare i32 @f_load_global_throwable() willreturn readonly +declare i32 @f_load_global_may_not_return() nounwind readonly declare i32 @f_load_arg(i32*) nounwind readonly argmemonly declare void @f_store_global(i32) nounwind declare void @f_store_arg(i32*) nounwind argmemonly @@ -13,11 +15,15 @@ declare i32 @f_readnone(i32) nounwind readnone ; Sink readonly call if no stores are in the way. ; -; CHECK-LABEL: @test_sink_no_stores( -; CHECK: true: -; CHECK-NEXT: %l = call i32 @f_load_global -; CHECK-NEXT: ret i32 %l define i32 @test_sink_no_stores(i1 %z) { +; CHECK-LABEL: @test_sink_no_stores( +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global() +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; %l = call i32 @f_load_global() br i1 %z, label %true, label %false true: @@ -26,10 +32,15 @@ false: ret i32 0 } -; CHECK-LABEL: @test_throwable_no_stores( -; CHECK: %l = call i32 @f_load_global -; CHECK-NEXT: br i1 %z define i32 @test_throwable_no_stores(i1 %z) { +; CHECK-LABEL: @test_throwable_no_stores( +; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global_throwable() +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; %l = call i32 @f_load_global_throwable() br i1 %z, label %true, label %false true: @@ -38,11 +49,33 @@ false: ret i32 0 } -; CHECK-LABEL: @test_sink_argmem_store( -; CHECK: true: -; CHECK-NEXT: %l = call i32 @f_load_arg -; CHECK-NEXT: ret i32 %l +define i32 @test_may_not_return_no_stores(i1 %z) { +; CHECK-LABEL: @test_may_not_return_no_stores( +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global_may_not_return() +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; + %l = call i32 @f_load_global_may_not_return() + br i1 %z, label %true, label %false +true: + ret i32 %l +false: + ret i32 0 +} + define i32 @test_sink_argmem_store(i1 %z) { +; CHECK-LABEL: @test_sink_argmem_store( +; CHECK-NEXT: store i32 0, i32* @B, align 4 +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(i32* @A) +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; %l = call i32 @f_load_arg(i32* @A) store i32 0, i32* @B br i1 %z, label %true, label %false @@ -52,11 +85,16 @@ false: ret i32 0 } -; CHECK-LABEL: @test_sink_argmem_call( -; CHECK: true: -; CHECK-NEXT: %l = call i32 @f_load_arg -; CHECK-NEXT: ret i32 %l define i32 @test_sink_argmem_call(i1 %z) { +; CHECK-LABEL: @test_sink_argmem_call( +; CHECK-NEXT: call void @f_store_arg(i32* @B) +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(i32* @A) +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; %l = call i32 @f_load_arg(i32* @A) call void @f_store_arg(i32* @B) br i1 %z, label %true, label %false @@ -66,11 +104,16 @@ false: ret i32 0 } -; CHECK-LABEL: @test_sink_argmem_multiple( -; CHECK: true: -; CHECK-NEXT: %l = call i32 @f_load_arg -; CHECK-NEXT: ret i32 %l define i32 @test_sink_argmem_multiple(i1 %z) { +; CHECK-LABEL: @test_sink_argmem_multiple( +; CHECK-NEXT: call void @f_readonly_arg(i32* @A, i32* @B) +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(i32* @A) +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; %l = call i32 @f_load_arg(i32* @A) call void @f_readonly_arg(i32* @A, i32* @B) br i1 %z, label %true, label %false @@ -81,11 +124,16 @@ false: } ; But don't sink if there is a store. -; -; CHECK-LABEL: @test_nosink_store( -; CHECK: call i32 @f_load_global -; CHECK-NEXT: store i32 define i32 @test_nosink_store(i1 %z) { +; CHECK-LABEL: @test_nosink_store( +; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global() +; CHECK-NEXT: store i32 0, i32* @A, align 4 +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; %l = call i32 @f_load_global() store i32 0, i32* @A br i1 %z, label %true, label %false @@ -95,10 +143,16 @@ false: ret i32 0 } -; CHECK-LABEL: @test_nosink_call( -; CHECK: call i32 @f_load_global -; CHECK-NEXT: call void @f_store_global define i32 @test_nosink_call(i1 %z) { +; CHECK-LABEL: @test_nosink_call( +; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global() +; CHECK-NEXT: call void @f_store_global(i32 0) +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; %l = call i32 @f_load_global() call void @f_store_global(i32 0) br i1 %z, label %true, label %false @@ -109,12 +163,16 @@ false: } ; readnone calls are sunk across stores. -; -; CHECK-LABEL: @test_sink_readnone( -; CHECK: true: -; CHECK-NEXT: %l = call i32 @f_readnone( -; CHECK-NEXT: ret i32 %l define i32 @test_sink_readnone(i1 %z) { +; CHECK-LABEL: @test_sink_readnone( +; CHECK-NEXT: store i32 0, i32* @A, align 4 +; CHECK-NEXT: br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[L:%.*]] = call i32 @f_readnone(i32 0) +; CHECK-NEXT: ret i32 [[L]] +; CHECK: false: +; CHECK-NEXT: ret i32 0 +; %l = call i32 @f_readnone(i32 0) store i32 0, i32* @A br i1 %z, label %true, label %false |