aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJF Bastien <jfb@chromium.org>2013-07-30 16:38:26 -0700
committerJF Bastien <jfb@chromium.org>2013-07-30 16:38:26 -0700
commitf75fd0a9f95109b9cb13a74aad6dcc98c3d5d625 (patch)
tree652c465d76008ef58f5c8d55827050a6f1d875e1 /test
parent423b3bb89c78e96c59843aa7c6e55d01bde174d1 (diff)
Rewrite ``asm("":::"memory")`` to ``fence seq_cst``
This is often used as a compiler barrier and should "just work" in user code. BUG= https://code.google.com/p/nativeclient/issues/detail?id=2345 R=eliben@chromium.org TEST= (cd ./pnacl/build/llvm_x86_64 && ninja check-all) Review URL: https://codereview.chromium.org/21178002
Diffstat (limited to 'test')
-rw-r--r--test/Transforms/NaCl/rewrite-asm-memory.ll71
1 files changed, 71 insertions, 0 deletions
diff --git a/test/Transforms/NaCl/rewrite-asm-memory.ll b/test/Transforms/NaCl/rewrite-asm-memory.ll
new file mode 100644
index 0000000000..8481c831ee
--- /dev/null
+++ b/test/Transforms/NaCl/rewrite-asm-memory.ll
@@ -0,0 +1,71 @@
+; RUN: opt < %s -rewrite-asm-directives -S | FileCheck %s
+; RUN: opt < %s -O3 -rewrite-asm-directives -S | FileCheck %s
+; RUN: opt < %s -O3 -rewrite-asm-directives -S | FileCheck %s -check-prefix=ELIM
+; RUN: opt < %s -rewrite-asm-directives -S | FileCheck %s -check-prefix=CLEANED
+
+; Test that asm("":::"memory"), a compiler barrier, gets rewritten to a
+; sequentially-consistent fence. The test is also run at O3 to make sure
+; that loads and stores don't get unexpectedly eliminated.
+
+; CLEANED-NOT: asm
+
+@a = external global i32
+@b = external global i32
+
+; Different triples encode "touch everything" constraints differently.
+define void @memory_assembly_encoding_test() {
+; CHECK: @memory_assembly_encoding_test()
+ call void asm sideeffect "", "~{memory}"()
+ call void asm sideeffect "", "~{memory},~{dirflag},~{fpsr},~{flags}"()
+ ; CHECK-NEXT: fence seq_cst
+ ; CHECK-NEXT: fence seq_cst
+
+ ret void
+ ; CHECK-NEXT: ret void
+}
+
+define void @memory_assembly_ordering_test() {
+; CHECK: @memory_assembly_ordering_test()
+ %1 = load i32* @a, align 4
+ store i32 %1, i32* @b, align 4
+ call void asm sideeffect "", "~{memory}"()
+ ; CHECK-NEXT: %1 = load i32* @a, align 4
+ ; CHECK-NEXT: store i32 %1, i32* @b, align 4
+ ; CHECK-NEXT: fence seq_cst
+
+ ; Redundant load from the previous location, and store to the same
+ ; location (making the previous one dead). Shouldn't get eliminated
+ ; because of the fence.
+ %2 = load i32* @a, align 4
+ store i32 %2, i32* @b, align 4
+ call void asm sideeffect "", "~{memory}"()
+ ; CHECK-NEXT: %2 = load i32* @a, align 4
+ ; CHECK-NEXT: store i32 %2, i32* @b, align 4
+ ; CHECK-NEXT: fence seq_cst
+
+ ; Same here.
+ %3 = load i32* @a, align 4
+ store i32 %3, i32* @b, align 4
+ ; CHECK-NEXT: %3 = load i32* @a, align 4
+ ; CHECK-NEXT: store i32 %3, i32* @b, align 4
+
+ ret void
+ ; CHECK-NEXT: ret void
+}
+
+; Same function as above, but without the barriers. At O3 some loads and
+; stores should get eliminated.
+define void @memory_ordering_test() {
+; ELIM: @memory_ordering_test()
+ %1 = load i32* @a, align 4
+ store i32 %1, i32* @b, align 4
+ %2 = load i32* @a, align 4
+ store i32 %2, i32* @b, align 4
+ %3 = load i32* @a, align 4
+ store i32 %3, i32* @b, align 4
+ ; ELIM-NEXT: %1 = load i32* @a, align 4
+ ; ELIM-NEXT: store i32 %1, i32* @b, align 4
+
+ ret void
+ ; ELIM-NEXT: ret void
+}