diff options
| author | Max Kazantsev <max.kazantsev@azul.com> | 2017-11-28 07:07:55 +0000 |
|---|---|---|
| committer | Max Kazantsev <max.kazantsev@azul.com> | 2017-11-28 07:07:55 +0000 |
| commit | 115607226a12f6dbaa2b9e32a36089a9685daa7e (patch) | |
| tree | 3846ff78cbc20a0d337dd3d4bc00935865f69074 /llvm/test/Transforms | |
| parent | bf74f64e6718b73f48da255c7331d6d5ab3c601e (diff) | |
| download | bcm5719-llvm-115607226a12f6dbaa2b9e32a36089a9685daa7e.tar.gz bcm5719-llvm-115607226a12f6dbaa2b9e32a36089a9685daa7e.zip | |
[GVN] Prevent ScalarPRE from hoisting across instructions that don't pass control flow to successors
This is to address a problem similar to those in D37460 for Scalar PRE. We should not
PRE across an instruction that may not pass execution to its successor unless it is safe
to speculatively execute it.
Differential Revision: https://reviews.llvm.org/D38619
llvm-svn: 319147
Diffstat (limited to 'llvm/test/Transforms')
| -rw-r--r-- | llvm/test/Transforms/GVN/PRE/local-pre.ll | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/llvm/test/Transforms/GVN/PRE/local-pre.ll b/llvm/test/Transforms/GVN/PRE/local-pre.ll index 943f351f17a..22d9b506644 100644 --- a/llvm/test/Transforms/GVN/PRE/local-pre.ll +++ b/llvm/test/Transforms/GVN/PRE/local-pre.ll @@ -1,6 +1,13 @@ ; RUN: opt < %s -gvn -enable-pre -S | FileCheck %s +declare void @may_exit() nounwind + +declare void @may_exit_1(i32) nounwind + define i32 @main(i32 %p, i32 %q) { + +; CHECK-LABEL: @main( + block1: %cmp = icmp eq i32 %p, %q br i1 %cmp, label %block2, label %block3 @@ -20,3 +27,121 @@ block4: ; CHECK: %b.pre-phi = phi i32 [ %.pre, %block3 ], [ %a, %block2 ] ; CHECK-NEXT: ret i32 %b.pre-phi } + +; Don't PRE across implicit control flow. +define i32 @test2(i32 %p, i32 %q) { + +; CHECK-LABEL: @test2 +; CHECK: block1: + +block1: + %cmp = icmp eq i32 %p, %q + br i1 %cmp, label %block2, label %block3 + +block2: + %a = sdiv i32 %p, %q + br label %block4 + +block3: + br label %block4 + +; CHECK: block4: +; CHECK-NEXT: call void @may_exit( +; CHECK-NEXT: %b = sdiv +; CHECK-NEXT: ret i32 %b + +block4: + call void @may_exit() nounwind + %b = sdiv i32 %p, %q + ret i32 %b +} + +; Don't PRE across implicit control flow. +define i32 @test3(i32 %p, i32 %q, i1 %r) { + +; CHECK-LABEL: @test3 +; CHECK: block1: + +block1: + br i1 %r, label %block2, label %block3 + +block2: + %a = sdiv i32 %p, %q + br label %block4 + +block3: + br label %block4 + +block4: + +; CHECK: block4: +; CHECK-NEXT: phi i32 +; CHECK-NEXT: call void @may_exit_1( +; CHECK-NEXT: %b = sdiv +; CHECK-NEXT: ret i32 %b + + %phi = phi i32 [ 0, %block3 ], [ %a, %block2 ] + call void @may_exit_1(i32 %phi) nounwind + %b = sdiv i32 %p, %q + ret i32 %b + +} + +; It's OK to PRE an instruction that is guaranteed to be safe to execute +; speculatively. +; TODO: Does it make any sense in this case? +define i32 @test4(i32 %p, i32 %q) { + +; CHECK-LABEL: @test4 +; CHECK: block1: + +block1: + %cmp = icmp eq i32 %p, %q + br i1 %cmp, label %block2, label %block3 + +block2: + %a = sdiv i32 %p, 6 + br label %block4 + +block3: + br label %block4 + +; CHECK: block4: +; CHECK-NEXT: %b.pre-phi = phi i32 +; CHECK-NEXT: call void @may_exit( +; CHECK-NEXT: ret i32 %b + +block4: + call void @may_exit() nounwind + %b = sdiv i32 %p, 6 + ret i32 %b +} + +; It is OK to PRE across implicit control flow if we don't insert new +; instructions. +define i32 @test5(i1 %cond, i32 %p, i32 %q) { + +; CHECK-LABEL: @test5 +; CHECK: block1: + +block1: + br i1 %cond, label %block2, label %block3 + +block2: + %a = sdiv i32 %p, %q + br label %block4 + +block3: + %b = sdiv i32 %p, %q + br label %block4 + +; CHECK: block4: +; CHECK-NEXT: %c.pre-phi = phi i32 [ %b, %block3 ], [ %a, %block2 ] +; CHECK-NEXT: call void @may_exit() +; CHECK-NEXT: ret i32 %c.pre-phi + +block4: + call void @may_exit() nounwind + %c = sdiv i32 %p, %q + ret i32 %c +} |

