summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/DeadStoreElimination
diff options
context:
space:
mode:
authorPhilip Reames <listmail@philipreames.com>2016-03-25 22:40:35 +0000
committerPhilip Reames <listmail@philipreames.com>2016-03-25 22:40:35 +0000
commitb5681138e41ea0c2712c6bf1b770f66391f45216 (patch)
treefd7751f7ef543b21296c78666ce3a88cccce10b0 /llvm/test/Transforms/DeadStoreElimination
parent0e32c5283ae8307179da18ddeef112435bbcbf6b (diff)
downloadbcm5719-llvm-b5681138e41ea0c2712c6bf1b770f66391f45216.tar.gz
bcm5719-llvm-b5681138e41ea0c2712c6bf1b770f66391f45216.zip
Allow value forwarding past release fences in GVN
A release fence acts as a publication barrier for stores within the current thread to become visible to other threads which might observe the release fence. It does not require the current thread to observe stores performed on other threads. As a result, we can allow store-load and load-load forwarding across a release fence. We choose to be much more conservative about stores. In theory, nothing prevents us from shifting a store from after a release fence to before it, and then eliminating the preceeding (previously fenced) store. Doing this without actually moving the second store is likely also legal, but we chose to be conservative at this time. The LangRef indicates only atomic loads and stores are effected by fences. This patch chooses to be far more conservative then that. This is the GVN companion to http://reviews.llvm.org/D11434 which applied the same logic in EarlyCSE and has been baking in tree for a while now. Differential Revision: http://reviews.llvm.org/D11436 llvm-svn: 264472
Diffstat (limited to 'llvm/test/Transforms/DeadStoreElimination')
-rw-r--r--llvm/test/Transforms/DeadStoreElimination/fence.ll48
1 files changed, 48 insertions, 0 deletions
diff --git a/llvm/test/Transforms/DeadStoreElimination/fence.ll b/llvm/test/Transforms/DeadStoreElimination/fence.ll
new file mode 100644
index 00000000000..66cfc7dd774
--- /dev/null
+++ b/llvm/test/Transforms/DeadStoreElimination/fence.ll
@@ -0,0 +1,48 @@
+; RUN: opt -S -basicaa -dse < %s | FileCheck %s
+
+; We conservative choose to prevent dead store elimination
+; across release or stronger fences. It's not required
+; (since the must still be a race on %addd.i), but
+; it is conservatively correct. A legal optimization
+; could hoist the second store above the fence, and then
+; DSE one of them.
+define void @test1(i32* %addr.i) {
+; CHECK-LABEL: @test1
+; CHECK: store i32 5
+; CHECK: fence
+; CHECK: store i32 5
+; CHECK: ret
+ store i32 5, i32* %addr.i, align 4
+ fence release
+ store i32 5, i32* %addr.i, align 4
+ ret void
+}
+
+; Same as previous, but with different values. If we ever optimize
+; this more aggressively, this allows us to check that the correct
+; store is retained (the 'i32 1' store in this case)
+define void @test1b(i32* %addr.i) {
+; CHECK-LABEL: @test1b
+; CHECK: store i32 42
+; CHECK: fence release
+; CHECK: store i32 1
+; CHECK: ret
+ store i32 42, i32* %addr.i, align 4
+ fence release
+ store i32 1, i32* %addr.i, align 4
+ ret void
+}
+
+; We *could* DSE across this fence, but don't. No other thread can
+; observe the order of the acquire fence and the store.
+define void @test2(i32* %addr.i) {
+; CHECK-LABEL: @test2
+; CHECK: store
+; CHECK: fence
+; CHECK: store
+; CHECK: ret
+ store i32 5, i32* %addr.i, align 4
+ fence acquire
+ store i32 5, i32* %addr.i, align 4
+ ret void
+}
OpenPOWER on IntegriCloud