ARM: relax the atomic release barrier to "dmb ishst" on Swift
authorTim Northover <tnorthover@apple.com>
Wed, 3 Jul 2013 09:20:36 +0000 (09:20 +0000)
committerTim Northover <tnorthover@apple.com>
Wed, 3 Jul 2013 09:20:36 +0000 (09:20 +0000)
Swift cores implement store barriers that are stronger than the ARM
specification but weaker than general barriers. They are, in fact, just about
enough to provide the ordering needed for atomic operations with release
semantics.

This patch makes use of that quirk.

llvm-svn: 185527

llvm/lib/Target/ARM/ARMISelLowering.cpp
llvm/test/CodeGen/ARM/atomic-64bit.ll
llvm/test/CodeGen/ARM/atomic-load-store.ll
llvm/test/CodeGen/ARM/swift-atomics.ll [new file with mode: 0644]

index ff8571b..cc09754 100644 (file)
@@ -2557,8 +2557,18 @@ static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG,
                        DAG.getConstant(0, MVT::i32));
   }
 
+  ConstantSDNode *OrdN = cast<ConstantSDNode>(Op.getOperand(1));
+  AtomicOrdering Ord = static_cast<AtomicOrdering>(OrdN->getZExtValue());
+  unsigned Domain = ARM_MB::ISH;
+  if (Subtarget->isSwift() && Ord == Release) {
+    // Swift happens to implement ISHST barriers in a way that's compatible with
+    // Release semantics but weaker than ISH so we'd be fools not to use
+    // it. Beware: other processors probably don't!
+    Domain = ARM_MB::ISHST;
+  }
+
   return DAG.getNode(ARMISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0),
-                     DAG.getConstant(ARM_MB::ISH, MVT::i32));
+                     DAG.getConstant(Domain, MVT::i32));
 }
 
 static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG,
