diff options
| author | Philip Reames <listmail@philipreames.com> | 2015-12-08 21:45:41 +0000 |
|---|---|---|
| committer | Philip Reames <listmail@philipreames.com> | 2015-12-08 21:45:41 +0000 |
| commit | 8fc2cbf933d6d264538bd59321320649ea935aef (patch) | |
| tree | c2e4db58b767a12c6156bfee90f905001f3eea49 /llvm/test/Transforms | |
| parent | 0aea1b89eb63affa44d88bc836ee323ce605ec03 (diff) | |
| download | bcm5719-llvm-8fc2cbf933d6d264538bd59321320649ea935aef.tar.gz bcm5719-llvm-8fc2cbf933d6d264538bd59321320649ea935aef.zip | |
[EarlyCSE] Value forwarding for unordered atomics
This patch teaches the fully redundant load part of EarlyCSE how to forward from atomic and volatile loads and stores, and how to eliminate unordered atomics (only). This patch does not include dead store elimination support for unordered atomics, that will follow in the near future.
The basic idea is that we allow all loads and stores to be tracked by the AvailableLoad table. We store a bit in the table which tracks whether load/store was atomic, and then only replace atomic loads with ones which were also atomic.
No attempt is made to refine our handling of ordered loads or stores. Those are still treated as full fences. We could pretty easily extend the release fence handling to release stores, but that should be a separate patch.
Differential Revision: http://reviews.llvm.org/D15337
llvm-svn: 255054
Diffstat (limited to 'llvm/test/Transforms')
| -rw-r--r-- | llvm/test/Transforms/EarlyCSE/atomics.ll | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/llvm/test/Transforms/EarlyCSE/atomics.ll b/llvm/test/Transforms/EarlyCSE/atomics.ll new file mode 100644 index 00000000000..f08220fd42d --- /dev/null +++ b/llvm/test/Transforms/EarlyCSE/atomics.ll @@ -0,0 +1,127 @@ +; RUN: opt < %s -S -early-cse | FileCheck %s + +; CHECK-LABEL: @test12( +define i32 @test12(i1 %B, i32* %P1, i32* %P2) { + %load0 = load i32, i32* %P1 + %1 = load atomic i32, i32* %P2 seq_cst, align 4 + %load1 = load i32, i32* %P1 + %sel = select i1 %B, i32 %load0, i32 %load1 + ret i32 %sel + ; CHECK: load i32, i32* %P1 + ; CHECK: load i32, i32* %P1 +} + +; CHECK-LABEL: @test13( +; atomic to non-atomic forwarding is legal +define i32 @test13(i1 %B, i32* %P1) { + %a = load atomic i32, i32* %P1 seq_cst, align 4 + %b = load i32, i32* %P1 + %res = sub i32 %a, %b + ret i32 %res + ; CHECK: load atomic i32, i32* %P1 + ; CHECK: ret i32 0 +} + +; CHECK-LABEL: @test14( +; atomic to unordered atomic forwarding is legal +define i32 @test14(i1 %B, i32* %P1) { + %a = load atomic i32, i32* %P1 seq_cst, align 4 + %b = load atomic i32, i32* %P1 unordered, align 4 + %res = sub i32 %a, %b + ret i32 %res + ; CHECK: load atomic i32, i32* %P1 + ; CHECK: ret i32 0 +} + +; CHECK-LABEL: @test15( +; implementation restiction: can't forward to stonger +; than unordered +define i32 @test15(i1 %B, i32* %P1, i32* %P2) { + %a = load atomic i32, i32* %P1 seq_cst, align 4 + %b = load atomic i32, i32* %P1 seq_cst, align 4 + %res = sub i32 %a, %b + ret i32 %res + ; CHECK: load atomic i32, i32* %P1 + ; CHECK: load atomic i32, i32* %P1 +} + +; CHECK-LABEL: @test16( +; forwarding non-atomic to atomic is wrong! (However, +; it would be legal to use the later value in place of the +; former in this particular example. We just don't +; do that right now.) +define i32 @test16(i1 %B, i32* %P1, i32* %P2) { + %a = load i32, i32* %P1, align 4 + %b = load atomic i32, i32* %P1 unordered, align 4 + %res = sub i32 %a, %b + ret i32 %res + ; CHECK: load i32, i32* %P1 + ; CHECK: load atomic i32, i32* %P1 +} + +; Can't DSE across a full fence +define void @test17(i1 %B, i32* %P1, i32* %P2) { +; CHECK-LABEL: @test17 +; CHECK: store +; CHECK: store atomic +; CHECK: store + store i32 0, i32* %P1, align 4 + store atomic i32 0, i32* %P2 seq_cst, align 4 + store i32 0, i32* %P1, align 4 + ret void +} + +; Can't remove a volatile load +define i32 @test18(i1 %B, i32* %P1, i32* %P2) { + %a = load i32, i32* %P1, align 4 + %b = load volatile i32, i32* %P1, align 4 + %res = sub i32 %a, %b + ret i32 %res + ; CHECK-LABEL: @test18 + ; CHECK: load i32, i32* %P1 + ; CHECK: load volatile i32, i32* %P1 +} + +; Can't DSE a volatile store +define void @test19(i1 %B, i32* %P1, i32* %P2) { +; CHECK-LABEL: @test19 +; CHECK: store volatile +; CHECK: store + store volatile i32 0, i32* %P1, align 4 + store i32 3, i32* %P1, align 4 + ret void +} + +; Can value forward from volailes +define i32 @test20(i1 %B, i32* %P1, i32* %P2) { + %a = load volatile i32, i32* %P1, align 4 + %b = load i32, i32* %P1, align 4 + %res = sub i32 %a, %b + ret i32 %res + ; CHECK-LABEL: @test20 + ; CHECK: load volatile i32, i32* %P1 + ; CHECK: ret i32 0 +} + +; Can DSE a non-volatile store in favor of a volatile one +; currently a missed optimization +define void @test21(i1 %B, i32* %P1, i32* %P2) { +; CHECK-LABEL: @test21 +; CHECK: store +; CHECK: store volatile + store i32 0, i32* %P1, align 4 + store volatile i32 3, i32* %P1, align 4 + ret void +} + +; Can DSE a normal store in favor of a unordered one +define void @test22(i1 %B, i32* %P1, i32* %P2) { +; CHECK-LABEL: @test22 +; CHECK-NEXT: store atomic + store i32 0, i32* %P1, align 4 + store atomic i32 3, i32* %P1 unordered, align 4 + ret void +} + + + |

