summaryrefslogtreecommitdiffstats
path: root/llvm/test/CodeGen
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@imgtec.com>2017-02-24 16:32:18 +0000
committerSimon Dardis <simon.dardis@imgtec.com>2017-02-24 16:32:18 +0000
commitae6f2bcb258472b3ed89b24b8fa6989395c059e3 (patch)
treeaa70d33c1f2346b99231e5eca9cdcc417ee9d0d5 /llvm/test/CodeGen
parent3c58c18ff0f9670f5d4d493263f2cd7dc84258c0 (diff)
downloadbcm5719-llvm-ae6f2bcb258472b3ed89b24b8fa6989395c059e3.tar.gz
bcm5719-llvm-ae6f2bcb258472b3ed89b24b8fa6989395c059e3.zip
Recommit "[mips] Fix atomic compare and swap at O0."
This time with the missing files. Similar to PR/25526, fast-regalloc introduces spills at the end of basic blocks. When this occurs in between an ll and sc, the store can cause the atomic sequence to fail. This patch fixes the issue by introducing more pseudos to represent atomic operations and moving their lowering to after the expansion of postRA pseudos. This resolves PR/32020. Thanks to James Cowgill for reporting the issue! Reviewers: slthakur Differential Revision: https://reviews.llvm.org/D30257 llvm-svn: 296134
Diffstat (limited to 'llvm/test/CodeGen')
-rw-r--r--llvm/test/CodeGen/Mips/atomicCmpSwapPW.ll14
-rw-r--r--llvm/test/CodeGen/Mips/no-store-in-atomic-rmw.ll156
2 files changed, 167 insertions, 3 deletions
diff --git a/llvm/test/CodeGen/Mips/atomicCmpSwapPW.ll b/llvm/test/CodeGen/Mips/atomicCmpSwapPW.ll
index 981f0983fa4..e64501d1fa8 100644
--- a/llvm/test/CodeGen/Mips/atomicCmpSwapPW.ll
+++ b/llvm/test/CodeGen/Mips/atomicCmpSwapPW.ll
@@ -5,13 +5,21 @@
; RUN: llc -O0 -march=mips64el -mcpu=mips64r2 -target-abi=n64 < %s -filetype=asm -o - \
; RUN: | FileCheck -check-prefixes=PTR64,ALL %s
+
+; ALL-LABEL: foo:
; PTR32: lw $[[R0:[0-9]+]]
+; PTR32: addiu $[[R1:[0-9]+]], $zero, -4
+; PTR32: and $[[R2:[0-9]+]], $[[R0]], $[[R1]]
+
; PTR64: ld $[[R0:[0-9]+]]
+; PTR64: daddiu $[[R1:[0-9]+]], $zero, -4
+; PTR64: and $[[R2:[0-9]+]], $[[R0]], $[[R1]]
-; ALL: ll ${{[0-9]+}}, 0($[[R0]])
+; ALL: ll ${{[0-9]+}}, 0($[[R2]])
-define {i16, i1} @foo(i16* %addr, i16 signext %r, i16 zeroext %new) {
- %res = cmpxchg i16* %addr, i16 %r, i16 %new seq_cst seq_cst
+define {i16, i1} @foo(i16** %addr, i16 signext %r, i16 zeroext %new) {
+ %ptr = load i16*, i16** %addr
+ %res = cmpxchg i16* %ptr, i16 %r, i16 %new seq_cst seq_cst
ret {i16, i1} %res
}
diff --git a/llvm/test/CodeGen/Mips/no-store-in-atomic-rmw.ll b/llvm/test/CodeGen/Mips/no-store-in-atomic-rmw.ll
new file mode 100644
index 00000000000..fc6b278ec8a
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/no-store-in-atomic-rmw.ll
@@ -0,0 +1,156 @@
+; RUN: llc -O0 -march=mips64 -mcpu=mips64r2 < %s | FileCheck %s
+
+; Check that no stores occur between ll and sc when the fast register allocator
+; is used. Atomic read-modify-write sequences on certain MIPS implementations
+; will fail if a store occurs between a ll and sc.
+
+define i32 @main() {
+; CHECK-LABEL: main:
+entry:
+ %retval = alloca i32, align 4
+ %I = alloca i32, align 4
+ %k = alloca i32, align 4
+ %i = alloca i32*, align 8
+ %ret = alloca i32, align 4
+ %flag_k = alloca i8, align 1
+ %.atomictmp = alloca i32, align 4
+ %atomic-temp = alloca i32, align 4
+ %.atomictmp1 = alloca i32, align 4
+ %atomic-temp2 = alloca i32, align 4
+ %.atomictmp3 = alloca i32, align 4
+ %atomic-temp4 = alloca i32, align 4
+ %.atomictmp5 = alloca i32, align 4
+ %atomic-temp6 = alloca i32, align 4
+ %.atomictmp7 = alloca i32, align 4
+ %atomic-temp8 = alloca i32, align 4
+ %.atomictmp9 = alloca i32, align 4
+ %atomic-temp10 = alloca i32, align 4
+ %.atomictmp11 = alloca i32, align 4
+ %atomic-temp12 = alloca i32, align 4
+ %.atomictmp13 = alloca i32, align 4
+ %cmpxchg.bool = alloca i8, align 1
+ %cmpxchg.bool14 = alloca i8, align 1
+ store i32 0, i32* %retval, align 4
+ store i32 0, i32* %I, align 4
+ store i32 5, i32* %k, align 4
+ store i32* %I, i32** %i, align 8
+ store i32 0, i32* %ret, align 4
+ store i8 0, i8* %flag_k, align 1
+ %0 = load i32*, i32** %i, align 8
+ %1 = load i32, i32* %k, align 4
+ %2 = atomicrmw xchg i32* %0, i32 %1 monotonic
+; CHECK-LABEL: .LBB0_1:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: sc
+ store i32 %2, i32* %ret, align 4
+ %3 = load i32*, i32** %i, align 8
+ store i32 3, i32* %.atomictmp, align 4
+ %4 = load i32, i32* %.atomictmp, align 4
+ %5 = atomicrmw add i32* %3, i32 %4 monotonic
+; CHECK-LABEL: .LBB0_3:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: addu
+; CHECK: sc
+ store i32 %5, i32* %atomic-temp, align 4
+ %6 = load i32, i32* %atomic-temp, align 4
+ %7 = load i32*, i32** %i, align 8
+ store i32 3, i32* %.atomictmp1, align 4
+ %8 = load i32, i32* %.atomictmp1, align 4
+ %9 = atomicrmw sub i32* %7, i32 %8 monotonic
+; CHECK-LABEL: .LBB0_5:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: subu
+; CHECK: sc
+ store i32 %9, i32* %atomic-temp2, align 4
+ %10 = load i32, i32* %atomic-temp2, align 4
+ %11 = load i32*, i32** %i, align 8
+ store i32 3, i32* %.atomictmp3, align 4
+ %12 = load i32, i32* %.atomictmp3, align 4
+ %13 = atomicrmw and i32* %11, i32 %12 monotonic
+; CHECK-LABEL: .LBB0_7:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: and
+; CHECK: sc
+ store i32 %13, i32* %atomic-temp4, align 4
+ %14 = load i32, i32* %atomic-temp4, align 4
+ %15 = load i32*, i32** %i, align 8
+ store i32 3, i32* %.atomictmp5, align 4
+ %16 = load i32, i32* %.atomictmp5, align 4
+ %17 = atomicrmw or i32* %15, i32 %16 monotonic
+; CHECK-LABEL: .LBB0_9:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: or
+; CHECK: sc
+ %18 = load i32*, i32** %i, align 8
+ store i32 5, i32* %.atomictmp13, align 4
+ %19 = load i32, i32* %I, align 4
+ %20 = load i32, i32* %.atomictmp13, align 4
+ %21 = cmpxchg weak i32* %18, i32 %19, i32 %20 monotonic monotonic
+; CHECK-LABEL: .LBB0_11:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: sc
+ %22 = extractvalue { i32, i1 } %21, 0
+ %23 = extractvalue { i32, i1 } %21, 1
+ br i1 %23, label %cmpxchg.continue, label %cmpxchg.store_expected
+
+cmpxchg.store_expected: ; preds = %entry
+ store i32 %22, i32* %I, align 4
+ br label %cmpxchg.continue
+
+cmpxchg.continue: ; preds = %cmpxchg.store_expected, %entry
+ %frombool = zext i1 %23 to i8
+ store i8 %frombool, i8* %cmpxchg.bool, align 1
+ %24 = load i8, i8* %cmpxchg.bool, align 1
+ %tobool = trunc i8 %24 to i1
+ %25 = load i32*, i32** %i, align 8
+ %26 = load i32, i32* %I, align 4
+ %27 = load i32, i32* %ret, align 4
+ %28 = cmpxchg i32* %25, i32 %26, i32 %27 monotonic monotonic
+; CHECK-LABEL: .LBB0_17:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: sc
+ %29 = extractvalue { i32, i1 } %28, 0
+ %30 = extractvalue { i32, i1 } %28, 1
+ br i1 %30, label %cmpxchg.continue16, label %cmpxchg.store_expected15
+
+cmpxchg.store_expected15: ; preds = %cmpxchg.continue
+ store i32 %29, i32* %I, align 4
+ br label %cmpxchg.continue16
+
+cmpxchg.continue16: ; preds = %cmpxchg.store_expected15, %cmpxchg.continue
+ %frombool17 = zext i1 %30 to i8
+ store i8 %frombool17, i8* %cmpxchg.bool14, align 1
+ %31 = load i8, i8* %cmpxchg.bool14, align 1
+ %tobool18 = trunc i8 %31 to i1
+ %32 = atomicrmw xchg i8* %flag_k, i8 1 monotonic
+; CHECK-LABEL: .LBB0_23:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: sc
+ %tobool19 = icmp ne i8 %32, 0
+ %33 = atomicrmw xchg i8* %flag_k, i8 1 monotonic
+; CHECK-LABEL: .LBB0_26:
+; CHECK: ll
+; CHECK-NOT: sd
+; CHECK-NOT: sw
+; CHECK: sc
+ %tobool20 = icmp ne i8 %33, 0
+ store atomic i8 0, i8* %flag_k monotonic, align 1
+ %34 = load i32, i32* %retval, align 4
+ ret i32 %34
+}
OpenPOWER on IntegriCloud