index f2c7305..669c563 100644 (file)
@@ -3,24 +3,24 @@
 
 define i64 @test1(i64* %ptr, i64 %val) {
 ; CHECK: test1:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: adds [[REG3:(r[0-9]?[02468])]], [[REG1]]
 ; CHECK: adc [[REG4:(r[0-9]?[13579])]], [[REG2]]
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test1:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: adds.w [[REG3:[a-z0-9]+]], [[REG1]]
 ; CHECK-THUMB: adc.w [[REG4:[a-z0-9]+]], [[REG2]]
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw add i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -28,24 +28,24 @@ define i64 @test1(i64* %ptr, i64 %val) {
 
 define i64 @test2(i64* %ptr, i64 %val) {
 ; CHECK: test2:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: subs [[REG3:(r[0-9]?[02468])]], [[REG1]]
 ; CHECK: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]]
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test2:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: subs.w [[REG3:[a-z0-9]+]], [[REG1]]
 ; CHECK-THUMB: sbc.w [[REG4:[a-z0-9]+]], [[REG2]]
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw sub i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -53,24 +53,24 @@ define i64 @test2(i64* %ptr, i64 %val) {
 
 define i64 @test3(i64* %ptr, i64 %val) {
 ; CHECK: test3:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: and [[REG3:(r[0-9]?[02468])]], [[REG1]]
 ; CHECK: and [[REG4:(r[0-9]?[13579])]], [[REG2]]
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test3:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: and.w [[REG3:[a-z0-9]+]], [[REG1]]
 ; CHECK-THUMB: and.w [[REG4:[a-z0-9]+]], [[REG2]]
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw and i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -78,24 +78,24 @@ define i64 @test3(i64* %ptr, i64 %val) {
 
 define i64 @test4(i64* %ptr, i64 %val) {
 ; CHECK: test4:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: orr [[REG3:(r[0-9]?[02468])]], [[REG1]]
 ; CHECK: orr [[REG4:(r[0-9]?[13579])]], [[REG2]]
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test4:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: orr.w [[REG3:[a-z0-9]+]], [[REG1]]
 ; CHECK-THUMB: orr.w [[REG4:[a-z0-9]+]], [[REG2]]
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw or i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -103,24 +103,24 @@ define i64 @test4(i64* %ptr, i64 %val) {
 
 define i64 @test5(i64* %ptr, i64 %val) {
 ; CHECK: test5:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: eor [[REG3:(r[0-9]?[02468])]], [[REG1]]
 ; CHECK: eor [[REG4:(r[0-9]?[13579])]], [[REG2]]
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test5:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: eor.w [[REG3:[a-z0-9]+]], [[REG1]]
 ; CHECK-THUMB: eor.w [[REG4:[a-z0-9]+]], [[REG2]]
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw xor i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -128,20 +128,20 @@ define i64 @test5(i64* %ptr, i64 %val) {
 
 define i64 @test6(i64* %ptr, i64 %val) {
 ; CHECK: test6:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test6:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw xchg i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -149,7 +149,7 @@ define i64 @test6(i64* %ptr, i64 %val) {
 
 define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
 ; CHECK: test7:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: cmp [[REG1]]
 ; CHECK: cmpeq [[REG2]]
@@ -157,10 +157,10 @@ define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test7:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: cmp [[REG1]]
 ; CHECK-THUMB: it eq
@@ -169,7 +169,7 @@ define i64 @test7(i64* %ptr, i64 %val1, i64 %val2) {
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = cmpxchg i64* %ptr, i64 %val1, i64 %val2 seq_cst
   ret i64 %r
@@ -186,7 +186,7 @@ define i64 @test8(i64* %ptr) {
 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test8:
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
@@ -197,7 +197,7 @@ define i64 @test8(i64* %ptr) {
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = load atomic i64* %ptr seq_cst, align 8
   ret i64 %r
@@ -207,20 +207,20 @@ define i64 @test8(i64* %ptr) {
 ; way to write it.
 define void @test9(i64* %ptr, i64 %val) {
 ; CHECK: test9:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test9:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   store atomic i64 %val, i64* %ptr seq_cst, align 8
   ret void
@@ -228,7 +228,7 @@ define void @test9(i64* %ptr, i64 %val) {
 
 define i64 @test10(i64* %ptr, i64 %val) {
 ; CHECK: test10:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]]
 ; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]]
@@ -236,10 +236,10 @@ define i64 @test10(i64* %ptr, i64 %val) {
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test10:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]]
 ; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]]
@@ -247,7 +247,7 @@ define i64 @test10(i64* %ptr, i64 %val) {
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw min i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -255,7 +255,7 @@ define i64 @test10(i64* %ptr, i64 %val) {
 
 define i64 @test11(i64* %ptr, i64 %val) {
 ; CHECK: test11:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]]
 ; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]]
@@ -263,11 +263,11 @@ define i64 @test11(i64* %ptr, i64 %val) {
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 
 ; CHECK-THUMB: test11:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]]
 ; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]]
@@ -275,7 +275,7 @@ define i64 @test11(i64* %ptr, i64 %val) {
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw umin i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -283,7 +283,7 @@ define i64 @test11(i64* %ptr, i64 %val) {
 
 define i64 @test12(i64* %ptr, i64 %val) {
 ; CHECK: test12:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]]
 ; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]]
@@ -291,10 +291,10 @@ define i64 @test12(i64* %ptr, i64 %val) {
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test12:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]]
 ; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]]
@@ -302,7 +302,7 @@ define i64 @test12(i64* %ptr, i64 %val) {
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 
   %r = atomicrmw max i64* %ptr, i64 %val seq_cst
   ret i64 %r
@@ -310,7 +310,7 @@ define i64 @test12(i64* %ptr, i64 %val) {
 
 define i64 @test13(i64* %ptr, i64 %val) {
 ; CHECK: test13:
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 ; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
 ; CHECK: subs {{[a-z0-9]+}}, [[REG1]], [[REG3:(r[0-9]?[02468])]]
 ; CHECK: sbcs {{[a-z0-9]+}}, [[REG2]], [[REG4:(r[0-9]?[13579])]]
@@ -318,10 +318,10 @@ define i64 @test13(i64* %ptr, i64 %val) {
 ; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK: cmp
 ; CHECK: bne
-; CHECK: dmb ish
+; CHECK: dmb {{ish$}}
 
 ; CHECK-THUMB: test13:
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
 ; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
 ; CHECK-THUMB: subs.w {{[a-z0-9]+}}, [[REG1]], [[REG3:[a-z0-9]+]]
 ; CHECK-THUMB: sbcs.w {{[a-z0-9]+}}, [[REG2]], [[REG4:[a-z0-9]+]]
@@ -329,7 +329,7 @@ define i64 @test13(i64* %ptr, i64 %val) {
 ; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
 ; CHECK-THUMB: cmp
 ; CHECK-THUMB: bne
-; CHECK-THUMB: dmb ish
+; CHECK-THUMB: dmb {{ish$}}
   %r = atomicrmw umax i64* %ptr, i64 %val seq_cst
   ret i64 %r
 }
index 66916a7..476b3dd 100644 (file)
@@ -6,15 +6,15 @@
 
 define void @test1(i32* %ptr, i32 %val1) {
 ; ARM: test1
-; ARM: dmb ish
+; ARM: dmb {{ish$}}
 ; ARM-NEXT: str
-; ARM-NEXT: dmb ish
+; ARM-NEXT: dmb {{ish$}}
 ; THUMBONE: test1
 ; THUMBONE: __sync_lock_test_and_set_4
 ; THUMBTWO: test1
-; THUMBTWO: dmb ish
+; THUMBTWO: dmb {{ish$}}
 ; THUMBTWO-NEXT: str
-; THUMBTWO-NEXT: dmb ish
+; THUMBTWO-NEXT: dmb {{ish$}}
   store atomic i32 %val1, i32* %ptr seq_cst, align 4
   ret void
 }
@@ -22,12 +22,12 @@ define void @test1(i32* %ptr, i32 %val1) {
 define i32 @test2(i32* %ptr) {
 ; ARM: test2
 ; ARM: ldr
-; ARM-NEXT: dmb ish
+; ARM-NEXT: dmb {{ish$}}
 ; THUMBONE: test2
 ; THUMBONE: __sync_val_compare_and_swap_4
 ; THUMBTWO: test2
 ; THUMBTWO: ldr
-; THUMBTWO-NEXT: dmb ish
+; THUMBTWO-NEXT: dmb {{ish$}}
   %val = load atomic i32* %ptr seq_cst, align 4
   ret i32 %val
 }
diff --git a/llvm/test/CodeGen/ARM/swift-atomics.ll b/llvm/test/CodeGen/ARM/swift-atomics.ll
new file mode 100644 (file)
index 0000000..9711a9f
--- /dev/null
@@ -0,0 +1,45 @@
+; RUN: llc -mtriple=armv7-apple-ios6.0 -mcpu=swift < %s | FileCheck %s
+; RUN: llc -mtriple=armv7-apple-ios6.0 < %s | FileCheck %s --check-prefix=CHECK-STRICT-ATOMIC
+
+; Release operations only need the store barrier provided by a "dmb ishst",
+
+define void @test_store_release(i32* %p, i32 %v) {
+; CHECK: test_store_release:
+; CHECK: dmb ishst
+; CHECK: str
+
+; CHECK-STRICT-ATOMIC: dmb {{ish$}}
+  store atomic i32 %v, i32* %p release, align 4
+  ret void
+}
+
+; However, if sequential consistency is needed *something* must ensure a release
+; followed by an acquire does not get reordered. In that case a "dmb ishst" is
+; not adequate.
+define i32 @test_seq_cst(i32* %p, i32 %v) {
+; CHECK: test_seq_cst:
+; CHECK: dmb ishst
+; CHECK: str
+; CHECK: dmb {{ish$}}
+; CHECK: ldr
+; CHECK: dmb {{ish$}}
+
+; CHECK-STRICT-ATOMIC: dmb {{ish$}}
+; CHECK-STRICT-ATOMIC: dmb {{ish$}}
+
+  store atomic i32 %v, i32* %p seq_cst, align 4
+  %val = load atomic i32* %p seq_cst, align 4
+  ret i32 %val
+}
+
+; Also, pure acquire operations should definitely not have an ishst barrier.
+
+define i32 @test_acq(i32* %addr) {
+; CHECK: test_acq:
+; CHECK: ldr
+; CHECK: dmb {{ish$}}
+
+; CHECK-STRICT-ATOMIC: dmb {{ish$}}
+  %val = load atomic i32* %addr acquire, align 4
+  ret i32 %val
+}