diff options
author | Philip Reames <listmail@philipreames.com> | 2018-01-03 22:28:26 +0000 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2018-01-03 22:28:26 +0000 |
commit | cf524a408a4343d89b3fa7a3df535dba80116e13 (patch) | |
tree | bf9807d1d0b46936df11b8ef60890b4defdd2897 | |
parent | 10007815ac9f85960b36d5e9cd832d22e80c024b (diff) | |
download | bcm5719-llvm-cf524a408a4343d89b3fa7a3df535dba80116e13.tar.gz bcm5719-llvm-cf524a408a4343d89b3fa7a3df535dba80116e13.zip |
[PRE] Add a bunch of test cases for LICM-like PRE patterns
These were inspired by a very old review I'm about to abandon (https://reviews.llvm.org/D7061). Several of the test cases from that worked without modification and expanding test coverage of such cases is always worthwhile.
llvm-svn: 321764
-rw-r--r-- | llvm/test/Transforms/GVN/PRE/load-pre-licm.ll | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/llvm/test/Transforms/GVN/PRE/load-pre-licm.ll b/llvm/test/Transforms/GVN/PRE/load-pre-licm.ll index d14b01caf77..34edc84a96f 100644 --- a/llvm/test/Transforms/GVN/PRE/load-pre-licm.ll +++ b/llvm/test/Transforms/GVN/PRE/load-pre-licm.ll @@ -37,3 +37,171 @@ if.end: while.end.loopexit: ret void } + +declare void @hold(i32) readonly +declare void @clobber() + +; This is a classic LICM case +define i32 @test1(i1 %cnd, i32* %p) { +; CHECK-LABEL: @test1 +entry: +; CHECK-LABEL: entry +; CHECK-NEXT: %v1.pre = load i32, i32* %p + br label %header + +header: +; CHECK-LABEL: header + %v1 = load i32, i32* %p + call void @hold(i32 %v1) + br label %header +} + + +; Slightly more complicated case to highlight that MemoryDependenceAnalysis +; can compute availability for internal control flow. In this case, because +; the value is fully available across the backedge, we only need to establish +; anticipation for the preheader block (which is trivial in this case.) +define i32 @test2(i1 %cnd, i32* %p) { +; CHECK-LABEL: @test2 +entry: +; CHECK-LABEL: entry +; CHECK-NEXT: %v1.pre = load i32, i32* %p + br label %header + +header: +; CHECK-LABEL: header + %v1 = load i32, i32* %p + call void @hold(i32 %v1) + br i1 %cnd, label %bb1, label %bb2 + +bb1: + br label %merge + +bb2: + br label %merge + +merge: + br label %header +} + + +; TODO: at the moment, our anticipation check does not handle anything +; other than straight-line unconditional fallthrough. This particular +; case could be solved through either a backwards anticipation walk or +; use of the the "safe to speculate" status (if we annotate the param) +define i32 @test3(i1 %cnd, i32* %p) { +entry: +; CHECK-LABEL: @test3 +; CHECK-LABEL: entry + br label %header + +header: + br i1 %cnd, label %bb1, label %bb2 + +bb1: + br label %merge + +bb2: + br label %merge + +merge: +; CHECK-LABEL: merge +; CHECK: load i32, i32* %p + %v1 = load i32, i32* %p + call void @hold(i32 %v1) + br label %header +} + +; Highlight that we can PRE into a latch block when there are multiple +; latches only one of which clobbers an otherwise invariant value. +define i32 @test4(i1 %cnd, i32* %p) { +; CHECK-LABEL: @test4 +entry: +; CHECK-LABEL: entry + %v1 = load i32, i32* %p + call void @hold(i32 %v1) + br label %header + +header: +; CHECK-LABEL: header + %v2 = load i32, i32* %p + call void @hold(i32 %v2) + br i1 %cnd, label %bb1, label %bb2 + +bb1: + br label %header + +bb2: +; CHECK-LABEL: bb2 +; CHECK: call void @clobber() +; CHECK-NEXT: %v2.pre = load i32, i32* %p +; CHECK-NEXT: br label %header + + call void @clobber() + br label %header +} + +; Highlight the fact that we can PRE into a single clobbering latch block +; even in loop simplify form (though multiple applications of the same +; transformation). +define i32 @test5(i1 %cnd, i32* %p) { +; CHECK-LABEL: @test5 +entry: +; CHECK-LABEL: entry + %v1 = load i32, i32* %p + call void @hold(i32 %v1) + br label %header + +header: +; CHECK-LABEL: header + %v2 = load i32, i32* %p + call void @hold(i32 %v2) + br i1 %cnd, label %bb1, label %bb2 + +bb1: + br label %merge + +bb2: +; CHECK-LABEL: bb2 +; CHECK: call void @clobber() +; CHECK-NEXT: %v2.pre.pre = load i32, i32* %p +; CHECK-NEXT: br label %merge + + call void @clobber() + br label %merge + +merge: + br label %header +} + +declare void @llvm.experimental.guard(i1 %cnd, ...) + +; These two tests highlight speculation safety when we can not establish +; anticipation (since the original load might actually not execcute) +define i32 @test6a(i1 %cnd, i32* %p) { +entry: +; CHECK-LABEL: @test6a + br label %header + +header: +; CHECK-LABEL: header +; CHECK: load i32, i32* %p + call void (i1, ...) @llvm.experimental.guard(i1 %cnd) ["deopt"()] + %v1 = load i32, i32* %p + call void @hold(i32 %v1) + br label %header +} + +define i32 @test6b(i1 %cnd, i32* dereferenceable(8) %p) { +entry: +; CHECK-LABEL: @test6b +; CHECK: load i32, i32* %p + br label %header + +header: +; CHECK-LABEL: header + call void (i1, ...) @llvm.experimental.guard(i1 %cnd) ["deopt"()] + %v1 = load i32, i32* %p + call void @hold(i32 %v1) + br label %header +} |