[llvm] [ARM] Fix failure to register-allocate CMP_SWAP_64 pseudo-inst (PR #104039)
Oliver Stannard via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 14 08:26:42 PDT 2024
https://github.com/ostannard created https://github.com/llvm/llvm-project/pull/104039
This test case was failing to compile with a "ran out of registers during register allocation" error at -O0. This was because CMP_SWAP_64 has 3 operands which must be an even-odd register pair, and two other GPR operands. All of the def operands are also early-clobber, so registers can't be shared between uses and defs. Because the function has an over-aligned alloca it needs frame and base pointers, so r6 and r11 are both reserved. That leaves r0/r1, r2/r3, r4/r5 and r8/r9 as the only valid register pairs, and if the two individual GPR operands happen to get allocated to registers in different pairs then only 2 pairs will be available for the three GPRPair operands.
The fix is to allocate the GPRPair operands first, because once they are allocated they can't prevent the GPR operands from being allocated.
Fixes #98222
>From ccfd2ab0be992ba25bfdc1b4892428cd4c98c2d4 Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 14 Aug 2024 15:42:25 +0100
Subject: [PATCH 1/3] Re-generate tests
---
llvm/test/CodeGen/ARM/atomic-64bit.ll | 1846 ++++++++++++---
llvm/test/CodeGen/ARM/atomic-ops-v8.ll | 2904 ++++++++++++++++--------
2 files changed, 3489 insertions(+), 1261 deletions(-)
diff --git a/llvm/test/CodeGen/ARM/atomic-64bit.ll b/llvm/test/CodeGen/ARM/atomic-64bit.ll
index ab9e1dfd1cfb19..80658bdb9fda0a 100644
--- a/llvm/test/CodeGen/ARM/atomic-64bit.ll
+++ b/llvm/test/CodeGen/ARM/atomic-64bit.ll
@@ -1,219 +1,722 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE
; RUN: llc < %s -mtriple=thumbv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-LE
; RUN: llc < %s -mtriple=armebv7 -target-abi apcs | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE
; RUN: llc < %s -mtriple=thumbebv7-none-linux-gnueabihf | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-BE
-; RUN: llc < %s -mtriple=armv7m--none-eabi | FileCheck %s --check-prefix=CHECK-M
-; RUN: llc < %s -mtriple=armv8m--none-eabi | FileCheck %s --check-prefix=CHECK-M
+; RUN: llc < %s -mtriple=armv7m--none-eabi | FileCheck %s --check-prefix=CHECK-7M
+; RUN: llc < %s -mtriple=armv8m--none-eabi | FileCheck %s --check-prefix=CHECK-8M
define i64 @test1(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test1:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE: adds [[REG3:(r[0-9]?[02468])]], [[REG1]]
-; CHECK-LE: adc [[REG4:(r[0-9]?[13579])]], [[REG2]]
-; CHECK-BE: adds [[REG4:(r[0-9]?[13579])]], [[REG2]]
-; CHECK-BE: adc [[REG3:(r[0-9]?[02468])]], [[REG1]]
-; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test1:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE: adds.w [[REG3:[a-z0-9]+]], [[REG1]]
-; CHECK-THUMB-LE: adc.w [[REG4:[a-z0-9]+]], [[REG2]]
-; CHECK-THUMB-BE: adds.w [[REG4:[a-z0-9]+]], [[REG2]]
-; CHECK-THUMB-BE: adc.w [[REG3:[a-z0-9]+]], [[REG1]]
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_fetch_add_8
+; CHECK-LE-LABEL: test1:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB0_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: adds r6, r4, r1
+; CHECK-LE-NEXT: adc r7, r5, r2
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB0_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-LE-LABEL: test1:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: mov r12, r0
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: .LBB0_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT: adds.w lr, r0, r2
+; CHECK-THUMB-LE-NEXT: adc.w r4, r1, r3
+; CHECK-THUMB-LE-NEXT: strexd r5, lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB0_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test1:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB0_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: adds r7, r5, r2
+; CHECK-BE-NEXT: adc r6, r4, r1
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB0_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test1:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: mov r12, r0
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: .LBB0_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT: adds.w lr, r1, r3
+; CHECK-THUMB-BE-NEXT: adc.w r4, r0, r2
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB0_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-7M-LABEL: test1:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: .pad #8
+; CHECK-7M-NEXT: sub sp, #8
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: str r1, [sp]
+; CHECK-7M-NEXT: bl __atomic_fetch_add_8
+; CHECK-7M-NEXT: add sp, #8
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test1:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: .pad #8
+; CHECK-8M-NEXT: sub sp, sp, #8
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: str r1, [sp]
+; CHECK-8M-NEXT: bl __atomic_fetch_add_8
+; CHECK-8M-NEXT: add sp, sp, #8
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw add ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test2(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test2:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE: subs [[REG3:(r[0-9]?[02468])]], [[REG1]]
-; CHECK-LE: sbc [[REG4:(r[0-9]?[13579])]], [[REG2]]
-; CHECK-BE: subs [[REG4:(r[0-9]?[13579])]], [[REG2]]
-; CHECK-BE: sbc [[REG3:(r[0-9]?[02468])]], [[REG1]]
-; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test2:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE: subs.w [[REG3:[a-z0-9]+]], [[REG1]]
-; CHECK-THUMB-LE: sbc.w [[REG4:[a-z0-9]+]], [[REG2]]
-; CHECK-THUMB-BE: subs.w [[REG4:[a-z0-9]+]], [[REG2]]
-; CHECK-THUMB-BE: sbc.w [[REG3:[a-z0-9]+]], [[REG1]]
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_fetch_sub_8
+; CHECK-LE-LABEL: test2:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB1_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: subs r6, r4, r1
+; CHECK-LE-NEXT: sbc r7, r5, r2
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB1_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-LE-LABEL: test2:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: mov r12, r0
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: .LBB1_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT: subs.w lr, r0, r2
+; CHECK-THUMB-LE-NEXT: sbc.w r4, r1, r3
+; CHECK-THUMB-LE-NEXT: strexd r5, lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB1_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test2:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB1_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: subs r7, r5, r2
+; CHECK-BE-NEXT: sbc r6, r4, r1
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB1_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test2:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: mov r12, r0
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: .LBB1_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT: subs.w lr, r1, r3
+; CHECK-THUMB-BE-NEXT: sbc.w r4, r0, r2
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB1_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-7M-LABEL: test2:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: .pad #8
+; CHECK-7M-NEXT: sub sp, #8
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: str r1, [sp]
+; CHECK-7M-NEXT: bl __atomic_fetch_sub_8
+; CHECK-7M-NEXT: add sp, #8
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test2:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: .pad #8
+; CHECK-8M-NEXT: sub sp, sp, #8
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: str r1, [sp]
+; CHECK-8M-NEXT: bl __atomic_fetch_sub_8
+; CHECK-8M-NEXT: add sp, sp, #8
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw sub ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test3(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test3:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]],
-; CHECK-LE-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]],
-; CHECK-BE-DAG: and [[REG4:(r[0-9]?[13579])]], [[REG2]],
-; CHECK-BE-DAG: and [[REG3:(r[0-9]?[02468])]], [[REG1]],
-; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
+; CHECK-LE-LABEL: test3:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB2_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: and r6, r4, r1
+; CHECK-LE-NEXT: and r7, r5, r2
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB2_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
; CHECK-THUMB-LABEL: test3:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]],
-; CHECK-THUMB-LE-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]],
-; CHECK-THUMB-BE-DAG: and.w [[REG4:[a-z0-9]+]], [[REG2]],
-; CHECK-THUMB-BE-DAG: and.w [[REG3:[a-z0-9]+]], [[REG1]],
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: _atomic_fetch_and_8
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: mov r12, r0
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: .LBB2_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-NEXT: and.w lr, r0, r2
+; CHECK-THUMB-NEXT: and.w r4, r1, r3
+; CHECK-THUMB-NEXT: strexd r5, lr, r4, [r12]
+; CHECK-THUMB-NEXT: cmp r5, #0
+; CHECK-THUMB-NEXT: bne .LBB2_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test3:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB2_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: and r6, r4, r1
+; CHECK-BE-NEXT: and r7, r5, r2
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB2_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-7M-LABEL: test3:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: .pad #8
+; CHECK-7M-NEXT: sub sp, #8
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: str r1, [sp]
+; CHECK-7M-NEXT: bl __atomic_fetch_and_8
+; CHECK-7M-NEXT: add sp, #8
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test3:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: .pad #8
+; CHECK-8M-NEXT: sub sp, sp, #8
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: str r1, [sp]
+; CHECK-8M-NEXT: bl __atomic_fetch_and_8
+; CHECK-8M-NEXT: add sp, sp, #8
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw and ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test4(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test4:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE-DAG: orr [[REG3:(r[0-9]?[02468])]], [[REG1]],
-; CHECK-LE-DAG: orr [[REG4:(r[0-9]?[13579])]], [[REG2]],
-; CHECK-BE-DAG: orr [[REG4:(r[0-9]?[13579])]], [[REG2]],
-; CHECK-BE-DAG: orr [[REG3:(r[0-9]?[02468])]], [[REG1]],
-; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
+; CHECK-LE-LABEL: test4:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB3_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: orr r6, r4, r1
+; CHECK-LE-NEXT: orr r7, r5, r2
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB3_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
; CHECK-THUMB-LABEL: test4:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE-DAG: orr.w [[REG3:[a-z0-9]+]], [[REG1]],
-; CHECK-THUMB-LE-DAG: orr.w [[REG4:[a-z0-9]+]], [[REG2]],
-; CHECK-THUMB-BE-DAG: orr.w [[REG4:[a-z0-9]+]], [[REG2]],
-; CHECK-THUMB-BE-DAG: orr.w [[REG3:[a-z0-9]+]], [[REG1]],
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_fetch_or_8
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: mov r12, r0
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: .LBB3_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-NEXT: orr.w lr, r0, r2
+; CHECK-THUMB-NEXT: orr.w r4, r1, r3
+; CHECK-THUMB-NEXT: strexd r5, lr, r4, [r12]
+; CHECK-THUMB-NEXT: cmp r5, #0
+; CHECK-THUMB-NEXT: bne .LBB3_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test4:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB3_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: orr r6, r4, r1
+; CHECK-BE-NEXT: orr r7, r5, r2
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB3_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-7M-LABEL: test4:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: .pad #8
+; CHECK-7M-NEXT: sub sp, #8
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: str r1, [sp]
+; CHECK-7M-NEXT: bl __atomic_fetch_or_8
+; CHECK-7M-NEXT: add sp, #8
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test4:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: .pad #8
+; CHECK-8M-NEXT: sub sp, sp, #8
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: str r1, [sp]
+; CHECK-8M-NEXT: bl __atomic_fetch_or_8
+; CHECK-8M-NEXT: add sp, sp, #8
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw or ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test5(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test5:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE-DAG: eor [[REG3:(r[0-9]?[02468])]], [[REG1]],
-; CHECK-LE-DAG: eor [[REG4:(r[0-9]?[13579])]], [[REG2]],
-; CHECK-BE-DAG: eor [[REG4:(r[0-9]?[13579])]], [[REG2]],
-; CHECK-BE-DAG: eor [[REG3:(r[0-9]?[02468])]], [[REG1]],
-; CHECK: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
+; CHECK-LE-LABEL: test5:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB4_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: eor r6, r4, r1
+; CHECK-LE-NEXT: eor r7, r5, r2
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB4_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
; CHECK-THUMB-LABEL: test5:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE-DAG: eor.w [[REG3:[a-z0-9]+]], [[REG1]],
-; CHECK-THUMB-LE-DAG: eor.w [[REG4:[a-z0-9]+]], [[REG2]],
-; CHECK-THUMB-BE-DAG: eor.w [[REG4:[a-z0-9]+]], [[REG2]],
-; CHECK-THUMB-BE-DAG: eor.w [[REG3:[a-z0-9]+]], [[REG1]],
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[REG3]], [[REG4]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_fetch_xor_8
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: mov r12, r0
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: .LBB4_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-NEXT: eor.w lr, r0, r2
+; CHECK-THUMB-NEXT: eor.w r4, r1, r3
+; CHECK-THUMB-NEXT: strexd r5, lr, r4, [r12]
+; CHECK-THUMB-NEXT: cmp r5, #0
+; CHECK-THUMB-NEXT: bne .LBB4_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test5:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB4_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: eor r6, r4, r1
+; CHECK-BE-NEXT: eor r7, r5, r2
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB4_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-7M-LABEL: test5:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: .pad #8
+; CHECK-7M-NEXT: sub sp, #8
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: str r1, [sp]
+; CHECK-7M-NEXT: bl __atomic_fetch_xor_8
+; CHECK-7M-NEXT: add sp, #8
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test5:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: .pad #8
+; CHECK-8M-NEXT: sub sp, sp, #8
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: str r1, [sp]
+; CHECK-8M-NEXT: bl __atomic_fetch_xor_8
+; CHECK-8M-NEXT: add sp, sp, #8
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw xor ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test6(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test6:
-; 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-LE-LABEL: test6:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r5, r2
+; CHECK-LE-NEXT: mov r2, r0
+; CHECK-LE-NEXT: mov r4, r1
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB5_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r0, r1, [r2]
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r2]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB5_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, pc}
+;
; CHECK-THUMB-LABEL: test6:
-; 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: @ %bb.0:
+; CHECK-THUMB-NEXT: .save {r7, lr}
+; CHECK-THUMB-NEXT: push {r7, lr}
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: .LBB5_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexd r12, r1, [r0]
+; CHECK-THUMB-NEXT: strexd lr, r2, r3, [r0]
+; CHECK-THUMB-NEXT: cmp.w lr, #0
+; CHECK-THUMB-NEXT: bne .LBB5_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r12
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: pop {r7, pc}
+;
+; CHECK-BE-LABEL: test6:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r5, r2
+; CHECK-BE-NEXT: mov r2, r0
+; CHECK-BE-NEXT: mov r4, r1
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB5_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r0, r1, [r2]
+; CHECK-BE-NEXT: strexd r3, r4, r5, [r2]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB5_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, pc}
+;
+; CHECK-7M-LABEL: test6:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: .pad #8
+; CHECK-7M-NEXT: sub sp, #8
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: str r1, [sp]
+; CHECK-7M-NEXT: bl __atomic_exchange_8
+; CHECK-7M-NEXT: add sp, #8
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test6:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: .pad #8
+; CHECK-8M-NEXT: sub sp, sp, #8
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: str r1, [sp]
+; CHECK-8M-NEXT: bl __atomic_exchange_8
+; CHECK-8M-NEXT: add sp, sp, #8
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
-; CHECK-M: __atomic_exchange_8
%r = atomicrmw xchg ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test7(ptr %ptr, i64 %val1, i64 %val2) {
-; CHECK-LABEL: test7:
-; CHECK-DAG: mov [[VAL1LO:r[0-9]+]], r1
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-LE-DAG: eor [[MISMATCH_LO:.*]], [[REG1]], [[VAL1LO]]
-; CHECK-LE-DAG: eor [[MISMATCH_HI:.*]], [[REG2]], r2
-; CHECK-BE-DAG: eor [[MISMATCH_LO:.*]], [[REG2]], r2
-; CHECK-BE-DAG: eor [[MISMATCH_HI:.*]], [[REG1]], r1
-; CHECK: orrs {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
-; CHECK: bne
-; CHECK-DAG: dmb {{ish$}}
-; CHECK: strexd {{[a-z0-9]+}}, {{r[0-9]?[02468]}}, {{r[0-9]?[13579]}}
-; CHECK: cmp
-; CHECK: beq
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test7:
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-LE-DAG: eor.w [[MISMATCH_LO:[a-z0-9]+]], [[REG1]], r2
-; CHECK-THUMB-LE-DAG: eor.w [[MISMATCH_HI:[a-z0-9]+]], [[REG2]], r3
-; CHECK-THUMB-BE-DAG: eor.w [[MISMATCH_HI:[a-z0-9]+]], [[REG1]], r2
-; CHECK-THUMB-BE-DAG: eor.w [[MISMATCH_LO:[a-z0-9]+]], [[REG2]], r3
-; CHECK-THUMB-LE: orrs.w {{.*}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, {{[a-z0-9]+}}, {{[a-z0-9]+}}
-; CHECK-THUMB: cmp
-; CHECK-THUMB: beq
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_compare_exchange_8
+; CHECK-LE-LABEL: test7:
+; CHECK-LE: @ %bb.0: @ %cmpxchg.start
+; CHECK-LE-NEXT: push {r4, r6, r10, r11, lr}
+; CHECK-LE-NEXT: mov r10, r3
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r3, r0
+; CHECK-LE-NEXT: ldrexd r0, r1, [r0]
+; CHECK-LE-NEXT: eor r12, r1, r2
+; CHECK-LE-NEXT: eor r4, r0, r9
+; CHECK-LE-NEXT: orrs r4, r4, r12
+; CHECK-LE-NEXT: bne LBB6_4
+; CHECK-LE-NEXT: @ %bb.1: @ %cmpxchg.fencedstore
+; CHECK-LE-NEXT: ldr r11, [sp, #20]
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB6_2: @ %cmpxchg.trystore
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: strexd r4, r10, r11, [r3]
+; CHECK-LE-NEXT: cmp r4, #0
+; CHECK-LE-NEXT: beq LBB6_5
+; CHECK-LE-NEXT: @ %bb.3: @ %cmpxchg.releasedload
+; CHECK-LE-NEXT: @ in Loop: Header=BB6_2 Depth=1
+; CHECK-LE-NEXT: ldrexd r0, r1, [r3]
+; CHECK-LE-NEXT: eor r4, r0, r9
+; CHECK-LE-NEXT: eor r6, r1, r2
+; CHECK-LE-NEXT: orrs r6, r4, r6
+; CHECK-LE-NEXT: beq LBB6_2
+; CHECK-LE-NEXT: LBB6_4: @ %cmpxchg.nostore
+; CHECK-LE-NEXT: clrex
+; CHECK-LE-NEXT: LBB6_5: @ %cmpxchg.end
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r6, r10, r11, pc}
+;
+; CHECK-THUMB-LE-LABEL: test7:
+; CHECK-THUMB-LE: @ %bb.0: @ %cmpxchg.start
+; CHECK-THUMB-LE-NEXT: .save {r4, r5, r6, lr}
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r6, lr}
+; CHECK-THUMB-LE-NEXT: mov r12, r0
+; CHECK-THUMB-LE-NEXT: ldrexd r0, r1, [r0]
+; CHECK-THUMB-LE-NEXT: eor.w lr, r1, r3
+; CHECK-THUMB-LE-NEXT: eor.w r4, r0, r2
+; CHECK-THUMB-LE-NEXT: orrs.w r4, r4, lr
+; CHECK-THUMB-LE-NEXT: bne .LBB6_4
+; CHECK-THUMB-LE-NEXT: @ %bb.1: @ %cmpxchg.fencedstore
+; CHECK-THUMB-LE-NEXT: ldrd r4, lr, [sp, #16]
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: .LBB6_2: @ %cmpxchg.trystore
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-LE-NEXT: cbz r5, .LBB6_5
+; CHECK-THUMB-LE-NEXT: @ %bb.3: @ %cmpxchg.releasedload
+; CHECK-THUMB-LE-NEXT: @ in Loop: Header=BB6_2 Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT: eor.w r5, r0, r2
+; CHECK-THUMB-LE-NEXT: eor.w r6, r1, r3
+; CHECK-THUMB-LE-NEXT: orrs r5, r6
+; CHECK-THUMB-LE-NEXT: beq .LBB6_2
+; CHECK-THUMB-LE-NEXT: .LBB6_4: @ %cmpxchg.nostore
+; CHECK-THUMB-LE-NEXT: clrex
+; CHECK-THUMB-LE-NEXT: .LBB6_5: @ %cmpxchg.end
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r6, pc}
+;
+; CHECK-BE-LABEL: test7:
+; CHECK-BE: @ %bb.0: @ %cmpxchg.start
+; CHECK-BE-NEXT: push {r4, r6, r8, r9, lr}
+; CHECK-BE-NEXT: mov r8, r3
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov r3, r0
+; CHECK-BE-NEXT: ldrexd r0, r1, [r0]
+; CHECK-BE-NEXT: eor lr, r0, r12
+; CHECK-BE-NEXT: eor r6, r1, r2
+; CHECK-BE-NEXT: orrs r6, r6, lr
+; CHECK-BE-NEXT: bne .LBB6_4
+; CHECK-BE-NEXT: @ %bb.1: @ %cmpxchg.fencedstore
+; CHECK-BE-NEXT: ldr r9, [sp, #20]
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB6_2: @ %cmpxchg.trystore
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: strexd r6, r8, r9, [r3]
+; CHECK-BE-NEXT: cmp r6, #0
+; CHECK-BE-NEXT: beq .LBB6_5
+; CHECK-BE-NEXT: @ %bb.3: @ %cmpxchg.releasedload
+; CHECK-BE-NEXT: @ in Loop: Header=BB6_2 Depth=1
+; CHECK-BE-NEXT: ldrexd r0, r1, [r3]
+; CHECK-BE-NEXT: eor r6, r0, r12
+; CHECK-BE-NEXT: eor r4, r1, r2
+; CHECK-BE-NEXT: orrs r6, r4, r6
+; CHECK-BE-NEXT: beq .LBB6_2
+; CHECK-BE-NEXT: .LBB6_4: @ %cmpxchg.nostore
+; CHECK-BE-NEXT: clrex
+; CHECK-BE-NEXT: .LBB6_5: @ %cmpxchg.end
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r6, r8, r9, pc}
+;
+; CHECK-THUMB-BE-LABEL: test7:
+; CHECK-THUMB-BE: @ %bb.0: @ %cmpxchg.start
+; CHECK-THUMB-BE-NEXT: .save {r4, r5, r6, lr}
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r6, lr}
+; CHECK-THUMB-BE-NEXT: mov r12, r0
+; CHECK-THUMB-BE-NEXT: ldrexd r0, r1, [r0]
+; CHECK-THUMB-BE-NEXT: eor.w lr, r0, r2
+; CHECK-THUMB-BE-NEXT: eor.w r4, r1, r3
+; CHECK-THUMB-BE-NEXT: orrs.w r4, r4, lr
+; CHECK-THUMB-BE-NEXT: bne .LBB6_4
+; CHECK-THUMB-BE-NEXT: @ %bb.1: @ %cmpxchg.fencedstore
+; CHECK-THUMB-BE-NEXT: ldrd r4, lr, [sp, #16]
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: .LBB6_2: @ %cmpxchg.trystore
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cbz r5, .LBB6_5
+; CHECK-THUMB-BE-NEXT: @ %bb.3: @ %cmpxchg.releasedload
+; CHECK-THUMB-BE-NEXT: @ in Loop: Header=BB6_2 Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT: eor.w r5, r0, r2
+; CHECK-THUMB-BE-NEXT: eor.w r6, r1, r3
+; CHECK-THUMB-BE-NEXT: orrs r5, r6
+; CHECK-THUMB-BE-NEXT: beq .LBB6_2
+; CHECK-THUMB-BE-NEXT: .LBB6_4: @ %cmpxchg.nostore
+; CHECK-THUMB-BE-NEXT: clrex
+; CHECK-THUMB-BE-NEXT: .LBB6_5: @ %cmpxchg.end
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r6, pc}
+;
+; CHECK-7M-LABEL: test7:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: .pad #16
+; CHECK-7M-NEXT: sub sp, #16
+; CHECK-7M-NEXT: strd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: ldrd r2, r3, [sp, #24]
+; CHECK-7M-NEXT: strd r1, r1, [sp]
+; CHECK-7M-NEXT: add r1, sp, #8
+; CHECK-7M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-7M-NEXT: ldrd r0, r1, [sp, #8]
+; CHECK-7M-NEXT: add sp, #16
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test7:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: .pad #16
+; CHECK-8M-NEXT: sub sp, sp, #16
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: str r3, [sp, #12]
+; CHECK-8M-NEXT: str r2, [sp, #8]
+; CHECK-8M-NEXT: ldr r2, [sp, #24]
+; CHECK-8M-NEXT: ldr r3, [sp, #28]
+; CHECK-8M-NEXT: str r1, [sp]
+; CHECK-8M-NEXT: str r1, [sp, #4]
+; CHECK-8M-NEXT: add r1, sp, #8
+; CHECK-8M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-8M-NEXT: ldr r0, [sp, #8]
+; CHECK-8M-NEXT: ldr r1, [sp, #12]
+; CHECK-8M-NEXT: add sp, sp, #16
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%pair = cmpxchg ptr %ptr, i64 %val1, i64 %val2 seq_cst seq_cst
%r = extractvalue { i64, i1 } %pair, 0
@@ -224,20 +727,37 @@ define i64 @test7(ptr %ptr, i64 %val1, i64 %val2) {
; isn't supported.
define i64 @test8(ptr %ptr) {
; CHECK-LABEL: test8:
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK-NOT: strexd
-; CHECK: clrex
-; CHECK-NOT: strexd
-; CHECK: dmb {{ish$}}
-
+; CHECK: @ %bb.0:
+; CHECK-NEXT: ldrexd r0, r1, [r0]
+; CHECK-NEXT: clrex
+; CHECK-NEXT: dmb ish
+; CHECK-NEXT: bx lr
+;
; CHECK-THUMB-LABEL: test8:
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB-NOT: strexd
-; CHECK-THUMB: clrex
-; CHECK-THUMB-NOT: strexd
-; CHECK-THUMB: dmb {{ish$}}
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: ldrexd r0, r1, [r0]
+; CHECK-THUMB-NEXT: clrex
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-7M-LABEL: test8:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: bl __atomic_load_8
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test8:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: bl __atomic_load_8
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
-; CHECK-M: __atomic_load_8
%r = load atomic i64, ptr %ptr seq_cst, align 8
ret i64 %r
@@ -247,203 +767,825 @@ define i64 @test8(ptr %ptr) {
; way to write it. Except on M class devices, where ldrexd/strexd aren't
; supported.
define void @test9(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test9:
-; 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-LE-LABEL: test9:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r3, r2
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: mov r2, r1
+; CHECK-LE-NEXT: LBB8_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: strexd r1, r2, r3, [r0]
+; CHECK-LE-NEXT: cmp r1, #0
+; CHECK-LE-NEXT: bne LBB8_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, pc}
+;
; CHECK-THUMB-LABEL: test9:
-; 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: @ %bb.0:
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: .LBB8_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexd r1, r12, [r0]
+; CHECK-THUMB-NEXT: strexd r1, r2, r3, [r0]
+; CHECK-THUMB-NEXT: cmp r1, #0
+; CHECK-THUMB-NEXT: bne .LBB8_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: bx lr
+;
+; CHECK-BE-LABEL: test9:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r3, r2
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: mov r2, r1
+; CHECK-BE-NEXT: .LBB8_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: strexd r1, r2, r3, [r0]
+; CHECK-BE-NEXT: cmp r1, #0
+; CHECK-BE-NEXT: bne .LBB8_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, pc}
+;
+; CHECK-7M-LABEL: test9:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r7, lr}
+; CHECK-7M-NEXT: push {r7, lr}
+; CHECK-7M-NEXT: .pad #8
+; CHECK-7M-NEXT: sub sp, #8
+; CHECK-7M-NEXT: movs r1, #5
+; CHECK-7M-NEXT: str r1, [sp]
+; CHECK-7M-NEXT: bl __atomic_store_8
+; CHECK-7M-NEXT: add sp, #8
+; CHECK-7M-NEXT: pop {r7, pc}
+;
+; CHECK-8M-LABEL: test9:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r11, lr}
+; CHECK-8M-NEXT: push {r11, lr}
+; CHECK-8M-NEXT: .pad #8
+; CHECK-8M-NEXT: sub sp, sp, #8
+; CHECK-8M-NEXT: mov r1, #5
+; CHECK-8M-NEXT: str r1, [sp]
+; CHECK-8M-NEXT: bl __atomic_store_8
+; CHECK-8M-NEXT: add sp, sp, #8
+; CHECK-8M-NEXT: pop {r11, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
-; CHECK-M: __atomic_store_8
store atomic i64 %val, ptr %ptr seq_cst, align 8
ret void
}
define i64 @test10(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test10:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
-; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
-; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
-; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
-; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
-; CHECK: mov [[CMP:[a-z0-9]+]], #0
-; CHECK: movwge [[CMP]], #1
-; CHECK: cmp [[CMP]], #0
-; CHECK: movne [[OUT_HI]], [[REG2]]
-; CHECK: mov [[OUT_LO:[a-z0-9]+]], r1
-; CHECK: movne [[OUT_LO]], [[REG1]]
-; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test10:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
-; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
-; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
-; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
-; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
-; CHECK-THUMB: mov.w [[CMP:[a-z0-9]+]], #0
-; CHECK-THUMB: movge.w [[CMP]], #1
-; CHECK-THUMB: cmp.w [[CMP]], #0
-; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
-; CHECK-THUMB: movne [[OUT_HI]], [[REG2]]
-; CHECK-THUMB: movne [[OUT_LO]], [[REG1]]
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_compare_exchange_8
+; CHECK-LE-LABEL: test10:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB9_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: mov r7, r2
+; CHECK-LE-NEXT: subs r3, r1, r4
+; CHECK-LE-NEXT: sbcs r3, r2, r5
+; CHECK-LE-NEXT: mov r3, #0
+; CHECK-LE-NEXT: movwge r3, #1
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: movne r7, r5
+; CHECK-LE-NEXT: mov r6, r1
+; CHECK-LE-NEXT: movne r6, r4
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB9_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-LE-LABEL: test10:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: mov r12, r0
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: .LBB9_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT: mov r4, r2
+; CHECK-THUMB-LE-NEXT: subs.w lr, r2, r0
+; CHECK-THUMB-LE-NEXT: sbcs.w lr, r3, r1
+; CHECK-THUMB-LE-NEXT: mov.w lr, #0
+; CHECK-THUMB-LE-NEXT: it ge
+; CHECK-THUMB-LE-NEXT: movge.w lr, #1
+; CHECK-THUMB-LE-NEXT: cmp.w lr, #0
+; CHECK-THUMB-LE-NEXT: mov lr, r3
+; CHECK-THUMB-LE-NEXT: itt ne
+; CHECK-THUMB-LE-NEXT: movne lr, r1
+; CHECK-THUMB-LE-NEXT: movne r4, r0
+; CHECK-THUMB-LE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB9_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test10:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB9_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: mov r7, r2
+; CHECK-BE-NEXT: subs r3, r2, r5
+; CHECK-BE-NEXT: sbcs r3, r1, r4
+; CHECK-BE-NEXT: mov r3, #0
+; CHECK-BE-NEXT: movwge r3, #1
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: movne r7, r5
+; CHECK-BE-NEXT: mov r6, r1
+; CHECK-BE-NEXT: movne r6, r4
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB9_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test10:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: mov r12, r0
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: .LBB9_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT: mov r4, r2
+; CHECK-THUMB-BE-NEXT: subs.w lr, r3, r1
+; CHECK-THUMB-BE-NEXT: sbcs.w lr, r2, r0
+; CHECK-THUMB-BE-NEXT: mov.w lr, #0
+; CHECK-THUMB-BE-NEXT: it ge
+; CHECK-THUMB-BE-NEXT: movge.w lr, #1
+; CHECK-THUMB-BE-NEXT: cmp.w lr, #0
+; CHECK-THUMB-BE-NEXT: mov lr, r3
+; CHECK-THUMB-BE-NEXT: itt ne
+; CHECK-THUMB-BE-NEXT: movne lr, r1
+; CHECK-THUMB-BE-NEXT: movne r4, r0
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB9_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-7M-LABEL: test10:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r4, r5, r6, r7, r8, lr}
+; CHECK-7M-NEXT: push.w {r4, r5, r6, r7, r8, lr}
+; CHECK-7M-NEXT: .pad #16
+; CHECK-7M-NEXT: sub sp, #16
+; CHECK-7M-NEXT: mov r4, r3
+; CHECK-7M-NEXT: mov r5, r2
+; CHECK-7M-NEXT: ldrd r2, r3, [r0]
+; CHECK-7M-NEXT: add.w r8, sp, #8
+; CHECK-7M-NEXT: mov r6, r0
+; CHECK-7M-NEXT: movs r7, #5
+; CHECK-7M-NEXT: .LBB9_1: @ %atomicrmw.start
+; CHECK-7M-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-7M-NEXT: subs r0, r5, r2
+; CHECK-7M-NEXT: strd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: sbcs.w r0, r4, r3
+; CHECK-7M-NEXT: strd r7, r7, [sp]
+; CHECK-7M-NEXT: mov.w r0, #0
+; CHECK-7M-NEXT: mov r1, r8
+; CHECK-7M-NEXT: it ge
+; CHECK-7M-NEXT: movge r0, #1
+; CHECK-7M-NEXT: cmp r0, #0
+; CHECK-7M-NEXT: mov r0, r6
+; CHECK-7M-NEXT: itt eq
+; CHECK-7M-NEXT: moveq r2, r5
+; CHECK-7M-NEXT: moveq r3, r4
+; CHECK-7M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-7M-NEXT: ldrd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: cmp r0, #0
+; CHECK-7M-NEXT: beq .LBB9_1
+; CHECK-7M-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-7M-NEXT: mov r0, r2
+; CHECK-7M-NEXT: mov r1, r3
+; CHECK-7M-NEXT: add sp, #16
+; CHECK-7M-NEXT: pop.w {r4, r5, r6, r7, r8, pc}
+;
+; CHECK-8M-LABEL: test10:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: push {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: .pad #16
+; CHECK-8M-NEXT: sub sp, sp, #16
+; CHECK-8M-NEXT: add r8, sp, #8
+; CHECK-8M-NEXT: mov r4, r3
+; CHECK-8M-NEXT: mov r5, r2
+; CHECK-8M-NEXT: mov r6, r0
+; CHECK-8M-NEXT: ldm r0, {r2, r3}
+; CHECK-8M-NEXT: mov r7, #5
+; CHECK-8M-NEXT: .LBB9_1: @ %atomicrmw.start
+; CHECK-8M-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-8M-NEXT: subs r0, r5, r2
+; CHECK-8M-NEXT: str r2, [sp, #8]
+; CHECK-8M-NEXT: sbcs r0, r4, r3
+; CHECK-8M-NEXT: str r3, [sp, #12]
+; CHECK-8M-NEXT: mov r0, #0
+; CHECK-8M-NEXT: mov r1, r8
+; CHECK-8M-NEXT: movge r0, #1
+; CHECK-8M-NEXT: cmp r0, #0
+; CHECK-8M-NEXT: moveq r2, r5
+; CHECK-8M-NEXT: moveq r3, r4
+; CHECK-8M-NEXT: mov r0, r6
+; CHECK-8M-NEXT: str r7, [sp]
+; CHECK-8M-NEXT: str r7, [sp, #4]
+; CHECK-8M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-8M-NEXT: ldr r2, [sp, #8]
+; CHECK-8M-NEXT: cmp r0, #0
+; CHECK-8M-NEXT: ldr r3, [sp, #12]
+; CHECK-8M-NEXT: beq .LBB9_1
+; CHECK-8M-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-8M-NEXT: mov r0, r2
+; CHECK-8M-NEXT: mov r1, r3
+; CHECK-8M-NEXT: add sp, sp, #16
+; CHECK-8M-NEXT: pop {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw min ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test11(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test11:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
-; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
-; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
-; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
-; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
-; CHECK: mov [[CMP:[a-z0-9]+]], #0
-; CHECK: movwhs [[CMP]], #1
-; CHECK: cmp [[CMP]], #0
-; CHECK: movne [[OUT_HI]], [[REG2]]
-; CHECK: mov [[OUT_LO:[a-z0-9]+]], r1
-; CHECK: movne [[OUT_LO]], [[REG1]]
-; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test11:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
-; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
-; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
-; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
-; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
-; CHECK-THUMB: mov.w [[CMP:[a-z0-9]+]], #0
-; CHECK-THUMB: movhs.w [[CMP]], #1
-; CHECK-THUMB: cmp.w [[CMP]], #0
-; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
-; CHECK-THUMB: movne [[OUT_HI]], [[REG2]]
-; CHECK-THUMB: movne [[OUT_LO]], [[REG1]]
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_compare_exchange_8
+; CHECK-LE-LABEL: test11:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB10_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: mov r7, r2
+; CHECK-LE-NEXT: subs r3, r1, r4
+; CHECK-LE-NEXT: sbcs r3, r2, r5
+; CHECK-LE-NEXT: mov r3, #0
+; CHECK-LE-NEXT: movwhs r3, #1
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: movne r7, r5
+; CHECK-LE-NEXT: mov r6, r1
+; CHECK-LE-NEXT: movne r6, r4
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB10_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-LE-LABEL: test11:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: mov r12, r0
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: .LBB10_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT: mov r4, r2
+; CHECK-THUMB-LE-NEXT: subs.w lr, r2, r0
+; CHECK-THUMB-LE-NEXT: sbcs.w lr, r3, r1
+; CHECK-THUMB-LE-NEXT: mov.w lr, #0
+; CHECK-THUMB-LE-NEXT: it hs
+; CHECK-THUMB-LE-NEXT: movhs.w lr, #1
+; CHECK-THUMB-LE-NEXT: cmp.w lr, #0
+; CHECK-THUMB-LE-NEXT: mov lr, r3
+; CHECK-THUMB-LE-NEXT: itt ne
+; CHECK-THUMB-LE-NEXT: movne lr, r1
+; CHECK-THUMB-LE-NEXT: movne r4, r0
+; CHECK-THUMB-LE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB10_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test11:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB10_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: mov r7, r2
+; CHECK-BE-NEXT: subs r3, r2, r5
+; CHECK-BE-NEXT: sbcs r3, r1, r4
+; CHECK-BE-NEXT: mov r3, #0
+; CHECK-BE-NEXT: movwhs r3, #1
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: movne r7, r5
+; CHECK-BE-NEXT: mov r6, r1
+; CHECK-BE-NEXT: movne r6, r4
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB10_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test11:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: mov r12, r0
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: .LBB10_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT: mov r4, r2
+; CHECK-THUMB-BE-NEXT: subs.w lr, r3, r1
+; CHECK-THUMB-BE-NEXT: sbcs.w lr, r2, r0
+; CHECK-THUMB-BE-NEXT: mov.w lr, #0
+; CHECK-THUMB-BE-NEXT: it hs
+; CHECK-THUMB-BE-NEXT: movhs.w lr, #1
+; CHECK-THUMB-BE-NEXT: cmp.w lr, #0
+; CHECK-THUMB-BE-NEXT: mov lr, r3
+; CHECK-THUMB-BE-NEXT: itt ne
+; CHECK-THUMB-BE-NEXT: movne lr, r1
+; CHECK-THUMB-BE-NEXT: movne r4, r0
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB10_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-7M-LABEL: test11:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r4, r5, r6, r7, r8, lr}
+; CHECK-7M-NEXT: push.w {r4, r5, r6, r7, r8, lr}
+; CHECK-7M-NEXT: .pad #16
+; CHECK-7M-NEXT: sub sp, #16
+; CHECK-7M-NEXT: mov r4, r3
+; CHECK-7M-NEXT: mov r5, r2
+; CHECK-7M-NEXT: ldrd r2, r3, [r0]
+; CHECK-7M-NEXT: add.w r8, sp, #8
+; CHECK-7M-NEXT: mov r6, r0
+; CHECK-7M-NEXT: movs r7, #5
+; CHECK-7M-NEXT: .LBB10_1: @ %atomicrmw.start
+; CHECK-7M-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-7M-NEXT: subs r0, r5, r2
+; CHECK-7M-NEXT: strd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: sbcs.w r0, r4, r3
+; CHECK-7M-NEXT: strd r7, r7, [sp]
+; CHECK-7M-NEXT: mov.w r0, #0
+; CHECK-7M-NEXT: mov r1, r8
+; CHECK-7M-NEXT: it hs
+; CHECK-7M-NEXT: movhs r0, #1
+; CHECK-7M-NEXT: cmp r0, #0
+; CHECK-7M-NEXT: mov r0, r6
+; CHECK-7M-NEXT: itt eq
+; CHECK-7M-NEXT: moveq r2, r5
+; CHECK-7M-NEXT: moveq r3, r4
+; CHECK-7M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-7M-NEXT: ldrd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: cmp r0, #0
+; CHECK-7M-NEXT: beq .LBB10_1
+; CHECK-7M-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-7M-NEXT: mov r0, r2
+; CHECK-7M-NEXT: mov r1, r3
+; CHECK-7M-NEXT: add sp, #16
+; CHECK-7M-NEXT: pop.w {r4, r5, r6, r7, r8, pc}
+;
+; CHECK-8M-LABEL: test11:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: push {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: .pad #16
+; CHECK-8M-NEXT: sub sp, sp, #16
+; CHECK-8M-NEXT: add r8, sp, #8
+; CHECK-8M-NEXT: mov r4, r3
+; CHECK-8M-NEXT: mov r5, r2
+; CHECK-8M-NEXT: mov r6, r0
+; CHECK-8M-NEXT: ldm r0, {r2, r3}
+; CHECK-8M-NEXT: mov r7, #5
+; CHECK-8M-NEXT: .LBB10_1: @ %atomicrmw.start
+; CHECK-8M-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-8M-NEXT: subs r0, r5, r2
+; CHECK-8M-NEXT: str r2, [sp, #8]
+; CHECK-8M-NEXT: sbcs r0, r4, r3
+; CHECK-8M-NEXT: str r3, [sp, #12]
+; CHECK-8M-NEXT: mov r0, #0
+; CHECK-8M-NEXT: mov r1, r8
+; CHECK-8M-NEXT: movhs r0, #1
+; CHECK-8M-NEXT: cmp r0, #0
+; CHECK-8M-NEXT: moveq r2, r5
+; CHECK-8M-NEXT: moveq r3, r4
+; CHECK-8M-NEXT: mov r0, r6
+; CHECK-8M-NEXT: str r7, [sp]
+; CHECK-8M-NEXT: str r7, [sp, #4]
+; CHECK-8M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-8M-NEXT: ldr r2, [sp, #8]
+; CHECK-8M-NEXT: cmp r0, #0
+; CHECK-8M-NEXT: ldr r3, [sp, #12]
+; CHECK-8M-NEXT: beq .LBB10_1
+; CHECK-8M-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-8M-NEXT: mov r0, r2
+; CHECK-8M-NEXT: mov r1, r3
+; CHECK-8M-NEXT: add sp, sp, #16
+; CHECK-8M-NEXT: pop {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw umin ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test12(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test12:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
-; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
-; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
-; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
-; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
-; CHECK: mov [[CMP:[a-z0-9]+]], #0
-; CHECK: movwlt [[CMP]], #1
-; CHECK: cmp [[CMP]], #0
-; CHECK: movne [[OUT_HI]], [[REG2]]
-; CHECK: mov [[OUT_LO:[a-z0-9]+]], r1
-; CHECK: movne [[OUT_LO]], [[REG1]]
-; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test12:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
-; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
-; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
-; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
-; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
-; CHECK-THUMB: mov.w [[CMP:[a-z0-9]+]], #0
-; CHECK-THUMB: movlt.w [[CMP]], #1
-; CHECK-THUMB: cmp.w [[CMP]], #0
-; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
-; CHECK-THUMB: movne [[OUT_HI]], [[REG2]]
-; CHECK-THUMB: movne [[OUT_LO]], [[REG1]]
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_compare_exchange_8
+; CHECK-LE-LABEL: test12:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB11_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: mov r7, r2
+; CHECK-LE-NEXT: subs r3, r1, r4
+; CHECK-LE-NEXT: sbcs r3, r2, r5
+; CHECK-LE-NEXT: mov r3, #0
+; CHECK-LE-NEXT: movwlt r3, #1
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: movne r7, r5
+; CHECK-LE-NEXT: mov r6, r1
+; CHECK-LE-NEXT: movne r6, r4
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB11_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-LE-LABEL: test12:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: mov r12, r0
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: .LBB11_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT: mov r4, r2
+; CHECK-THUMB-LE-NEXT: subs.w lr, r2, r0
+; CHECK-THUMB-LE-NEXT: sbcs.w lr, r3, r1
+; CHECK-THUMB-LE-NEXT: mov.w lr, #0
+; CHECK-THUMB-LE-NEXT: it lt
+; CHECK-THUMB-LE-NEXT: movlt.w lr, #1
+; CHECK-THUMB-LE-NEXT: cmp.w lr, #0
+; CHECK-THUMB-LE-NEXT: mov lr, r3
+; CHECK-THUMB-LE-NEXT: itt ne
+; CHECK-THUMB-LE-NEXT: movne lr, r1
+; CHECK-THUMB-LE-NEXT: movne r4, r0
+; CHECK-THUMB-LE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB11_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test12:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB11_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: mov r7, r2
+; CHECK-BE-NEXT: subs r3, r2, r5
+; CHECK-BE-NEXT: sbcs r3, r1, r4
+; CHECK-BE-NEXT: mov r3, #0
+; CHECK-BE-NEXT: movwlt r3, #1
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: movne r7, r5
+; CHECK-BE-NEXT: mov r6, r1
+; CHECK-BE-NEXT: movne r6, r4
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB11_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test12:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: mov r12, r0
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: .LBB11_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT: mov r4, r2
+; CHECK-THUMB-BE-NEXT: subs.w lr, r3, r1
+; CHECK-THUMB-BE-NEXT: sbcs.w lr, r2, r0
+; CHECK-THUMB-BE-NEXT: mov.w lr, #0
+; CHECK-THUMB-BE-NEXT: it lt
+; CHECK-THUMB-BE-NEXT: movlt.w lr, #1
+; CHECK-THUMB-BE-NEXT: cmp.w lr, #0
+; CHECK-THUMB-BE-NEXT: mov lr, r3
+; CHECK-THUMB-BE-NEXT: itt ne
+; CHECK-THUMB-BE-NEXT: movne lr, r1
+; CHECK-THUMB-BE-NEXT: movne r4, r0
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB11_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-7M-LABEL: test12:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r4, r5, r6, r7, r8, lr}
+; CHECK-7M-NEXT: push.w {r4, r5, r6, r7, r8, lr}
+; CHECK-7M-NEXT: .pad #16
+; CHECK-7M-NEXT: sub sp, #16
+; CHECK-7M-NEXT: mov r4, r3
+; CHECK-7M-NEXT: mov r5, r2
+; CHECK-7M-NEXT: ldrd r2, r3, [r0]
+; CHECK-7M-NEXT: add.w r8, sp, #8
+; CHECK-7M-NEXT: mov r6, r0
+; CHECK-7M-NEXT: movs r7, #5
+; CHECK-7M-NEXT: .LBB11_1: @ %atomicrmw.start
+; CHECK-7M-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-7M-NEXT: subs r0, r5, r2
+; CHECK-7M-NEXT: strd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: sbcs.w r0, r4, r3
+; CHECK-7M-NEXT: strd r7, r7, [sp]
+; CHECK-7M-NEXT: mov.w r0, #0
+; CHECK-7M-NEXT: mov r1, r8
+; CHECK-7M-NEXT: it lt
+; CHECK-7M-NEXT: movlt r0, #1
+; CHECK-7M-NEXT: cmp r0, #0
+; CHECK-7M-NEXT: mov r0, r6
+; CHECK-7M-NEXT: itt eq
+; CHECK-7M-NEXT: moveq r2, r5
+; CHECK-7M-NEXT: moveq r3, r4
+; CHECK-7M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-7M-NEXT: ldrd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: cmp r0, #0
+; CHECK-7M-NEXT: beq .LBB11_1
+; CHECK-7M-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-7M-NEXT: mov r0, r2
+; CHECK-7M-NEXT: mov r1, r3
+; CHECK-7M-NEXT: add sp, #16
+; CHECK-7M-NEXT: pop.w {r4, r5, r6, r7, r8, pc}
+;
+; CHECK-8M-LABEL: test12:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: push {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: .pad #16
+; CHECK-8M-NEXT: sub sp, sp, #16
+; CHECK-8M-NEXT: add r8, sp, #8
+; CHECK-8M-NEXT: mov r4, r3
+; CHECK-8M-NEXT: mov r5, r2
+; CHECK-8M-NEXT: mov r6, r0
+; CHECK-8M-NEXT: ldm r0, {r2, r3}
+; CHECK-8M-NEXT: mov r7, #5
+; CHECK-8M-NEXT: .LBB11_1: @ %atomicrmw.start
+; CHECK-8M-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-8M-NEXT: subs r0, r5, r2
+; CHECK-8M-NEXT: str r2, [sp, #8]
+; CHECK-8M-NEXT: sbcs r0, r4, r3
+; CHECK-8M-NEXT: str r3, [sp, #12]
+; CHECK-8M-NEXT: mov r0, #0
+; CHECK-8M-NEXT: mov r1, r8
+; CHECK-8M-NEXT: movlt r0, #1
+; CHECK-8M-NEXT: cmp r0, #0
+; CHECK-8M-NEXT: moveq r2, r5
+; CHECK-8M-NEXT: moveq r3, r4
+; CHECK-8M-NEXT: mov r0, r6
+; CHECK-8M-NEXT: str r7, [sp]
+; CHECK-8M-NEXT: str r7, [sp, #4]
+; CHECK-8M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-8M-NEXT: ldr r2, [sp, #8]
+; CHECK-8M-NEXT: cmp r0, #0
+; CHECK-8M-NEXT: ldr r3, [sp, #12]
+; CHECK-8M-NEXT: beq .LBB11_1
+; CHECK-8M-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-8M-NEXT: mov r0, r2
+; CHECK-8M-NEXT: mov r1, r3
+; CHECK-8M-NEXT: add sp, sp, #16
+; CHECK-8M-NEXT: pop {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw max ptr %ptr, i64 %val seq_cst
ret i64 %r
}
define i64 @test13(ptr %ptr, i64 %val) {
-; CHECK-LABEL: test13:
-; CHECK: dmb {{ish$}}
-; CHECK: ldrexd [[REG1:(r[0-9]?[02468])]], [[REG2:(r[0-9]?[13579])]]
-; CHECK: mov [[OUT_HI:[a-z0-9]+]], r2
-; CHECK-LE: subs {{[^,]+}}, r1, [[REG1]]
-; CHECK-BE: subs {{[^,]+}}, r2, [[REG2]]
-; CHECK-LE: sbcs {{[^,]+}}, r2, [[REG2]]
-; CHECK-BE: sbcs {{[^,]+}}, r1, [[REG1]]
-; CHECK: mov [[CMP:[a-z0-9]+]], #0
-; CHECK: movwlo [[CMP]], #1
-; CHECK: cmp [[CMP]], #0
-; CHECK: movne [[OUT_HI]], [[REG2]]
-; CHECK: mov [[OUT_LO:[a-z0-9]+]], r1
-; CHECK: movne [[OUT_LO]], [[REG1]]
-; CHECK: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
-; CHECK: cmp
-; CHECK: bne
-; CHECK: dmb {{ish$}}
-
-; CHECK-THUMB-LABEL: test13:
-; CHECK-THUMB: dmb {{ish$}}
-; CHECK-THUMB: ldrexd [[REG1:[a-z0-9]+]], [[REG2:[a-z0-9]+]]
-; CHECK-THUMB: mov [[OUT_LO:[a-z0-9]+]], r2
-; CHECK-THUMB-LE: subs.w {{[^,]+}}, r2, [[REG1]]
-; CHECK-THUMB-BE: subs.w {{[^,]+}}, r3, [[REG2]]
-; CHECK-THUMB-LE: sbcs.w {{[^,]+}}, r3, [[REG2]]
-; CHECK-THUMB-BE: sbcs.w {{[^,]+}}, r2, [[REG1]]
-; CHECK-THUMB: mov.w [[CMP:[a-z0-9]+]], #0
-; CHECK-THUMB: movlo.w [[CMP]], #1
-; CHECK-THUMB: cmp.w [[CMP]], #0
-; CHECK-THUMB: mov [[OUT_HI:[a-z0-9]+]], r3
-; CHECK-THUMB: movne [[OUT_HI]], [[REG2]]
-; CHECK-THUMB: movne [[OUT_LO]], [[REG1]]
-; CHECK-THUMB: strexd {{[a-z0-9]+}}, [[OUT_LO]], [[OUT_HI]]
-; CHECK-THUMB: cmp
-; CHECK-THUMB: bne
-; CHECK-THUMB: dmb {{ish$}}
-
-; CHECK-M: __atomic_compare_exchange_8
+; CHECK-LE-LABEL: test13:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: LBB12_1: @ %atomicrmw.start
+; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-LE-NEXT: mov r7, r2
+; CHECK-LE-NEXT: subs r3, r1, r4
+; CHECK-LE-NEXT: sbcs r3, r2, r5
+; CHECK-LE-NEXT: mov r3, #0
+; CHECK-LE-NEXT: movwlo r3, #1
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: movne r7, r5
+; CHECK-LE-NEXT: mov r6, r1
+; CHECK-LE-NEXT: movne r6, r4
+; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: cmp r3, #0
+; CHECK-LE-NEXT: bne LBB12_1
+; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-LE-NEXT: mov r0, r4
+; CHECK-LE-NEXT: mov r1, r5
+; CHECK-LE-NEXT: dmb ish
+; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-LE-LABEL: test13:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: mov r12, r0
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: .LBB12_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-LE-NEXT: mov r4, r2
+; CHECK-THUMB-LE-NEXT: subs.w lr, r2, r0
+; CHECK-THUMB-LE-NEXT: sbcs.w lr, r3, r1
+; CHECK-THUMB-LE-NEXT: mov.w lr, #0
+; CHECK-THUMB-LE-NEXT: it lo
+; CHECK-THUMB-LE-NEXT: movlo.w lr, #1
+; CHECK-THUMB-LE-NEXT: cmp.w lr, #0
+; CHECK-THUMB-LE-NEXT: mov lr, r3
+; CHECK-THUMB-LE-NEXT: itt ne
+; CHECK-THUMB-LE-NEXT: movne lr, r1
+; CHECK-THUMB-LE-NEXT: movne r4, r0
+; CHECK-THUMB-LE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB12_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: dmb ish
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-BE-LABEL: test13:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: .LBB12_1: @ %atomicrmw.start
+; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
+; CHECK-BE-NEXT: mov r7, r2
+; CHECK-BE-NEXT: subs r3, r2, r5
+; CHECK-BE-NEXT: sbcs r3, r1, r4
+; CHECK-BE-NEXT: mov r3, #0
+; CHECK-BE-NEXT: movwlo r3, #1
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: movne r7, r5
+; CHECK-BE-NEXT: mov r6, r1
+; CHECK-BE-NEXT: movne r6, r4
+; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: cmp r3, #0
+; CHECK-BE-NEXT: bne .LBB12_1
+; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-BE-NEXT: mov r0, r4
+; CHECK-BE-NEXT: mov r1, r5
+; CHECK-BE-NEXT: dmb ish
+; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test13:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: .save {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: mov r12, r0
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: .LBB12_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-THUMB-BE-NEXT: mov r4, r2
+; CHECK-THUMB-BE-NEXT: subs.w lr, r3, r1
+; CHECK-THUMB-BE-NEXT: sbcs.w lr, r2, r0
+; CHECK-THUMB-BE-NEXT: mov.w lr, #0
+; CHECK-THUMB-BE-NEXT: it lo
+; CHECK-THUMB-BE-NEXT: movlo.w lr, #1
+; CHECK-THUMB-BE-NEXT: cmp.w lr, #0
+; CHECK-THUMB-BE-NEXT: mov lr, r3
+; CHECK-THUMB-BE-NEXT: itt ne
+; CHECK-THUMB-BE-NEXT: movne lr, r1
+; CHECK-THUMB-BE-NEXT: movne r4, r0
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB12_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: dmb ish
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-7M-LABEL: test13:
+; CHECK-7M: @ %bb.0:
+; CHECK-7M-NEXT: .save {r4, r5, r6, r7, r8, lr}
+; CHECK-7M-NEXT: push.w {r4, r5, r6, r7, r8, lr}
+; CHECK-7M-NEXT: .pad #16
+; CHECK-7M-NEXT: sub sp, #16
+; CHECK-7M-NEXT: mov r4, r3
+; CHECK-7M-NEXT: mov r5, r2
+; CHECK-7M-NEXT: ldrd r2, r3, [r0]
+; CHECK-7M-NEXT: add.w r8, sp, #8
+; CHECK-7M-NEXT: mov r6, r0
+; CHECK-7M-NEXT: movs r7, #5
+; CHECK-7M-NEXT: .LBB12_1: @ %atomicrmw.start
+; CHECK-7M-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-7M-NEXT: subs r0, r5, r2
+; CHECK-7M-NEXT: strd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: sbcs.w r0, r4, r3
+; CHECK-7M-NEXT: strd r7, r7, [sp]
+; CHECK-7M-NEXT: mov.w r0, #0
+; CHECK-7M-NEXT: mov r1, r8
+; CHECK-7M-NEXT: it lo
+; CHECK-7M-NEXT: movlo r0, #1
+; CHECK-7M-NEXT: cmp r0, #0
+; CHECK-7M-NEXT: mov r0, r6
+; CHECK-7M-NEXT: itt eq
+; CHECK-7M-NEXT: moveq r2, r5
+; CHECK-7M-NEXT: moveq r3, r4
+; CHECK-7M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-7M-NEXT: ldrd r2, r3, [sp, #8]
+; CHECK-7M-NEXT: cmp r0, #0
+; CHECK-7M-NEXT: beq .LBB12_1
+; CHECK-7M-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-7M-NEXT: mov r0, r2
+; CHECK-7M-NEXT: mov r1, r3
+; CHECK-7M-NEXT: add sp, #16
+; CHECK-7M-NEXT: pop.w {r4, r5, r6, r7, r8, pc}
+;
+; CHECK-8M-LABEL: test13:
+; CHECK-8M: @ %bb.0:
+; CHECK-8M-NEXT: .save {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: push {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: .pad #16
+; CHECK-8M-NEXT: sub sp, sp, #16
+; CHECK-8M-NEXT: add r8, sp, #8
+; CHECK-8M-NEXT: mov r4, r3
+; CHECK-8M-NEXT: mov r5, r2
+; CHECK-8M-NEXT: mov r6, r0
+; CHECK-8M-NEXT: ldm r0, {r2, r3}
+; CHECK-8M-NEXT: mov r7, #5
+; CHECK-8M-NEXT: .LBB12_1: @ %atomicrmw.start
+; CHECK-8M-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-8M-NEXT: subs r0, r5, r2
+; CHECK-8M-NEXT: str r2, [sp, #8]
+; CHECK-8M-NEXT: sbcs r0, r4, r3
+; CHECK-8M-NEXT: str r3, [sp, #12]
+; CHECK-8M-NEXT: mov r0, #0
+; CHECK-8M-NEXT: mov r1, r8
+; CHECK-8M-NEXT: movlo r0, #1
+; CHECK-8M-NEXT: cmp r0, #0
+; CHECK-8M-NEXT: moveq r2, r5
+; CHECK-8M-NEXT: moveq r3, r4
+; CHECK-8M-NEXT: mov r0, r6
+; CHECK-8M-NEXT: str r7, [sp]
+; CHECK-8M-NEXT: str r7, [sp, #4]
+; CHECK-8M-NEXT: bl __atomic_compare_exchange_8
+; CHECK-8M-NEXT: ldr r2, [sp, #8]
+; CHECK-8M-NEXT: cmp r0, #0
+; CHECK-8M-NEXT: ldr r3, [sp, #12]
+; CHECK-8M-NEXT: beq .LBB12_1
+; CHECK-8M-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-8M-NEXT: mov r0, r2
+; CHECK-8M-NEXT: mov r1, r3
+; CHECK-8M-NEXT: add sp, sp, #16
+; CHECK-8M-NEXT: pop {r4, r5, r6, r7, r8, lr}
+; CHECK-8M-NEXT: mov pc, lr
+
+
%r = atomicrmw umax ptr %ptr, i64 %val seq_cst
ret i64 %r
diff --git a/llvm/test/CodeGen/ARM/atomic-ops-v8.ll b/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
index 0a467c2b70acf2..c7d4cf5912d179 100644
--- a/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
+++ b/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=armv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE --check-prefix=CHECK-ARM --check-prefix=CHECK-ARM-LE
; RUN: llc -mtriple=armebv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE --check-prefix=CHECK-ARM --check-prefix=CHECK-ARM-BE
; RUN: llc -mtriple=thumbv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-LE
@@ -9,1399 +10,2488 @@
@var64 = global i64 0
define i8 @test_atomic_load_add_i8(i8 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_add_i8:
+; CHECK-ARM-LABEL: test_atomic_load_add_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB0_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexb r1, [r12]
+; CHECK-ARM-NEXT: add r3, r1, r0
+; CHECK-ARM-NEXT: stlexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB0_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_add_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB0_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexb r1, [r12]
+; CHECK-THUMB-NEXT: adds r3, r1, r0
+; CHECK-THUMB-NEXT: stlexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB0_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw add ptr @var8, i8 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_add_i16(i16 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_add_i16:
+; CHECK-ARM-LABEL: test_atomic_load_add_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB1_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexh r1, [r12]
+; CHECK-ARM-NEXT: add r3, r1, r0
+; CHECK-ARM-NEXT: strexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB1_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_add_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB1_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexh r1, [r12]
+; CHECK-THUMB-NEXT: adds r3, r1, r0
+; CHECK-THUMB-NEXT: strexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB1_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw add ptr @var16, i16 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK: movt r[[ADDR]], :upper16:var16
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_add_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_add_i32:
+; CHECK-ARM-LABEL: test_atomic_load_add_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB2_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrex r1, [r12]
+; CHECK-ARM-NEXT: add r3, r1, r0
+; CHECK-ARM-NEXT: stlex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB2_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_add_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB2_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrex r1, [r12]
+; CHECK-THUMB-NEXT: adds r3, r1, r0
+; CHECK-THUMB-NEXT: stlex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB2_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw add ptr @var32, i32 %offset release
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_add_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_add_i64:
+; CHECK-ARM-LE-LABEL: test_atomic_load_add_i64:
+; CHECK-ARM-LE: @ %bb.0:
+; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: .LBB3_1: @ %atomicrmw.start
+; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-LE-NEXT: ldrexd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: adds r6, r4, r0
+; CHECK-ARM-LE-NEXT: adc r7, r5, r1
+; CHECK-ARM-LE-NEXT: strexd r3, r6, r7, [r2]
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: bne .LBB3_1
+; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-ARM-BE-LABEL: test_atomic_load_add_i64:
+; CHECK-ARM-BE: @ %bb.0:
+; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: .LBB3_1: @ %atomicrmw.start
+; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-BE-NEXT: ldrexd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: adds r7, r5, r1
+; CHECK-ARM-BE-NEXT: adc r6, r4, r0
+; CHECK-ARM-BE-NEXT: strexd r3, r6, r7, [r2]
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: bne .LBB3_1
+; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LE-LABEL: test_atomic_load_add_i64:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-LE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-LE-NEXT: .LBB3_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r3, r2, [r12]
+; CHECK-THUMB-LE-NEXT: adds.w lr, r3, r0
+; CHECK-THUMB-LE-NEXT: adc.w r4, r2, r1
+; CHECK-THUMB-LE-NEXT: strexd r5, lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB3_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: strd r3, r2, [r12]
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test_atomic_load_add_i64:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-BE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-BE-NEXT: .LBB3_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r3, r2, [r12]
+; CHECK-THUMB-BE-NEXT: adds.w lr, r2, r1
+; CHECK-THUMB-BE-NEXT: adc.w r4, r3, r0
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB3_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: strd r3, r2, [r12]
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw add ptr @var64, i64 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-LE-NEXT: adds{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
-; CHECK-LE-NEXT: adc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
-; CHECK-BE-NEXT: adds{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
-; CHECK-BE-NEXT: adc{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
-; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_sub_i8(i8 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_sub_i8:
+; CHECK-ARM-LABEL: test_atomic_load_sub_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB4_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexb r1, [r12]
+; CHECK-ARM-NEXT: sub r3, r1, r0
+; CHECK-ARM-NEXT: strexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB4_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_sub_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB4_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexb r1, [r12]
+; CHECK-THUMB-NEXT: subs r3, r1, r0
+; CHECK-THUMB-NEXT: strexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB4_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw sub ptr @var8, i8 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_sub_i16(i16 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_sub_i16:
+; CHECK-ARM-LABEL: test_atomic_load_sub_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB5_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexh r1, [r12]
+; CHECK-ARM-NEXT: sub r3, r1, r0
+; CHECK-ARM-NEXT: stlexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB5_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_sub_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB5_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexh r1, [r12]
+; CHECK-THUMB-NEXT: subs r3, r1, r0
+; CHECK-THUMB-NEXT: stlexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB5_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw sub ptr @var16, i16 %offset release
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK: movt r[[ADDR]], :upper16:var16
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_sub_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_sub_i32:
+; CHECK-ARM-LABEL: test_atomic_load_sub_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB6_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaex r1, [r12]
+; CHECK-ARM-NEXT: sub r3, r1, r0
+; CHECK-ARM-NEXT: strex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB6_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_sub_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB6_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaex r1, [r12]
+; CHECK-THUMB-NEXT: subs r3, r1, r0
+; CHECK-THUMB-NEXT: strex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB6_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw sub ptr @var32, i32 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: strex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_sub_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_sub_i64:
+; CHECK-ARM-LE-LABEL: test_atomic_load_sub_i64:
+; CHECK-ARM-LE: @ %bb.0:
+; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: .LBB7_1: @ %atomicrmw.start
+; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-LE-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: subs r6, r4, r0
+; CHECK-ARM-LE-NEXT: sbc r7, r5, r1
+; CHECK-ARM-LE-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: bne .LBB7_1
+; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-ARM-BE-LABEL: test_atomic_load_sub_i64:
+; CHECK-ARM-BE: @ %bb.0:
+; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: .LBB7_1: @ %atomicrmw.start
+; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-BE-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: subs r7, r5, r1
+; CHECK-ARM-BE-NEXT: sbc r6, r4, r0
+; CHECK-ARM-BE-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: bne .LBB7_1
+; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LE-LABEL: test_atomic_load_sub_i64:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-LE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-LE-NEXT: .LBB7_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldaexd r3, r2, [r12]
+; CHECK-THUMB-LE-NEXT: subs.w lr, r3, r0
+; CHECK-THUMB-LE-NEXT: sbc.w r4, r2, r1
+; CHECK-THUMB-LE-NEXT: stlexd r5, lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB7_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: strd r3, r2, [r12]
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test_atomic_load_sub_i64:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-BE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-BE-NEXT: .LBB7_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldaexd r3, r2, [r12]
+; CHECK-THUMB-BE-NEXT: subs.w lr, r2, r1
+; CHECK-THUMB-BE-NEXT: sbc.w r4, r3, r0
+; CHECK-THUMB-BE-NEXT: stlexd r5, r4, lr, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB7_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: strd r3, r2, [r12]
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw sub ptr @var64, i64 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-LE-NEXT: subs{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
-; CHECK-LE-NEXT: sbc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
-; CHECK-BE-NEXT: subs{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
-; CHECK-BE-NEXT: sbc{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
-; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_and_i8(i8 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_and_i8:
+; CHECK-ARM-LABEL: test_atomic_load_and_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB8_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexb r1, [r12]
+; CHECK-ARM-NEXT: and r3, r1, r0
+; CHECK-ARM-NEXT: stlexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB8_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_and_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB8_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexb r1, [r12]
+; CHECK-THUMB-NEXT: and.w r3, r1, r0
+; CHECK-THUMB-NEXT: stlexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB8_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw and ptr @var8, i8 %offset release
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_and_i16(i16 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_and_i16:
+; CHECK-ARM-LABEL: test_atomic_load_and_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB9_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexh r1, [r12]
+; CHECK-ARM-NEXT: and r3, r1, r0
+; CHECK-ARM-NEXT: strexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB9_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_and_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB9_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexh r1, [r12]
+; CHECK-THUMB-NEXT: and.w r3, r1, r0
+; CHECK-THUMB-NEXT: strexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB9_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw and ptr @var16, i16 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK: movt r[[ADDR]], :upper16:var16
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_and_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_and_i32:
+; CHECK-ARM-LABEL: test_atomic_load_and_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB10_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaex r1, [r12]
+; CHECK-ARM-NEXT: and r3, r1, r0
+; CHECK-ARM-NEXT: stlex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB10_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_and_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB10_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaex r1, [r12]
+; CHECK-THUMB-NEXT: and.w r3, r1, r0
+; CHECK-THUMB-NEXT: stlex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB10_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw and ptr @var32, i32 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_and_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_and_i64:
+; CHECK-ARM-LABEL: test_atomic_load_and_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: .LBB11_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-NEXT: and r7, r5, r1
+; CHECK-ARM-NEXT: and r6, r4, r0
+; CHECK-ARM-NEXT: strexd r3, r6, r7, [r2]
+; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: bne .LBB11_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LABEL: test_atomic_load_and_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-NEXT: .LBB11_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexd r3, r2, [r12]
+; CHECK-THUMB-NEXT: and.w lr, r2, r1
+; CHECK-THUMB-NEXT: and.w r4, r3, r0
+; CHECK-THUMB-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-NEXT: cmp r5, #0
+; CHECK-THUMB-NEXT: bne .LBB11_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: strd r3, r2, [r12]
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw and ptr @var64, i64 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-LE-DAG: and{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
-; CHECK-LE-DAG: and{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
-; CHECK-BE-DAG: and{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
-; CHECK-BE-DAG: and{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
-; CHECK: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_or_i8(i8 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_or_i8:
+; CHECK-ARM-LABEL: test_atomic_load_or_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB12_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexb r1, [r12]
+; CHECK-ARM-NEXT: orr r3, r1, r0
+; CHECK-ARM-NEXT: stlexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB12_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_or_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB12_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexb r1, [r12]
+; CHECK-THUMB-NEXT: orr.w r3, r1, r0
+; CHECK-THUMB-NEXT: stlexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB12_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw or ptr @var8, i8 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_or_i16(i16 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_or_i16:
+; CHECK-ARM-LABEL: test_atomic_load_or_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB13_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexh r1, [r12]
+; CHECK-ARM-NEXT: orr r3, r1, r0
+; CHECK-ARM-NEXT: strexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB13_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_or_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB13_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexh r1, [r12]
+; CHECK-THUMB-NEXT: orr.w r3, r1, r0
+; CHECK-THUMB-NEXT: strexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB13_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw or ptr @var16, i16 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK: movt r[[ADDR]], :upper16:var16
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_or_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_or_i32:
+; CHECK-ARM-LABEL: test_atomic_load_or_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB14_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaex r1, [r12]
+; CHECK-ARM-NEXT: orr r3, r1, r0
+; CHECK-ARM-NEXT: strex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB14_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_or_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB14_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaex r1, [r12]
+; CHECK-THUMB-NEXT: orr.w r3, r1, r0
+; CHECK-THUMB-NEXT: strex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB14_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw or ptr @var32, i32 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: strex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_or_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_or_i64:
+; CHECK-ARM-LABEL: test_atomic_load_or_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: .LBB15_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexd r4, r5, [r2]
+; CHECK-ARM-NEXT: orr r7, r5, r1
+; CHECK-ARM-NEXT: orr r6, r4, r0
+; CHECK-ARM-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: bne .LBB15_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LABEL: test_atomic_load_or_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-NEXT: .LBB15_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexd r3, r2, [r12]
+; CHECK-THUMB-NEXT: orr.w lr, r2, r1
+; CHECK-THUMB-NEXT: orr.w r4, r3, r0
+; CHECK-THUMB-NEXT: stlexd r5, r4, lr, [r12]
+; CHECK-THUMB-NEXT: cmp r5, #0
+; CHECK-THUMB-NEXT: bne .LBB15_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: strd r3, r2, [r12]
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw or ptr @var64, i64 %offset release
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-LE-DAG: orr{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
-; CHECK-LE-DAG: orr{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
-; CHECK-BE-DAG: orr{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
-; CHECK-BE-DAG: orr{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
-; CHECK: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_xor_i8(i8 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_xor_i8:
+; CHECK-ARM-LABEL: test_atomic_load_xor_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB16_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexb r1, [r12]
+; CHECK-ARM-NEXT: eor r3, r1, r0
+; CHECK-ARM-NEXT: strexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB16_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_xor_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB16_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexb r1, [r12]
+; CHECK-THUMB-NEXT: eor.w r3, r1, r0
+; CHECK-THUMB-NEXT: strexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB16_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw xor ptr @var8, i8 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_xor_i16(i16 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_xor_i16:
+; CHECK-ARM-LABEL: test_atomic_load_xor_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB17_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexh r1, [r12]
+; CHECK-ARM-NEXT: eor r3, r1, r0
+; CHECK-ARM-NEXT: stlexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB17_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_xor_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB17_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexh r1, [r12]
+; CHECK-THUMB-NEXT: eor.w r3, r1, r0
+; CHECK-THUMB-NEXT: stlexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB17_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw xor ptr @var16, i16 %offset release
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK: movt r[[ADDR]], :upper16:var16
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_xor_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_xor_i32:
+; CHECK-ARM-LABEL: test_atomic_load_xor_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB18_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaex r1, [r12]
+; CHECK-ARM-NEXT: eor r3, r1, r0
+; CHECK-ARM-NEXT: stlex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB18_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_xor_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB18_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaex r1, [r12]
+; CHECK-THUMB-NEXT: eor.w r3, r1, r0
+; CHECK-THUMB-NEXT: stlex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB18_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw xor ptr @var32, i32 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
-; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_xor_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_xor_i64:
+; CHECK-ARM-LABEL: test_atomic_load_xor_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: .LBB19_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexd r4, r5, [r2]
+; CHECK-ARM-NEXT: eor r7, r5, r1
+; CHECK-ARM-NEXT: eor r6, r4, r0
+; CHECK-ARM-NEXT: strexd r3, r6, r7, [r2]
+; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: bne .LBB19_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LABEL: test_atomic_load_xor_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-NEXT: .LBB19_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexd r3, r2, [r12]
+; CHECK-THUMB-NEXT: eor.w lr, r2, r1
+; CHECK-THUMB-NEXT: eor.w r4, r3, r0
+; CHECK-THUMB-NEXT: strexd r5, r4, lr, [r12]
+; CHECK-THUMB-NEXT: cmp r5, #0
+; CHECK-THUMB-NEXT: bne .LBB19_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: strd r3, r2, [r12]
+; CHECK-THUMB-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw xor ptr @var64, i64 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-LE-DAG: eor{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
-; CHECK-LE-DAG: eor{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
-; CHECK-BE-DAG: eor{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
-; CHECK-BE-DAG: eor{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
-; CHECK: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_xchg_i8(i8 %offset) nounwind {
; CHECK-LABEL: test_atomic_load_xchg_i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r2, :lower16:var8
+; CHECK-NEXT: movt r2, :upper16:var8
+; CHECK-NEXT: .LBB20_1: @ %atomicrmw.start
+; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: ldrexb r1, [r2]
+; CHECK-NEXT: strexb r3, r0, [r2]
+; CHECK-NEXT: cmp r3, #0
+; CHECK-NEXT: bne .LBB20_1
+; CHECK-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-NEXT: mov r0, r1
+; CHECK-NEXT: bx lr
%old = atomicrmw xchg ptr @var8, i8 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: mov r0, r[[OLD]]
ret i8 %old
}
define i16 @test_atomic_load_xchg_i16(i16 %offset) nounwind {
; CHECK-LABEL: test_atomic_load_xchg_i16:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r2, :lower16:var16
+; CHECK-NEXT: movt r2, :upper16:var16
+; CHECK-NEXT: .LBB21_1: @ %atomicrmw.start
+; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: ldaexh r1, [r2]
+; CHECK-NEXT: stlexh r3, r0, [r2]
+; CHECK-NEXT: cmp r3, #0
+; CHECK-NEXT: bne .LBB21_1
+; CHECK-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-NEXT: mov r0, r1
+; CHECK-NEXT: bx lr
%old = atomicrmw xchg ptr @var16, i16 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK: movt r[[ADDR]], :upper16:var16
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: mov r0, r[[OLD]]
ret i16 %old
}
define i32 @test_atomic_load_xchg_i32(i32 %offset) nounwind {
; CHECK-LABEL: test_atomic_load_xchg_i32:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r2, :lower16:var32
+; CHECK-NEXT: movt r2, :upper16:var32
+; CHECK-NEXT: .LBB22_1: @ %atomicrmw.start
+; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: ldrex r1, [r2]
+; CHECK-NEXT: stlex r3, r0, [r2]
+; CHECK-NEXT: cmp r3, #0
+; CHECK-NEXT: bne .LBB22_1
+; CHECK-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-NEXT: mov r0, r1
+; CHECK-NEXT: bx lr
%old = atomicrmw xchg ptr @var32, i32 %offset release
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: mov r0, r[[OLD]]
ret i32 %old
}
define void @test_atomic_load_xchg_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_xchg_i64:
+; CHECK-ARM-LABEL: test_atomic_load_xchg_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: push {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-NEXT: @ kill: def $r1 killed $r1 killed $r0_r1 def $r0_r1
+; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: @ kill: def $r0 killed $r0 killed $r0_r1 def $r0_r1
+; CHECK-ARM-NEXT: .LBB23_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-NEXT: strexd r3, r0, r1, [r2]
+; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: bne .LBB23_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-NEXT: pop {r4, r5, r11, pc}
+;
+; CHECK-THUMB-LABEL: test_atomic_load_xchg_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: push {r7, lr}
+; CHECK-THUMB-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-NEXT: .LBB23_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexd r3, lr, [r12]
+; CHECK-THUMB-NEXT: strexd r2, r0, r1, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB23_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-NEXT: pop {r7, pc}
%old = atomicrmw xchg ptr @var64, i64 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_min_i8(i8 signext %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_min_i8:
+; CHECK-ARM-LABEL: test_atomic_load_min_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB24_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexb r1, [r12]
+; CHECK-ARM-NEXT: sxtb r3, r1
+; CHECK-ARM-NEXT: cmp r3, r0
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: movle r3, r1
+; CHECK-ARM-NEXT: strexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB24_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_min_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB24_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexb r1, [r12]
+; CHECK-THUMB-NEXT: sxtb r3, r1
+; CHECK-THUMB-NEXT: cmp r3, r0
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: it le
+; CHECK-THUMB-NEXT: movle r3, r1
+; CHECK-THUMB-NEXT: strexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB24_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw min ptr @var8, i8 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK-DAG: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
-; CHECK-DAG: movt [[ADDR]], :upper16:var8
-
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
-; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
+
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLDX]], r0
; Thumb mode: it le
-; CHECK: movle r[[OLDX]], r[[OLD]]
-; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_min_i16(i16 signext %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_min_i16:
+; CHECK-ARM-LABEL: test_atomic_load_min_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB25_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexh r1, [r12]
+; CHECK-ARM-NEXT: sxth r3, r1
+; CHECK-ARM-NEXT: cmp r3, r0
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: movle r3, r1
+; CHECK-ARM-NEXT: stlexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB25_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_min_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB25_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexh r1, [r12]
+; CHECK-THUMB-NEXT: sxth r3, r1
+; CHECK-THUMB-NEXT: cmp r3, r0
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: it le
+; CHECK-THUMB-NEXT: movle r3, r1
+; CHECK-THUMB-NEXT: stlexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB25_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw min ptr @var16, i16 %offset release
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
-; CHECK: movt [[ADDR]], :upper16:var16
-
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
-; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
+
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLDX]], r0
; Thumb mode: it le
-; CHECK: movle r[[OLDX]], r[[OLD]]
-; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_min_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_min_i32:
+; CHECK-ARM-LABEL: test_atomic_load_min_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB26_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrex r1, [r12]
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: cmp r1, r0
+; CHECK-ARM-NEXT: movle r3, r1
+; CHECK-ARM-NEXT: strex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB26_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_min_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB26_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrex r1, [r12]
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: cmp r1, r0
+; CHECK-THUMB-NEXT: it le
+; CHECK-THUMB-NEXT: movle r3, r1
+; CHECK-THUMB-NEXT: strex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB26_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw min ptr @var32, i32 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
-; CHECK-NEXT: cmp r[[OLD]], r0
; Thumb mode: it le
-; CHECK: movle r[[NEW]], r[[OLD]]
-; CHECK-NEXT: strex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_min_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_min_i64:
+; CHECK-ARM-LE-LABEL: test_atomic_load_min_i64:
+; CHECK-ARM-LE: @ %bb.0:
+; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: .LBB27_1: @ %atomicrmw.start
+; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-LE-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: mov r7, r1
+; CHECK-ARM-LE-NEXT: subs r3, r0, r4
+; CHECK-ARM-LE-NEXT: sbcs r3, r1, r5
+; CHECK-ARM-LE-NEXT: mov r3, #0
+; CHECK-ARM-LE-NEXT: movwge r3, #1
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: movne r7, r5
+; CHECK-ARM-LE-NEXT: mov r6, r0
+; CHECK-ARM-LE-NEXT: movne r6, r4
+; CHECK-ARM-LE-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: bne .LBB27_1
+; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-ARM-BE-LABEL: test_atomic_load_min_i64:
+; CHECK-ARM-BE: @ %bb.0:
+; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: .LBB27_1: @ %atomicrmw.start
+; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-BE-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: mov r7, r1
+; CHECK-ARM-BE-NEXT: subs r3, r1, r5
+; CHECK-ARM-BE-NEXT: sbcs r3, r0, r4
+; CHECK-ARM-BE-NEXT: mov r3, #0
+; CHECK-ARM-BE-NEXT: movwge r3, #1
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: movne r7, r5
+; CHECK-ARM-BE-NEXT: mov r6, r0
+; CHECK-ARM-BE-NEXT: movne r6, r4
+; CHECK-ARM-BE-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: bne .LBB27_1
+; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LE-LABEL: test_atomic_load_min_i64:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-LE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-LE-NEXT: .LBB27_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldaexd r3, lr, [r12]
+; CHECK-THUMB-LE-NEXT: mov r4, r0
+; CHECK-THUMB-LE-NEXT: subs r2, r0, r3
+; CHECK-THUMB-LE-NEXT: sbcs.w r2, r1, lr
+; CHECK-THUMB-LE-NEXT: mov.w r2, #0
+; CHECK-THUMB-LE-NEXT: it ge
+; CHECK-THUMB-LE-NEXT: movge r2, #1
+; CHECK-THUMB-LE-NEXT: cmp r2, #0
+; CHECK-THUMB-LE-NEXT: mov r2, r1
+; CHECK-THUMB-LE-NEXT: itt ne
+; CHECK-THUMB-LE-NEXT: movne r2, lr
+; CHECK-THUMB-LE-NEXT: movne r4, r3
+; CHECK-THUMB-LE-NEXT: stlexd r5, r4, r2, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB27_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test_atomic_load_min_i64:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-BE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-BE-NEXT: .LBB27_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldaexd r3, lr, [r12]
+; CHECK-THUMB-BE-NEXT: mov r4, r0
+; CHECK-THUMB-BE-NEXT: subs.w r2, r1, lr
+; CHECK-THUMB-BE-NEXT: sbcs.w r2, r0, r3
+; CHECK-THUMB-BE-NEXT: mov.w r2, #0
+; CHECK-THUMB-BE-NEXT: it ge
+; CHECK-THUMB-BE-NEXT: movge r2, #1
+; CHECK-THUMB-BE-NEXT: cmp r2, #0
+; CHECK-THUMB-BE-NEXT: mov r2, r1
+; CHECK-THUMB-BE-NEXT: itt ne
+; CHECK-THUMB-BE-NEXT: movne r2, lr
+; CHECK-THUMB-BE-NEXT: movne r4, r3
+; CHECK-THUMB-BE-NEXT: stlexd r5, r4, r2, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB27_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw min ptr @var64, i64 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
-; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
-; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
-; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
-; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
-; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
-; CHECK-ARM: movwge [[CMP:r[0-9]+|lr]], #1
-; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
-; CHECK-ARM: movne [[MINHI]], [[OLD2]]
-; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
-; CHECK-ARM: movne [[MINLO]], [[OLD1]]
-; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
-; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_max_i8(i8 signext %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_max_i8:
+; CHECK-ARM-LABEL: test_atomic_load_max_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB28_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexb r1, [r12]
+; CHECK-ARM-NEXT: sxtb r3, r1
+; CHECK-ARM-NEXT: cmp r3, r0
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: movgt r3, r1
+; CHECK-ARM-NEXT: stlexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB28_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_max_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB28_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexb r1, [r12]
+; CHECK-THUMB-NEXT: sxtb r3, r1
+; CHECK-THUMB-NEXT: cmp r3, r0
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: it gt
+; CHECK-THUMB-NEXT: movgt r3, r1
+; CHECK-THUMB-NEXT: stlexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB28_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw max ptr @var8, i8 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
-; CHECK: movt [[ADDR]], :upper16:var8
-
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
-; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
+
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLDX]], r0
; Thumb mode: it gt
-; CHECK: movgt r[[OLDX]], r[[OLD]]
-; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_max_i16(i16 signext %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_max_i16:
+; CHECK-ARM-LABEL: test_atomic_load_max_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB29_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexh r1, [r12]
+; CHECK-ARM-NEXT: sxth r3, r1
+; CHECK-ARM-NEXT: cmp r3, r0
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: movgt r3, r1
+; CHECK-ARM-NEXT: strexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB29_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_max_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB29_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexh r1, [r12]
+; CHECK-THUMB-NEXT: sxth r3, r1
+; CHECK-THUMB-NEXT: cmp r3, r0
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: it gt
+; CHECK-THUMB-NEXT: movgt r3, r1
+; CHECK-THUMB-NEXT: strexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB29_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw max ptr @var16, i16 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK: movt r[[ADDR]], :upper16:var16
-
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
-; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
+
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLDX]], r0
; Thumb mode: it gt
-; CHECK: movgt r[[OLDX]], r[[OLD]]
-; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[OLDX]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_max_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_max_i32:
+; CHECK-ARM-LABEL: test_atomic_load_max_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB30_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrex r1, [r12]
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: cmp r1, r0
+; CHECK-ARM-NEXT: movgt r3, r1
+; CHECK-ARM-NEXT: stlex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB30_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_max_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB30_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrex r1, [r12]
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: cmp r1, r0
+; CHECK-THUMB-NEXT: it gt
+; CHECK-THUMB-NEXT: movgt r3, r1
+; CHECK-THUMB-NEXT: stlex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB30_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw max ptr @var32, i32 %offset release
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
-; CHECK-NEXT: cmp r[[OLD]], r0
; Thumb mode: it gt
-; CHECK: movgt r[[NEW]], r[[OLD]]
-; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_max_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_max_i64:
+; CHECK-ARM-LE-LABEL: test_atomic_load_max_i64:
+; CHECK-ARM-LE: @ %bb.0:
+; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: .LBB31_1: @ %atomicrmw.start
+; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-LE-NEXT: ldrexd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: mov r7, r1
+; CHECK-ARM-LE-NEXT: subs r3, r0, r4
+; CHECK-ARM-LE-NEXT: sbcs r3, r1, r5
+; CHECK-ARM-LE-NEXT: mov r3, #0
+; CHECK-ARM-LE-NEXT: movwlt r3, #1
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: movne r7, r5
+; CHECK-ARM-LE-NEXT: mov r6, r0
+; CHECK-ARM-LE-NEXT: movne r6, r4
+; CHECK-ARM-LE-NEXT: strexd r3, r6, r7, [r2]
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: bne .LBB31_1
+; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-ARM-BE-LABEL: test_atomic_load_max_i64:
+; CHECK-ARM-BE: @ %bb.0:
+; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: .LBB31_1: @ %atomicrmw.start
+; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-BE-NEXT: ldrexd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: mov r7, r1
+; CHECK-ARM-BE-NEXT: subs r3, r1, r5
+; CHECK-ARM-BE-NEXT: sbcs r3, r0, r4
+; CHECK-ARM-BE-NEXT: mov r3, #0
+; CHECK-ARM-BE-NEXT: movwlt r3, #1
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: movne r7, r5
+; CHECK-ARM-BE-NEXT: mov r6, r0
+; CHECK-ARM-BE-NEXT: movne r6, r4
+; CHECK-ARM-BE-NEXT: strexd r3, r6, r7, [r2]
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: bne .LBB31_1
+; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LE-LABEL: test_atomic_load_max_i64:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-LE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-LE-NEXT: .LBB31_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd r3, lr, [r12]
+; CHECK-THUMB-LE-NEXT: mov r4, r0
+; CHECK-THUMB-LE-NEXT: subs r2, r0, r3
+; CHECK-THUMB-LE-NEXT: sbcs.w r2, r1, lr
+; CHECK-THUMB-LE-NEXT: mov.w r2, #0
+; CHECK-THUMB-LE-NEXT: it lt
+; CHECK-THUMB-LE-NEXT: movlt r2, #1
+; CHECK-THUMB-LE-NEXT: cmp r2, #0
+; CHECK-THUMB-LE-NEXT: mov r2, r1
+; CHECK-THUMB-LE-NEXT: itt ne
+; CHECK-THUMB-LE-NEXT: movne r2, lr
+; CHECK-THUMB-LE-NEXT: movne r4, r3
+; CHECK-THUMB-LE-NEXT: strexd r5, r4, r2, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB31_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test_atomic_load_max_i64:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-BE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-BE-NEXT: .LBB31_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd r3, lr, [r12]
+; CHECK-THUMB-BE-NEXT: mov r4, r0
+; CHECK-THUMB-BE-NEXT: subs.w r2, r1, lr
+; CHECK-THUMB-BE-NEXT: sbcs.w r2, r0, r3
+; CHECK-THUMB-BE-NEXT: mov.w r2, #0
+; CHECK-THUMB-BE-NEXT: it lt
+; CHECK-THUMB-BE-NEXT: movlt r2, #1
+; CHECK-THUMB-BE-NEXT: cmp r2, #0
+; CHECK-THUMB-BE-NEXT: mov r2, r1
+; CHECK-THUMB-BE-NEXT: itt ne
+; CHECK-THUMB-BE-NEXT: movne r2, lr
+; CHECK-THUMB-BE-NEXT: movne r4, r3
+; CHECK-THUMB-BE-NEXT: strexd r5, r4, r2, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB31_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw max ptr @var64, i64 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
-; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
-; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
-; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
-; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
-; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
-; CHECK-ARM: movwlt [[CMP:r[0-9]+|lr]], #1
-; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
-; CHECK-ARM: movne [[MINHI]], [[OLD2]]
-; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
-; CHECK-ARM: movne [[MINLO]], [[OLD1]]
-; CHECK-ARM: strexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
-; CHECK-THUMB: strexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_umin_i8(i8 zeroext %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_umin_i8:
+; CHECK-ARM-LABEL: test_atomic_load_umin_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB32_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexb r1, [r12]
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: cmp r1, r0
+; CHECK-ARM-NEXT: movls r3, r1
+; CHECK-ARM-NEXT: strexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB32_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_umin_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB32_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexb r1, [r12]
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: cmp r1, r0
+; CHECK-THUMB-NEXT: it ls
+; CHECK-THUMB-NEXT: movls r3, r1
+; CHECK-THUMB-NEXT: strexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB32_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw umin ptr @var8, i8 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
-; CHECK: movt [[ADDR]], :upper16:var8
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
-; CHECK-NEXT: cmp r[[OLD]], r0
; Thumb mode: it ls
-; CHECK: movls r[[NEW]], r[[OLD]]
-; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_umin_i16(i16 zeroext %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_umin_i16:
+; CHECK-ARM-LABEL: test_atomic_load_umin_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB33_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexh r1, [r12]
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: cmp r1, r0
+; CHECK-ARM-NEXT: movls r3, r1
+; CHECK-ARM-NEXT: strexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB33_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_umin_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB33_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexh r1, [r12]
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: cmp r1, r0
+; CHECK-THUMB-NEXT: it ls
+; CHECK-THUMB-NEXT: movls r3, r1
+; CHECK-THUMB-NEXT: strexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB33_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw umin ptr @var16, i16 %offset acquire
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
-; CHECK: movt [[ADDR]], :upper16:var16
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
-; CHECK-NEXT: cmp r[[OLD]], r0
; Thumb mode: it ls
-; CHECK: movls r[[NEW]], r[[OLD]]
-; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_umin_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_umin_i32:
+; CHECK-ARM-LABEL: test_atomic_load_umin_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB34_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaex r1, [r12]
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: cmp r1, r0
+; CHECK-ARM-NEXT: movls r3, r1
+; CHECK-ARM-NEXT: stlex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB34_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_umin_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB34_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaex r1, [r12]
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: cmp r1, r0
+; CHECK-THUMB-NEXT: it ls
+; CHECK-THUMB-NEXT: movls r3, r1
+; CHECK-THUMB-NEXT: stlex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB34_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw umin ptr @var32, i32 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
-; CHECK-NEXT: cmp r[[OLD]], r0
; Thumb mode: it ls
-; CHECK: movls r[[NEW]], r[[OLD]]
-; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_umin_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_umin_i64:
+; CHECK-ARM-LE-LABEL: test_atomic_load_umin_i64:
+; CHECK-ARM-LE: @ %bb.0:
+; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: .LBB35_1: @ %atomicrmw.start
+; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-LE-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: mov r7, r1
+; CHECK-ARM-LE-NEXT: subs r3, r0, r4
+; CHECK-ARM-LE-NEXT: sbcs r3, r1, r5
+; CHECK-ARM-LE-NEXT: mov r3, #0
+; CHECK-ARM-LE-NEXT: movwhs r3, #1
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: movne r7, r5
+; CHECK-ARM-LE-NEXT: mov r6, r0
+; CHECK-ARM-LE-NEXT: movne r6, r4
+; CHECK-ARM-LE-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: bne .LBB35_1
+; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-ARM-BE-LABEL: test_atomic_load_umin_i64:
+; CHECK-ARM-BE: @ %bb.0:
+; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: .LBB35_1: @ %atomicrmw.start
+; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-BE-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: mov r7, r1
+; CHECK-ARM-BE-NEXT: subs r3, r1, r5
+; CHECK-ARM-BE-NEXT: sbcs r3, r0, r4
+; CHECK-ARM-BE-NEXT: mov r3, #0
+; CHECK-ARM-BE-NEXT: movwhs r3, #1
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: movne r7, r5
+; CHECK-ARM-BE-NEXT: mov r6, r0
+; CHECK-ARM-BE-NEXT: movne r6, r4
+; CHECK-ARM-BE-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: bne .LBB35_1
+; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LE-LABEL: test_atomic_load_umin_i64:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-LE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-LE-NEXT: .LBB35_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldaexd r3, lr, [r12]
+; CHECK-THUMB-LE-NEXT: mov r4, r0
+; CHECK-THUMB-LE-NEXT: subs r2, r0, r3
+; CHECK-THUMB-LE-NEXT: sbcs.w r2, r1, lr
+; CHECK-THUMB-LE-NEXT: mov.w r2, #0
+; CHECK-THUMB-LE-NEXT: it hs
+; CHECK-THUMB-LE-NEXT: movhs r2, #1
+; CHECK-THUMB-LE-NEXT: cmp r2, #0
+; CHECK-THUMB-LE-NEXT: mov r2, r1
+; CHECK-THUMB-LE-NEXT: itt ne
+; CHECK-THUMB-LE-NEXT: movne r2, lr
+; CHECK-THUMB-LE-NEXT: movne r4, r3
+; CHECK-THUMB-LE-NEXT: stlexd r5, r4, r2, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB35_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test_atomic_load_umin_i64:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-BE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-BE-NEXT: .LBB35_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldaexd r3, lr, [r12]
+; CHECK-THUMB-BE-NEXT: mov r4, r0
+; CHECK-THUMB-BE-NEXT: subs.w r2, r1, lr
+; CHECK-THUMB-BE-NEXT: sbcs.w r2, r0, r3
+; CHECK-THUMB-BE-NEXT: mov.w r2, #0
+; CHECK-THUMB-BE-NEXT: it hs
+; CHECK-THUMB-BE-NEXT: movhs r2, #1
+; CHECK-THUMB-BE-NEXT: cmp r2, #0
+; CHECK-THUMB-BE-NEXT: mov r2, r1
+; CHECK-THUMB-BE-NEXT: itt ne
+; CHECK-THUMB-BE-NEXT: movne r2, lr
+; CHECK-THUMB-BE-NEXT: movne r4, r3
+; CHECK-THUMB-BE-NEXT: stlexd r5, r4, r2, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB35_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw umin ptr @var64, i64 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
-; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
-; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
-; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
-; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
-; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
-; CHECK-ARM: movwhs [[CMP:r[0-9]+|lr]], #1
-; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
-; CHECK-ARM: movne [[MINHI]], [[OLD2]]
-; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
-; CHECK-ARM: movne [[MINLO]], [[OLD1]]
-; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
-; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_umax_i8(i8 zeroext %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_umax_i8:
+; CHECK-ARM-LABEL: test_atomic_load_umax_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB36_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexb r1, [r12]
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: cmp r1, r0
+; CHECK-ARM-NEXT: movhi r3, r1
+; CHECK-ARM-NEXT: stlexb r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB36_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_umax_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB36_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexb r1, [r12]
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: cmp r1, r0
+; CHECK-THUMB-NEXT: it hi
+; CHECK-THUMB-NEXT: movhi r3, r1
+; CHECK-THUMB-NEXT: stlexb r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB36_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw umax ptr @var8, i8 %offset acq_rel
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
-; CHECK: movt [[ADDR]], :upper16:var8
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
-; CHECK-NEXT: cmp r[[OLD]], r0
; Thumb mode: it hi
-; CHECK: movhi r[[NEW]], r[[OLD]]
-; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i8 %old
}
define i16 @test_atomic_load_umax_i16(i16 zeroext %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_umax_i16:
+; CHECK-ARM-LABEL: test_atomic_load_umax_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB37_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexh r1, [r12]
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: cmp r1, r0
+; CHECK-ARM-NEXT: movhi r3, r1
+; CHECK-ARM-NEXT: strexh r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB37_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_umax_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB37_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexh r1, [r12]
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: cmp r1, r0
+; CHECK-THUMB-NEXT: it hi
+; CHECK-THUMB-NEXT: movhi r3, r1
+; CHECK-THUMB-NEXT: strexh r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB37_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw umax ptr @var16, i16 %offset monotonic
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
-; CHECK: movt [[ADDR]], :upper16:var16
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
-; CHECK-NEXT: cmp r[[OLD]], r0
; Thumb mode: it hi
-; CHECK: movhi r[[NEW]], r[[OLD]]
-; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i16 %old
}
define i32 @test_atomic_load_umax_i32(i32 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_umax_i32:
+; CHECK-ARM-LABEL: test_atomic_load_umax_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB38_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaex r1, [r12]
+; CHECK-ARM-NEXT: mov r3, r0
+; CHECK-ARM-NEXT: cmp r1, r0
+; CHECK-ARM-NEXT: movhi r3, r1
+; CHECK-ARM-NEXT: stlex r2, r3, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB38_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_load_umax_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB38_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaex r1, [r12]
+; CHECK-THUMB-NEXT: mov r3, r0
+; CHECK-THUMB-NEXT: cmp r1, r0
+; CHECK-THUMB-NEXT: it hi
+; CHECK-THUMB-NEXT: movhi r3, r1
+; CHECK-THUMB-NEXT: stlex r2, r3, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB38_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: mov r0, r1
+; CHECK-THUMB-NEXT: bx lr
%old = atomicrmw umax ptr @var32, i32 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
-; CHECK-NEXT: cmp r[[OLD]], r0
; Thumb mode: it hi
-; CHECK: movhi r[[NEW]], r[[OLD]]
-; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: mov r0, r[[OLD]]
+
ret i32 %old
}
define void @test_atomic_load_umax_i64(i64 %offset) nounwind {
-; CHECK-LABEL: test_atomic_load_umax_i64:
+; CHECK-ARM-LE-LABEL: test_atomic_load_umax_i64:
+; CHECK-ARM-LE: @ %bb.0:
+; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: .LBB39_1: @ %atomicrmw.start
+; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-LE-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: mov r7, r1
+; CHECK-ARM-LE-NEXT: subs r3, r0, r4
+; CHECK-ARM-LE-NEXT: sbcs r3, r1, r5
+; CHECK-ARM-LE-NEXT: mov r3, #0
+; CHECK-ARM-LE-NEXT: movwlo r3, #1
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: movne r7, r5
+; CHECK-ARM-LE-NEXT: mov r6, r0
+; CHECK-ARM-LE-NEXT: movne r6, r4
+; CHECK-ARM-LE-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: bne .LBB39_1
+; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-ARM-BE-LABEL: test_atomic_load_umax_i64:
+; CHECK-ARM-BE: @ %bb.0:
+; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: .LBB39_1: @ %atomicrmw.start
+; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-BE-NEXT: ldaexd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: mov r7, r1
+; CHECK-ARM-BE-NEXT: subs r3, r1, r5
+; CHECK-ARM-BE-NEXT: sbcs r3, r0, r4
+; CHECK-ARM-BE-NEXT: mov r3, #0
+; CHECK-ARM-BE-NEXT: movwlo r3, #1
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: movne r7, r5
+; CHECK-ARM-BE-NEXT: mov r6, r0
+; CHECK-ARM-BE-NEXT: movne r6, r4
+; CHECK-ARM-BE-NEXT: stlexd r3, r6, r7, [r2]
+; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: bne .LBB39_1
+; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
+;
+; CHECK-THUMB-LE-LABEL: test_atomic_load_umax_i64:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-LE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-LE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-LE-NEXT: .LBB39_1: @ %atomicrmw.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldaexd r3, lr, [r12]
+; CHECK-THUMB-LE-NEXT: mov r4, r0
+; CHECK-THUMB-LE-NEXT: subs r2, r0, r3
+; CHECK-THUMB-LE-NEXT: sbcs.w r2, r1, lr
+; CHECK-THUMB-LE-NEXT: mov.w r2, #0
+; CHECK-THUMB-LE-NEXT: it lo
+; CHECK-THUMB-LE-NEXT: movlo r2, #1
+; CHECK-THUMB-LE-NEXT: cmp r2, #0
+; CHECK-THUMB-LE-NEXT: mov r2, r1
+; CHECK-THUMB-LE-NEXT: itt ne
+; CHECK-THUMB-LE-NEXT: movne r2, lr
+; CHECK-THUMB-LE-NEXT: movne r4, r3
+; CHECK-THUMB-LE-NEXT: stlexd r5, r4, r2, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB39_1
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-LE-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r7, pc}
+;
+; CHECK-THUMB-BE-LABEL: test_atomic_load_umax_i64:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r7, lr}
+; CHECK-THUMB-BE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-BE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-BE-NEXT: .LBB39_1: @ %atomicrmw.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldaexd r3, lr, [r12]
+; CHECK-THUMB-BE-NEXT: mov r4, r0
+; CHECK-THUMB-BE-NEXT: subs.w r2, r1, lr
+; CHECK-THUMB-BE-NEXT: sbcs.w r2, r0, r3
+; CHECK-THUMB-BE-NEXT: mov.w r2, #0
+; CHECK-THUMB-BE-NEXT: it lo
+; CHECK-THUMB-BE-NEXT: movlo r2, #1
+; CHECK-THUMB-BE-NEXT: cmp r2, #0
+; CHECK-THUMB-BE-NEXT: mov r2, r1
+; CHECK-THUMB-BE-NEXT: itt ne
+; CHECK-THUMB-BE-NEXT: movne r2, lr
+; CHECK-THUMB-BE-NEXT: movne r4, r3
+; CHECK-THUMB-BE-NEXT: stlexd r5, r4, r2, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB39_1
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-BE-NEXT: strd r3, lr, [r12]
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r7, pc}
%old = atomicrmw umax ptr @var64, i64 %offset seq_cst
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
-; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
-; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
-; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
-; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
-; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
-; CHECK-ARM: movwlo [[CMP:r[0-9]+|lr]], #1
-; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
-; CHECK-ARM: movne [[MINHI]], [[OLD2]]
-; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
-; CHECK-ARM: movne [[MINLO]], [[OLD1]]
-; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
-; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_cmpxchg_i8(i8 zeroext %wanted, i8 zeroext %new) nounwind {
-; CHECK-LABEL: test_atomic_cmpxchg_i8:
+; CHECK-ARM-LABEL: test_atomic_cmpxchg_i8:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var8
+; CHECK-ARM-NEXT: movt r12, :upper16:var8
+; CHECK-ARM-NEXT: .LBB40_1: @ %cmpxchg.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexb r2, [r12]
+; CHECK-ARM-NEXT: cmp r2, r0
+; CHECK-ARM-NEXT: bne .LBB40_4
+; CHECK-ARM-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-ARM-NEXT: @ in Loop: Header=BB40_1 Depth=1
+; CHECK-ARM-NEXT: strexb r3, r1, [r12]
+; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: bne .LBB40_1
+; CHECK-ARM-NEXT: @ %bb.3: @ %cmpxchg.end
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+; CHECK-ARM-NEXT: .LBB40_4: @ %cmpxchg.nostore
+; CHECK-ARM-NEXT: clrex
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_cmpxchg_i8:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var8
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: movt r12, :upper16:var8
+; CHECK-THUMB-NEXT: .LBB40_1: @ %cmpxchg.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexb r0, [r12]
+; CHECK-THUMB-NEXT: cmp r0, r2
+; CHECK-THUMB-NEXT: bne .LBB40_3
+; CHECK-THUMB-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-THUMB-NEXT: @ in Loop: Header=BB40_1 Depth=1
+; CHECK-THUMB-NEXT: strexb r3, r1, [r12]
+; CHECK-THUMB-NEXT: cmp r3, #0
+; CHECK-THUMB-NEXT: it eq
+; CHECK-THUMB-NEXT: bxeq lr
+; CHECK-THUMB-NEXT: b .LBB40_1
+; CHECK-THUMB-NEXT: .LBB40_3: @ %cmpxchg.nostore
+; CHECK-THUMB-NEXT: clrex
+; CHECK-THUMB-NEXT: bx lr
%pair = cmpxchg ptr @var8, i8 %wanted, i8 %new acquire acquire
%old = extractvalue { i8, i1 } %pair, 0
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK-DAG: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK-DAG: movt r[[ADDR]], :upper16:var8
-; CHECK-THUMB-DAG: mov r[[WANTED:[0-9]+]], r0
-
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
+
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-ARM-NEXT: cmp r[[OLD]], r0
-; CHECK-THUMB-NEXT: cmp r[[OLD]], r[[WANTED]]
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_{{[0-9]}}
-; CHECK-NEXT: %bb.2:
; As above, r1 is a reasonable guess.
-; CHECK: strexb [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-ARM-NEXT: bne .LBB{{[0-9]+}}_{{[0-9]}}
-; CHECK-THUMB-NEXT: it eq
-; CHECK-THUMB-NEXT: bxeq lr
-; CHECK-ARM: mov r0, r[[OLD]]
-; CHECK-ARM: clrex
-; CHECK: bx lr
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret i8 %old
}
define i16 @test_atomic_cmpxchg_i16(i16 zeroext %wanted, i16 zeroext %new) nounwind {
-; CHECK-LABEL: test_atomic_cmpxchg_i16:
+; CHECK-ARM-LABEL: test_atomic_cmpxchg_i16:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var16
+; CHECK-ARM-NEXT: movt r12, :upper16:var16
+; CHECK-ARM-NEXT: .LBB41_1: @ %cmpxchg.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldaexh r2, [r12]
+; CHECK-ARM-NEXT: cmp r2, r0
+; CHECK-ARM-NEXT: bne .LBB41_4
+; CHECK-ARM-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-ARM-NEXT: @ in Loop: Header=BB41_1 Depth=1
+; CHECK-ARM-NEXT: stlexh r3, r1, [r12]
+; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: bne .LBB41_1
+; CHECK-ARM-NEXT: @ %bb.3: @ %cmpxchg.end
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+; CHECK-ARM-NEXT: .LBB41_4: @ %cmpxchg.nostore
+; CHECK-ARM-NEXT: clrex
+; CHECK-ARM-NEXT: mov r0, r2
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_cmpxchg_i16:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var16
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: movt r12, :upper16:var16
+; CHECK-THUMB-NEXT: .LBB41_1: @ %cmpxchg.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldaexh r0, [r12]
+; CHECK-THUMB-NEXT: cmp r0, r2
+; CHECK-THUMB-NEXT: bne .LBB41_3
+; CHECK-THUMB-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-THUMB-NEXT: @ in Loop: Header=BB41_1 Depth=1
+; CHECK-THUMB-NEXT: stlexh r3, r1, [r12]
+; CHECK-THUMB-NEXT: cmp r3, #0
+; CHECK-THUMB-NEXT: it eq
+; CHECK-THUMB-NEXT: bxeq lr
+; CHECK-THUMB-NEXT: b .LBB41_1
+; CHECK-THUMB-NEXT: .LBB41_3: @ %cmpxchg.nostore
+; CHECK-THUMB-NEXT: clrex
+; CHECK-THUMB-NEXT: bx lr
%pair = cmpxchg ptr @var16, i16 %wanted, i16 %new seq_cst seq_cst
%old = extractvalue { i16, i1 } %pair, 0
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK-DAG: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK-DAG: movt r[[ADDR]], :upper16:var16
-; CHECK-THUMB-DAG: mov r[[WANTED:[0-9]+]], r0
-
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
+
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-ARM-NEXT: cmp r[[OLD]], r0
-; CHECK-THUMB-NEXT: cmp r[[OLD]], r[[WANTED]]
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_{{[0-9]}}
-; CHECK-NEXT: %bb.2:
; As above, r1 is a reasonable guess.
-; CHECK: stlexh [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-ARM-NEXT: bne .LBB{{[0-9]+}}_{{[0-9]}}
-; CHECK-THUMB-NEXT: it eq
-; CHECK-THUMB-NEXT: bxeq lr
-; CHECK-ARM: mov r0, r[[OLD]]
-; CHECK: bx lr
-; CHECK-ARM-NEXT: .LBB{{[0-9]+}}_{{[0-9]}}
-; CHECK-ARM-NEXT: clrex
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK-ARM: mov r0, r[[OLD]]
-; CHECK-ARM-NEXT: bx lr
+
ret i16 %old
}
define void @test_atomic_cmpxchg_i32(i32 %wanted, i32 %new) nounwind {
-; CHECK-LABEL: test_atomic_cmpxchg_i32:
+; CHECK-ARM-LABEL: test_atomic_cmpxchg_i32:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: movw r12, :lower16:var32
+; CHECK-ARM-NEXT: movt r12, :upper16:var32
+; CHECK-ARM-NEXT: .LBB42_1: @ %cmpxchg.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrex r3, [r12]
+; CHECK-ARM-NEXT: cmp r3, r0
+; CHECK-ARM-NEXT: bne .LBB42_4
+; CHECK-ARM-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-ARM-NEXT: @ in Loop: Header=BB42_1 Depth=1
+; CHECK-ARM-NEXT: stlex r2, r1, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
+; CHECK-ARM-NEXT: bne .LBB42_1
+; CHECK-ARM-NEXT: @ %bb.3: @ %cmpxchg.end
+; CHECK-ARM-NEXT: str r3, [r12]
+; CHECK-ARM-NEXT: bx lr
+; CHECK-ARM-NEXT: .LBB42_4: @ %cmpxchg.nostore
+; CHECK-ARM-NEXT: clrex
+; CHECK-ARM-NEXT: str r3, [r12]
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: test_atomic_cmpxchg_i32:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var32
+; CHECK-THUMB-NEXT: movt r12, :upper16:var32
+; CHECK-THUMB-NEXT: .LBB42_1: @ %cmpxchg.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrex r3, [r12]
+; CHECK-THUMB-NEXT: cmp r3, r0
+; CHECK-THUMB-NEXT: bne .LBB42_4
+; CHECK-THUMB-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-THUMB-NEXT: @ in Loop: Header=BB42_1 Depth=1
+; CHECK-THUMB-NEXT: stlex r2, r1, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB42_1
+; CHECK-THUMB-NEXT: @ %bb.3: @ %cmpxchg.end
+; CHECK-THUMB-NEXT: str.w r3, [r12]
+; CHECK-THUMB-NEXT: bx lr
+; CHECK-THUMB-NEXT: .LBB42_4: @ %cmpxchg.nostore
+; CHECK-THUMB-NEXT: clrex
+; CHECK-THUMB-NEXT: str.w r3, [r12]
+; CHECK-THUMB-NEXT: bx lr
%pair = cmpxchg ptr @var32, i32 %wanted, i32 %new release monotonic
%old = extractvalue { i32, i1 } %pair, 0
store i32 %old, ptr @var32
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
-; CHECK: movt r[[ADDR]], :upper16:var32
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
; r0 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-NEXT: cmp r[[OLD]], r0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_4
-; CHECK-NEXT: %bb.2:
; As above, r1 is a reasonable guess.
-; CHECK: stlex [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK: str{{(.w)?}} r[[OLD]],
-; CHECK-NEXT: bx lr
-; CHECK-NEXT: .LBB{{[0-9]+}}_4:
-; CHECK-NEXT: clrex
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK: str{{(.w)?}} r[[OLD]],
-; CHECK-ARM-NEXT: bx lr
+
ret void
}
define void @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind {
-; CHECK-LABEL: test_atomic_cmpxchg_i64:
+; CHECK-ARM-LE-LABEL: test_atomic_cmpxchg_i64:
+; CHECK-ARM-LE: @ %bb.0:
+; CHECK-ARM-LE-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-LE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-LE-NEXT: @ kill: def $r3 killed $r3 killed $r2_r3 def $r2_r3
+; CHECK-ARM-LE-NEXT: movt r12, :upper16:var64
+; CHECK-ARM-LE-NEXT: @ kill: def $r2 killed $r2 killed $r2_r3 def $r2_r3
+; CHECK-ARM-LE-NEXT: .LBB43_1: @ %cmpxchg.start
+; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-LE-NEXT: ldrexd r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: eor lr, r5, r1
+; CHECK-ARM-LE-NEXT: eor r6, r4, r0
+; CHECK-ARM-LE-NEXT: orrs r6, r6, lr
+; CHECK-ARM-LE-NEXT: bne .LBB43_4
+; CHECK-ARM-LE-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-ARM-LE-NEXT: @ in Loop: Header=BB43_1 Depth=1
+; CHECK-ARM-LE-NEXT: strexd r6, r2, r3, [r12]
+; CHECK-ARM-LE-NEXT: cmp r6, #0
+; CHECK-ARM-LE-NEXT: bne .LBB43_1
+; CHECK-ARM-LE-NEXT: @ %bb.3: @ %cmpxchg.end
+; CHECK-ARM-LE-NEXT: strd r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, pc}
+; CHECK-ARM-LE-NEXT: .LBB43_4: @ %cmpxchg.nostore
+; CHECK-ARM-LE-NEXT: clrex
+; CHECK-ARM-LE-NEXT: strd r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, pc}
+;
+; CHECK-ARM-BE-LABEL: test_atomic_cmpxchg_i64:
+; CHECK-ARM-BE: @ %bb.0:
+; CHECK-ARM-BE-NEXT: push {r4, r5, r6, lr}
+; CHECK-ARM-BE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-BE-NEXT: @ kill: def $r3 killed $r3 killed $r2_r3 def $r2_r3
+; CHECK-ARM-BE-NEXT: movt r12, :upper16:var64
+; CHECK-ARM-BE-NEXT: @ kill: def $r2 killed $r2 killed $r2_r3 def $r2_r3
+; CHECK-ARM-BE-NEXT: .LBB43_1: @ %cmpxchg.start
+; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-BE-NEXT: ldrexd r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: eor lr, r4, r0
+; CHECK-ARM-BE-NEXT: eor r6, r5, r1
+; CHECK-ARM-BE-NEXT: orrs r6, r6, lr
+; CHECK-ARM-BE-NEXT: bne .LBB43_4
+; CHECK-ARM-BE-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-ARM-BE-NEXT: @ in Loop: Header=BB43_1 Depth=1
+; CHECK-ARM-BE-NEXT: strexd r6, r2, r3, [r12]
+; CHECK-ARM-BE-NEXT: cmp r6, #0
+; CHECK-ARM-BE-NEXT: bne .LBB43_1
+; CHECK-ARM-BE-NEXT: @ %bb.3: @ %cmpxchg.end
+; CHECK-ARM-BE-NEXT: strd r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, pc}
+; CHECK-ARM-BE-NEXT: .LBB43_4: @ %cmpxchg.nostore
+; CHECK-ARM-BE-NEXT: clrex
+; CHECK-ARM-BE-NEXT: strd r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, pc}
+;
+; CHECK-THUMB-LE-LABEL: test_atomic_cmpxchg_i64:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: push {r4, r5, r6, lr}
+; CHECK-THUMB-LE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-LE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-LE-NEXT: .LBB43_1: @ %cmpxchg.start
+; CHECK-THUMB-LE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-LE-NEXT: ldrexd lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT: eor.w r5, r4, r1
+; CHECK-THUMB-LE-NEXT: eor.w r6, lr, r0
+; CHECK-THUMB-LE-NEXT: orrs r5, r6
+; CHECK-THUMB-LE-NEXT: bne .LBB43_4
+; CHECK-THUMB-LE-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-THUMB-LE-NEXT: @ in Loop: Header=BB43_1 Depth=1
+; CHECK-THUMB-LE-NEXT: strexd r5, r2, r3, [r12]
+; CHECK-THUMB-LE-NEXT: cmp r5, #0
+; CHECK-THUMB-LE-NEXT: bne .LBB43_1
+; CHECK-THUMB-LE-NEXT: @ %bb.3: @ %cmpxchg.end
+; CHECK-THUMB-LE-NEXT: strd lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r6, pc}
+; CHECK-THUMB-LE-NEXT: .LBB43_4: @ %cmpxchg.nostore
+; CHECK-THUMB-LE-NEXT: clrex
+; CHECK-THUMB-LE-NEXT: strd lr, r4, [r12]
+; CHECK-THUMB-LE-NEXT: pop {r4, r5, r6, pc}
+;
+; CHECK-THUMB-BE-LABEL: test_atomic_cmpxchg_i64:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: push {r4, r5, r6, lr}
+; CHECK-THUMB-BE-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-BE-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-BE-NEXT: .LBB43_1: @ %cmpxchg.start
+; CHECK-THUMB-BE-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-BE-NEXT: ldrexd lr, r4, [r12]
+; CHECK-THUMB-BE-NEXT: eor.w r5, lr, r0
+; CHECK-THUMB-BE-NEXT: eor.w r6, r4, r1
+; CHECK-THUMB-BE-NEXT: orrs r5, r6
+; CHECK-THUMB-BE-NEXT: bne .LBB43_4
+; CHECK-THUMB-BE-NEXT: @ %bb.2: @ %cmpxchg.trystore
+; CHECK-THUMB-BE-NEXT: @ in Loop: Header=BB43_1 Depth=1
+; CHECK-THUMB-BE-NEXT: strexd r5, r2, r3, [r12]
+; CHECK-THUMB-BE-NEXT: cmp r5, #0
+; CHECK-THUMB-BE-NEXT: bne .LBB43_1
+; CHECK-THUMB-BE-NEXT: @ %bb.3: @ %cmpxchg.end
+; CHECK-THUMB-BE-NEXT: strd lr, r4, [r12]
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r6, pc}
+; CHECK-THUMB-BE-NEXT: .LBB43_4: @ %cmpxchg.nostore
+; CHECK-THUMB-BE-NEXT: clrex
+; CHECK-THUMB-BE-NEXT: strd lr, r4, [r12]
+; CHECK-THUMB-BE-NEXT: pop {r4, r5, r6, pc}
%pair = cmpxchg ptr @var64, i64 %wanted, i64 %new monotonic monotonic
%old = extractvalue { i64, i1 } %pair, 0
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
-; CHECK: ldrexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK-LE-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
-; CHECK-LE-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
-; CHECK-ARM-LE: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
-; CHECK-THUMB-LE: orrs{{(\.w)?}} {{(r[0-9]+, )?}}[[MISMATCH_HI]], [[MISMATCH_LO]]
-; CHECK-BE-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
-; CHECK-BE-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
-; CHECK-ARM-BE: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_HI]], [[MISMATCH_LO]]
-; CHECK-THUMB-BE: orrs{{(\.w)?}} {{(r[0-9]+, )?}}[[MISMATCH_LO]], [[MISMATCH_HI]]
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_4
-; CHECK-NEXT: %bb.2:
; As above, r2, r3 is a reasonable guess.
-; CHECK: strexd [[STATUS:r[0-9]+]], r2, r3, [r[[ADDR]]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
-; CHECK-NEXT: pop
-; CHECK-NEXT: .LBB{{[0-9]+}}_4:
-; CHECK-NEXT: clrex
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-
-; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
+
store i64 %old, ptr @var64
ret void
}
define i8 @test_atomic_load_monotonic_i8() nounwind {
; CHECK-LABEL: test_atomic_load_monotonic_i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r0, :lower16:var8
+; CHECK-NEXT: movt r0, :upper16:var8
+; CHECK-NEXT: ldrb r0, [r0]
+; CHECK-NEXT: bx lr
%val = load atomic i8, ptr @var8 monotonic, align 1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK: ldrb r0, [r[[ADDR]]]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret i8 %val
}
define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind {
-; CHECK-LABEL: test_atomic_load_monotonic_regoff_i8:
+; CHECK-LE-LABEL: test_atomic_load_monotonic_regoff_i8:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: ldrb r0, [r0, r2]
+; CHECK-LE-NEXT: bx lr
+;
+; CHECK-BE-LABEL: test_atomic_load_monotonic_regoff_i8:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: ldrb r0, [r1, r3]
+; CHECK-BE-NEXT: bx lr
%addr_int = add i64 %base, %off
%addr = inttoptr i64 %addr_int to ptr
%val = load atomic i8, ptr %addr monotonic, align 1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK-LE: ldrb r0, [r0, r2]
-; CHECK-BE: ldrb r0, [r1, r3]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret i8 %val
}
define i8 @test_atomic_load_acquire_i8() nounwind {
; CHECK-LABEL: test_atomic_load_acquire_i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r0, :lower16:var8
+; CHECK-NEXT: movt r0, :upper16:var8
+; CHECK-NEXT: ldab r0, [r0]
+; CHECK-NEXT: bx lr
%val = load atomic i8, ptr @var8 acquire, align 1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: ldab r0, [r[[ADDR]]]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret i8 %val
}
define i8 @test_atomic_load_seq_cst_i8() nounwind {
; CHECK-LABEL: test_atomic_load_seq_cst_i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r0, :lower16:var8
+; CHECK-NEXT: movt r0, :upper16:var8
+; CHECK-NEXT: ldab r0, [r0]
+; CHECK-NEXT: bx lr
%val = load atomic i8, ptr @var8 seq_cst, align 1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: ldab r0, [r[[ADDR]]]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret i8 %val
}
define i16 @test_atomic_load_monotonic_i16() nounwind {
; CHECK-LABEL: test_atomic_load_monotonic_i16:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r0, :lower16:var16
+; CHECK-NEXT: movt r0, :upper16:var16
+; CHECK-NEXT: ldrh r0, [r0]
+; CHECK-NEXT: bx lr
%val = load atomic i16, ptr @var16 monotonic, align 2
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movt r[[ADDR]], :upper16:var16
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: ldrh r0, [r[[ADDR]]]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret i16 %val
}
define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind {
-; CHECK-LABEL: test_atomic_load_monotonic_regoff_i32:
+; CHECK-LE-LABEL: test_atomic_load_monotonic_regoff_i32:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: ldr r0, [r0, r2]
+; CHECK-LE-NEXT: bx lr
+;
+; CHECK-BE-LABEL: test_atomic_load_monotonic_regoff_i32:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: ldr r0, [r1, r3]
+; CHECK-BE-NEXT: bx lr
%addr_int = add i64 %base, %off
%addr = inttoptr i64 %addr_int to ptr
%val = load atomic i32, ptr %addr monotonic, align 4
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK-LE: ldr r0, [r0, r2]
-; CHECK-BE: ldr r0, [r1, r3]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret i32 %val
}
define i64 @test_atomic_load_seq_cst_i64() nounwind {
; CHECK-LABEL: test_atomic_load_seq_cst_i64:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r0, :lower16:var64
+; CHECK-NEXT: movt r0, :upper16:var64
+; CHECK-NEXT: ldaexd r0, r1, [r0]
+; CHECK-NEXT: clrex
+; CHECK-NEXT: bx lr
%val = load atomic i64, ptr @var64 seq_cst, align 8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movt r[[ADDR]], :upper16:var64
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: ldaexd r0, r1, [r[[ADDR]]]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret i64 %val
}
define void @test_atomic_store_monotonic_i8(i8 %val) nounwind {
; CHECK-LABEL: test_atomic_store_monotonic_i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r1, :lower16:var8
+; CHECK-NEXT: movt r1, :upper16:var8
+; CHECK-NEXT: strb r0, [r1]
+; CHECK-NEXT: bx lr
store atomic i8 %val, ptr @var8 monotonic, align 1
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK: strb r0, [r[[ADDR]]]
ret void
}
define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val) nounwind {
-; CHECK-LABEL: test_atomic_store_monotonic_regoff_i8:
+; CHECK-ARM-LE-LABEL: test_atomic_store_monotonic_regoff_i8:
+; CHECK-ARM-LE: @ %bb.0:
+; CHECK-ARM-LE-NEXT: ldrb r1, [sp]
+; CHECK-ARM-LE-NEXT: strb r1, [r0, r2]
+; CHECK-ARM-LE-NEXT: bx lr
+;
+; CHECK-ARM-BE-LABEL: test_atomic_store_monotonic_regoff_i8:
+; CHECK-ARM-BE: @ %bb.0:
+; CHECK-ARM-BE-NEXT: ldrb r0, [sp, #3]
+; CHECK-ARM-BE-NEXT: strb r0, [r1, r3]
+; CHECK-ARM-BE-NEXT: bx lr
+;
+; CHECK-THUMB-LE-LABEL: test_atomic_store_monotonic_regoff_i8:
+; CHECK-THUMB-LE: @ %bb.0:
+; CHECK-THUMB-LE-NEXT: ldrb.w r1, [sp]
+; CHECK-THUMB-LE-NEXT: strb r1, [r0, r2]
+; CHECK-THUMB-LE-NEXT: bx lr
+;
+; CHECK-THUMB-BE-LABEL: test_atomic_store_monotonic_regoff_i8:
+; CHECK-THUMB-BE: @ %bb.0:
+; CHECK-THUMB-BE-NEXT: ldrb.w r0, [sp, #3]
+; CHECK-THUMB-BE-NEXT: strb r0, [r1, r3]
+; CHECK-THUMB-BE-NEXT: bx lr
%addr_int = add i64 %base, %off
%addr = inttoptr i64 %addr_int to ptr
store atomic i8 %val, ptr %addr monotonic, align 1
-; CHECK-LE: ldr{{b?(\.w)?}} [[VAL:r[0-9]+]], [sp]
-; CHECK-LE: strb [[VAL]], [r0, r2]
-; CHECK-BE: ldrb{{(\.w)?}} [[VAL:r[0-9]+]], [sp, #3]
-; CHECK-BE: strb [[VAL]], [r1, r3]
ret void
}
define void @test_atomic_store_release_i8(i8 %val) nounwind {
; CHECK-LABEL: test_atomic_store_release_i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r1, :lower16:var8
+; CHECK-NEXT: movt r1, :upper16:var8
+; CHECK-NEXT: stlb r0, [r1]
+; CHECK-NEXT: bx lr
store atomic i8 %val, ptr @var8 release, align 1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: stlb r0, [r[[ADDR]]]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret void
}
define void @test_atomic_store_seq_cst_i8(i8 %val) nounwind {
; CHECK-LABEL: test_atomic_store_seq_cst_i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r1, :lower16:var8
+; CHECK-NEXT: movt r1, :upper16:var8
+; CHECK-NEXT: stlb r0, [r1]
+; CHECK-NEXT: bx lr
store atomic i8 %val, ptr @var8 seq_cst, align 1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movt r[[ADDR]], :upper16:var8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: stlb r0, [r[[ADDR]]]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret void
}
define void @test_atomic_store_monotonic_i16(i16 %val) nounwind {
; CHECK-LABEL: test_atomic_store_monotonic_i16:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: movw r1, :lower16:var16
+; CHECK-NEXT: movt r1, :upper16:var16
+; CHECK-NEXT: strh r0, [r1]
+; CHECK-NEXT: bx lr
store atomic i16 %val, ptr @var16 monotonic, align 2
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movt r[[ADDR]], :upper16:var16
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: strh r0, [r[[ADDR]]]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret void
}
define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %val) nounwind {
-; CHECK-LABEL: test_atomic_store_monotonic_regoff_i32:
+; CHECK-LE-LABEL: test_atomic_store_monotonic_regoff_i32:
+; CHECK-LE: @ %bb.0:
+; CHECK-LE-NEXT: ldr r1, [sp]
+; CHECK-LE-NEXT: str r1, [r0, r2]
+; CHECK-LE-NEXT: bx lr
+;
+; CHECK-BE-LABEL: test_atomic_store_monotonic_regoff_i32:
+; CHECK-BE: @ %bb.0:
+; CHECK-BE-NEXT: ldr r0, [sp]
+; CHECK-BE-NEXT: str r0, [r1, r3]
+; CHECK-BE-NEXT: bx lr
%addr_int = add i64 %base, %off
%addr = inttoptr i64 %addr_int to ptr
store atomic i32 %val, ptr %addr monotonic, align 4
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: ldr [[VAL:r[0-9]+]], [sp]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK-LE: str [[VAL]], [r0, r2]
-; CHECK-BE: str [[VAL]], [r1, r3]
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret void
}
define void @test_atomic_store_release_i64(i64 %val) nounwind {
-; CHECK-LABEL: test_atomic_store_release_i64:
+; CHECK-ARM-LABEL: test_atomic_store_release_i64:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: push {r4, r5, r11, lr}
+; CHECK-ARM-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-NEXT: @ kill: def $r1 killed $r1 killed $r0_r1 def $r0_r1
+; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: @ kill: def $r0 killed $r0 killed $r0_r1 def $r0_r1
+; CHECK-ARM-NEXT: .LBB57_1: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrexd r4, r5, [r2]
+; CHECK-ARM-NEXT: stlexd r3, r0, r1, [r2]
+; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: bne .LBB57_1
+; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-ARM-NEXT: pop {r4, r5, r11, pc}
+;
+; CHECK-THUMB-LABEL: test_atomic_store_release_i64:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: movw r12, :lower16:var64
+; CHECK-THUMB-NEXT: movt r12, :upper16:var64
+; CHECK-THUMB-NEXT: .LBB57_1: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrexd r3, r2, [r12]
+; CHECK-THUMB-NEXT: stlexd r2, r0, r1, [r12]
+; CHECK-THUMB-NEXT: cmp r2, #0
+; CHECK-THUMB-NEXT: bne .LBB57_1
+; CHECK-THUMB-NEXT: @ %bb.2: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: bx lr
store atomic i64 %val, ptr @var64 release, align 8
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
-; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var64
-; CHECK: movt [[ADDR]], :upper16:var64
-; CHECK: .LBB{{[0-9]+}}_1:
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
; function there.
-; CHECK: stlexd [[STATUS:r[0-9]+]], r0, r1, {{.*}}[[ADDR]]
-; CHECK-NEXT: cmp [[STATUS]], #0
-; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
-; CHECK-NOT: dmb
-; CHECK-NOT: mcr
ret void
}
-define i32 @not.barriers(ptr %var, i1 %cond) {
-; CHECK-LABEL: not.barriers:
+define i32 @not_barriers(ptr %var, i1 %cond) {
+; CHECK-ARM-LABEL: not_barriers:
+; CHECK-ARM: @ %bb.0:
+; CHECK-ARM-NEXT: tst r1, #1
+; CHECK-ARM-NEXT: beq .LBB58_4
+; CHECK-ARM-NEXT: @ %bb.1: @ %atomic_ver
+; CHECK-ARM-NEXT: dmb ish
+; CHECK-ARM-NEXT: .LBB58_2: @ %atomicrmw.start
+; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-ARM-NEXT: ldrex r1, [r0]
+; CHECK-ARM-NEXT: sub r2, r1, #1
+; CHECK-ARM-NEXT: strex r3, r2, [r0]
+; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: bne .LBB58_2
+; CHECK-ARM-NEXT: @ %bb.3: @ %atomicrmw.end
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: dmb ish
+; CHECK-ARM-NEXT: bx lr
+; CHECK-ARM-NEXT: .LBB58_4: @ %simple_ver
+; CHECK-ARM-NEXT: ldr r1, [r0]
+; CHECK-ARM-NEXT: sub r1, r1, #1
+; CHECK-ARM-NEXT: str r1, [r0]
+; CHECK-ARM-NEXT: mov r0, r1
+; CHECK-ARM-NEXT: bx lr
+;
+; CHECK-THUMB-LABEL: not_barriers:
+; CHECK-THUMB: @ %bb.0:
+; CHECK-THUMB-NEXT: mov r2, r0
+; CHECK-THUMB-NEXT: lsls r0, r1, #31
+; CHECK-THUMB-NEXT: itttt eq
+; CHECK-THUMB-NEXT: ldreq r0, [r2]
+; CHECK-THUMB-NEXT: subeq r0, #1
+; CHECK-THUMB-NEXT: streq r0, [r2]
+; CHECK-THUMB-NEXT: bxeq lr
+; CHECK-THUMB-NEXT: .LBB58_1: @ %atomic_ver
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: .LBB58_2: @ %atomicrmw.start
+; CHECK-THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-THUMB-NEXT: ldrex r0, [r2]
+; CHECK-THUMB-NEXT: subs r1, r0, #1
+; CHECK-THUMB-NEXT: strex r3, r1, [r2]
+; CHECK-THUMB-NEXT: cmp r3, #0
+; CHECK-THUMB-NEXT: bne .LBB58_2
+; CHECK-THUMB-NEXT: @ %bb.3: @ %atomicrmw.end
+; CHECK-THUMB-NEXT: dmb ish
+; CHECK-THUMB-NEXT: bx lr
br i1 %cond, label %atomic_ver, label %simple_ver
simple_ver:
%oldval = load i32, ptr %var
@@ -1413,13 +2503,9 @@ atomic_ver:
%val = atomicrmw add ptr %var, i32 -1 monotonic
fence seq_cst
br label %somewhere
-; CHECK: dmb
-; CHECK: ldrex
-; CHECK: dmb
; The key point here is that the second dmb isn't immediately followed by the
; simple_ver basic block, which LLVM attempted to do when DMB had been marked
; with isBarrier. For now, look for something that looks like "somewhere".
-; CHECK-NEXT: {{mov|bx}}
somewhere:
%combined = phi i32 [ %val, %atomic_ver ], [ %newval, %simple_ver]
ret i32 %combined
>From 2527ffa9a3af68646645a26b8bc9fc7a3c2ba613 Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 14 Aug 2024 15:44:42 +0100
Subject: [PATCH 2/3] [RegAllocFast] Allocate use operands in register class
priority order
---
llvm/lib/CodeGen/RegAllocFast.cpp | 41 ++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 62f7ed29c8c819..6feefd87575e05 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -270,6 +270,8 @@ class RegAllocFastImpl {
SmallVector<unsigned, 0> UsedInInstr;
SmallVector<unsigned, 8> DefOperandIndexes;
+ SmallVector<unsigned, 8> UseOperandIndexes;
+
// Register masks attached to the current instruction.
SmallVector<const uint32_t *> RegMasks;
@@ -336,6 +338,7 @@ class RegAllocFastImpl {
Register Reg) const;
void findAndSortDefOperandIndexes(const MachineInstr &MI);
+ void findAndSortUseOperandIndexes(const MachineInstr &MI);
void allocateInstruction(MachineInstr &MI);
void handleDebugValue(MachineInstr &MI);
@@ -1368,6 +1371,40 @@ void RegAllocFastImpl::findAndSortDefOperandIndexes(const MachineInstr &MI) {
});
}
+/// Compute \ref UseOperandIndexes so it contains the indices of "use" operands
+/// that are to be allocated. Those are ordered in a way that high-priority
+/// classes are allocated first.
+void RegAllocFastImpl::findAndSortUseOperandIndexes(const MachineInstr &MI) {
+ UseOperandIndexes.clear();
+
+ for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
+ const MachineOperand &MO = MI.getOperand(I);
+ if (!MO.isReg())
+ continue;
+ Register Reg = MO.getReg();
+ if (MO.isUse() && Reg.isVirtual() && shouldAllocateRegister(Reg))
+ UseOperandIndexes.push_back(I);
+ }
+
+ llvm::sort(UseOperandIndexes, [&](unsigned I0, unsigned I1) {
+ const MachineOperand &MO0 = MI.getOperand(I0);
+ const MachineOperand &MO1 = MI.getOperand(I1);
+ Register Reg0 = MO0.getReg();
+ Register Reg1 = MO1.getReg();
+ const TargetRegisterClass &RC0 = *MRI->getRegClass(Reg0);
+ const TargetRegisterClass &RC1 = *MRI->getRegClass(Reg1);
+
+ // Allocate register classes with a high allocation priority first.
+ if (RC0.AllocationPriority > RC1.AllocationPriority)
+ return true;
+ if (RC0.AllocationPriority < RC1.AllocationPriority)
+ return false;
+
+ // Tie-break rule: operand index.
+ return I0 < I1;
+ });
+}
+
// Returns true if MO is tied and the operand it's tied to is not Undef (not
// Undef is not the same thing as Def).
static bool isTiedToNotUndef(const MachineOperand &MO) {
@@ -1569,7 +1606,9 @@ void RegAllocFastImpl::allocateInstruction(MachineInstr &MI) {
bool ReArrangedImplicitMOs = true;
while (ReArrangedImplicitMOs) {
ReArrangedImplicitMOs = false;
- for (MachineOperand &MO : MI.operands()) {
+ findAndSortUseOperandIndexes(MI);
+ for (unsigned OpIdx : UseOperandIndexes) {
+ MachineOperand &MO = MI.getOperand(OpIdx);
if (!MO.isReg() || !MO.isUse())
continue;
Register Reg = MO.getReg();
>From 33d7fa3aa210b170b7fd7057055dfe24d1339fc1 Mon Sep 17 00:00:00 2001
From: Oliver Stannard <oliver.stannard at arm.com>
Date: Wed, 14 Aug 2024 15:45:26 +0100
Subject: [PATCH 3/3] [ARM] Fix failure to register-allocate CMP_SWAP_64
pseudo-inst
This test case was failing to compile with a "ran out of registers
during register allocation" error at -O0. This was because CMP_SWAP_64
has 3 operands which must be an even-odd register pair, and two other
GPR operands. All of the def operands are also early-clobber, so
registers can't be shared between uses and defs. Because the function
has an over-aligned alloca it needs frame and base pointers, so r6 and
r11 are both reserved. That leaves r0/r1, r2/r3, r4/r5 and r8/r9 as the
only valid register pairs, and if the two individual GPR operands happen
to get allocated to registers in different pairs then only 2 pairs will
be available for the three GPRPair operands.
The fix is to allocate the GPRPair operands first, because once they are
allocated they can't prevent the GPR operands from being allocated.
---
llvm/lib/Target/ARM/ARMRegisterInfo.td | 3 +
.../CodeGen/ARM/atomic-64bit-fast-regalloc.ll | 82 ++++
llvm/test/CodeGen/ARM/atomic-64bit.ll | 400 +++++++++---------
llvm/test/CodeGen/ARM/atomic-ops-v8.ll | 364 ++++++++--------
.../CodeGen/ARM/atomicrmw-uinc-udec-wrap.ll | 60 ++-
5 files changed, 496 insertions(+), 413 deletions(-)
create mode 100644 llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll
diff --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td
index 212f22651f9f94..fc7e591ff44c89 100644
--- a/llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -548,6 +548,9 @@ def Tuples2Rsp : RegisterTuples<[gsub_0, gsub_1],
// Register class representing a pair of even-odd GPRs.
def GPRPair : RegisterClass<"ARM", [untyped], 64, (add Tuples2Rnosp, Tuples2Rsp)> {
let Size = 64; // 2 x 32 bits, we have no predefined type of that size.
+ // GPRPair must be allocated before GPR so that CMP_SWAP_64 can always be
+ // allocated when both the frame pointer and base pointer are reserved.
+ let AllocationPriority = 1;
}
// Register class representing a pair of even-odd GPRs, except (R12, SP).
diff --git a/llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll b/llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll
new file mode 100644
index 00000000000000..e06064a1bf9f32
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/atomic-64bit-fast-regalloc.ll
@@ -0,0 +1,82 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=armv7-none-eabi -O0 | FileCheck %s
+
+;; Previously, this failed during register allocation because the CMP_SWAP_64
+;; pseudo-instruction has a lot of operands, many of which need to be even-odd
+;; register pairs, and the over-aligned alloca in this function causes both a
+;; frame pointer and a base pointer to be needed.
+
+define void @test(ptr %ptr) {
+; CHECK-LABEL: test:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: .save {r4, r5, r6, r8, r9, r10, r11, lr}
+; CHECK-NEXT: push {r4, r5, r6, r8, r9, r10, r11, lr}
+; CHECK-NEXT: .setfp r11, sp, #24
+; CHECK-NEXT: add r11, sp, #24
+; CHECK-NEXT: .pad #16
+; CHECK-NEXT: sub sp, sp, #16
+; CHECK-NEXT: bfc sp, #0, #4
+; CHECK-NEXT: mov r6, sp
+; CHECK-NEXT: str r0, [r6, #12] @ 4-byte Spill
+; CHECK-NEXT: b .LBB0_1
+; CHECK-NEXT: .LBB0_1: @ %block1
+; CHECK-NEXT: ldr r0, [r6, #12] @ 4-byte Reload
+; CHECK-NEXT: mov r1, sp
+; CHECK-NEXT: sub r1, r1, #16
+; CHECK-NEXT: bic r1, r1, #15
+; CHECK-NEXT: mov sp, r1
+; CHECK-NEXT: dmb ish
+; CHECK-NEXT: ldr r1, [r0]
+; CHECK-NEXT: ldr r0, [r0, #4]
+; CHECK-NEXT: str r1, [r6, #4] @ 4-byte Spill
+; CHECK-NEXT: str r0, [r6, #8] @ 4-byte Spill
+; CHECK-NEXT: b .LBB0_2
+; CHECK-NEXT: .LBB0_2: @ %atomicrmw.start
+; CHECK-NEXT: @ =>This Loop Header: Depth=1
+; CHECK-NEXT: @ Child Loop BB0_3 Depth 2
+; CHECK-NEXT: ldr r1, [r6, #8] @ 4-byte Reload
+; CHECK-NEXT: ldr r8, [r6, #4] @ 4-byte Reload
+; CHECK-NEXT: ldr r12, [r6, #12] @ 4-byte Reload
+; CHECK-NEXT: str r8, [r6] @ 4-byte Spill
+; CHECK-NEXT: @ kill: def $r8 killed $r8 def $r8_r9
+; CHECK-NEXT: mov r9, r1
+; CHECK-NEXT: mov r0, #0
+; CHECK-NEXT: mov r2, r0
+; CHECK-NEXT: mov r3, r0
+; CHECK-NEXT: .LBB0_3: @ %atomicrmw.start
+; CHECK-NEXT: @ Parent Loop BB0_2 Depth=1
+; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+; CHECK-NEXT: ldrexd r4, r5, [r12]
+; CHECK-NEXT: cmp r4, r8
+; CHECK-NEXT: cmpeq r5, r9
+; CHECK-NEXT: bne .LBB0_5
+; CHECK-NEXT: @ %bb.4: @ %atomicrmw.start
+; CHECK-NEXT: @ in Loop: Header=BB0_3 Depth=2
+; CHECK-NEXT: strexd r0, r2, r3, [r12]
+; CHECK-NEXT: cmp r0, #0
+; CHECK-NEXT: bne .LBB0_3
+; CHECK-NEXT: .LBB0_5: @ %atomicrmw.start
+; CHECK-NEXT: @ in Loop: Header=BB0_2 Depth=1
+; CHECK-NEXT: ldr r2, [r6] @ 4-byte Reload
+; CHECK-NEXT: mov r0, r5
+; CHECK-NEXT: eor r3, r0, r1
+; CHECK-NEXT: mov r1, r4
+; CHECK-NEXT: eor r2, r1, r2
+; CHECK-NEXT: orr r2, r2, r3
+; CHECK-NEXT: cmp r2, #0
+; CHECK-NEXT: str r1, [r6, #4] @ 4-byte Spill
+; CHECK-NEXT: str r0, [r6, #8] @ 4-byte Spill
+; CHECK-NEXT: bne .LBB0_2
+; CHECK-NEXT: b .LBB0_6
+; CHECK-NEXT: .LBB0_6: @ %atomicrmw.end
+; CHECK-NEXT: dmb ish
+; CHECK-NEXT: sub sp, r11, #24
+; CHECK-NEXT: pop {r4, r5, r6, r8, r9, r10, r11, pc}
+entry:
+ br label %block1
+
+block1:
+ %stuff = alloca i8, i64 16, align 16
+ store atomic i64 0, ptr %ptr seq_cst, align 8
+ ret void
+}
diff --git a/llvm/test/CodeGen/ARM/atomic-64bit.ll b/llvm/test/CodeGen/ARM/atomic-64bit.ll
index 80658bdb9fda0a..84f1559fee14af 100644
--- a/llvm/test/CodeGen/ARM/atomic-64bit.ll
+++ b/llvm/test/CodeGen/ARM/atomic-64bit.ll
@@ -9,21 +9,21 @@
define i64 @test1(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test1:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB0_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: adds r6, r4, r1
-; CHECK-LE-NEXT: adc r7, r5, r2
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: adds r4, r0, r9
+; CHECK-LE-NEXT: adc r5, r1, r2
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB0_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LE-LABEL: test1:
; CHECK-THUMB-LE: @ %bb.0:
@@ -45,21 +45,21 @@ define i64 @test1(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test1:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB0_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: adds r7, r5, r2
-; CHECK-BE-NEXT: adc r6, r4, r1
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: adds r5, r1, r2
+; CHECK-BE-NEXT: adc r4, r0, r12
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB0_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-BE-LABEL: test1:
; CHECK-THUMB-BE: @ %bb.0:
@@ -113,21 +113,21 @@ define i64 @test1(ptr %ptr, i64 %val) {
define i64 @test2(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test2:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB1_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: subs r6, r4, r1
-; CHECK-LE-NEXT: sbc r7, r5, r2
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: subs r4, r0, r9
+; CHECK-LE-NEXT: sbc r5, r1, r2
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB1_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LE-LABEL: test2:
; CHECK-THUMB-LE: @ %bb.0:
@@ -149,21 +149,21 @@ define i64 @test2(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test2:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB1_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: subs r7, r5, r2
-; CHECK-BE-NEXT: sbc r6, r4, r1
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: subs r5, r1, r2
+; CHECK-BE-NEXT: sbc r4, r0, r12
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB1_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-BE-LABEL: test2:
; CHECK-THUMB-BE: @ %bb.0:
@@ -217,21 +217,21 @@ define i64 @test2(ptr %ptr, i64 %val) {
define i64 @test3(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test3:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB2_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: and r6, r4, r1
-; CHECK-LE-NEXT: and r7, r5, r2
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: and r4, r0, r9
+; CHECK-LE-NEXT: and r5, r1, r2
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB2_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LABEL: test3:
; CHECK-THUMB: @ %bb.0:
@@ -253,21 +253,21 @@ define i64 @test3(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test3:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB2_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: and r6, r4, r1
-; CHECK-BE-NEXT: and r7, r5, r2
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: and r4, r0, r12
+; CHECK-BE-NEXT: and r5, r1, r2
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB2_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-7M-LABEL: test3:
; CHECK-7M: @ %bb.0:
@@ -303,21 +303,21 @@ define i64 @test3(ptr %ptr, i64 %val) {
define i64 @test4(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test4:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB3_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: orr r6, r4, r1
-; CHECK-LE-NEXT: orr r7, r5, r2
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: orr r4, r0, r9
+; CHECK-LE-NEXT: orr r5, r1, r2
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB3_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LABEL: test4:
; CHECK-THUMB: @ %bb.0:
@@ -339,21 +339,21 @@ define i64 @test4(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test4:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB3_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: orr r6, r4, r1
-; CHECK-BE-NEXT: orr r7, r5, r2
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: orr r4, r0, r12
+; CHECK-BE-NEXT: orr r5, r1, r2
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB3_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-7M-LABEL: test4:
; CHECK-7M: @ %bb.0:
@@ -389,21 +389,21 @@ define i64 @test4(ptr %ptr, i64 %val) {
define i64 @test5(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test5:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB4_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: eor r6, r4, r1
-; CHECK-LE-NEXT: eor r7, r5, r2
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: eor r4, r0, r9
+; CHECK-LE-NEXT: eor r5, r1, r2
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB4_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LABEL: test5:
; CHECK-THUMB: @ %bb.0:
@@ -425,21 +425,21 @@ define i64 @test5(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test5:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB4_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: eor r6, r4, r1
-; CHECK-BE-NEXT: eor r7, r5, r2
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: eor r4, r0, r12
+; CHECK-BE-NEXT: eor r5, r1, r2
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB4_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-7M-LABEL: test5:
; CHECK-7M: @ %bb.0:
@@ -846,28 +846,28 @@ define void @test9(ptr %ptr, i64 %val) {
define i64 @test10(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test10:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB9_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: mov r7, r2
-; CHECK-LE-NEXT: subs r3, r1, r4
-; CHECK-LE-NEXT: sbcs r3, r2, r5
-; CHECK-LE-NEXT: mov r3, #0
-; CHECK-LE-NEXT: movwge r3, #1
-; CHECK-LE-NEXT: cmp r3, #0
-; CHECK-LE-NEXT: movne r7, r5
-; CHECK-LE-NEXT: mov r6, r1
-; CHECK-LE-NEXT: movne r6, r4
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: subs r5, r9, r0
+; CHECK-LE-NEXT: sbcs r5, r2, r1
+; CHECK-LE-NEXT: mov r5, #0
+; CHECK-LE-NEXT: movwge r5, #1
+; CHECK-LE-NEXT: cmp r5, #0
+; CHECK-LE-NEXT: mov r5, r2
+; CHECK-LE-NEXT: movne r5, r1
+; CHECK-LE-NEXT: mov r4, r9
+; CHECK-LE-NEXT: movne r4, r0
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB9_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LE-LABEL: test10:
; CHECK-THUMB-LE: @ %bb.0:
@@ -898,28 +898,28 @@ define i64 @test10(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test10:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB9_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: mov r7, r2
-; CHECK-BE-NEXT: subs r3, r2, r5
-; CHECK-BE-NEXT: sbcs r3, r1, r4
-; CHECK-BE-NEXT: mov r3, #0
-; CHECK-BE-NEXT: movwge r3, #1
-; CHECK-BE-NEXT: cmp r3, #0
-; CHECK-BE-NEXT: movne r7, r5
-; CHECK-BE-NEXT: mov r6, r1
-; CHECK-BE-NEXT: movne r6, r4
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: subs r5, r2, r1
+; CHECK-BE-NEXT: sbcs r5, r12, r0
+; CHECK-BE-NEXT: mov r5, #0
+; CHECK-BE-NEXT: movwge r5, #1
+; CHECK-BE-NEXT: cmp r5, #0
+; CHECK-BE-NEXT: mov r5, r2
+; CHECK-BE-NEXT: movne r5, r1
+; CHECK-BE-NEXT: mov r4, r12
+; CHECK-BE-NEXT: movne r4, r0
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB9_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-BE-LABEL: test10:
; CHECK-THUMB-BE: @ %bb.0:
@@ -1033,28 +1033,28 @@ define i64 @test10(ptr %ptr, i64 %val) {
define i64 @test11(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test11:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB10_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: mov r7, r2
-; CHECK-LE-NEXT: subs r3, r1, r4
-; CHECK-LE-NEXT: sbcs r3, r2, r5
-; CHECK-LE-NEXT: mov r3, #0
-; CHECK-LE-NEXT: movwhs r3, #1
-; CHECK-LE-NEXT: cmp r3, #0
-; CHECK-LE-NEXT: movne r7, r5
-; CHECK-LE-NEXT: mov r6, r1
-; CHECK-LE-NEXT: movne r6, r4
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: subs r5, r9, r0
+; CHECK-LE-NEXT: sbcs r5, r2, r1
+; CHECK-LE-NEXT: mov r5, #0
+; CHECK-LE-NEXT: movwhs r5, #1
+; CHECK-LE-NEXT: cmp r5, #0
+; CHECK-LE-NEXT: mov r5, r2
+; CHECK-LE-NEXT: movne r5, r1
+; CHECK-LE-NEXT: mov r4, r9
+; CHECK-LE-NEXT: movne r4, r0
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB10_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LE-LABEL: test11:
; CHECK-THUMB-LE: @ %bb.0:
@@ -1085,28 +1085,28 @@ define i64 @test11(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test11:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB10_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: mov r7, r2
-; CHECK-BE-NEXT: subs r3, r2, r5
-; CHECK-BE-NEXT: sbcs r3, r1, r4
-; CHECK-BE-NEXT: mov r3, #0
-; CHECK-BE-NEXT: movwhs r3, #1
-; CHECK-BE-NEXT: cmp r3, #0
-; CHECK-BE-NEXT: movne r7, r5
-; CHECK-BE-NEXT: mov r6, r1
-; CHECK-BE-NEXT: movne r6, r4
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: subs r5, r2, r1
+; CHECK-BE-NEXT: sbcs r5, r12, r0
+; CHECK-BE-NEXT: mov r5, #0
+; CHECK-BE-NEXT: movwhs r5, #1
+; CHECK-BE-NEXT: cmp r5, #0
+; CHECK-BE-NEXT: mov r5, r2
+; CHECK-BE-NEXT: movne r5, r1
+; CHECK-BE-NEXT: mov r4, r12
+; CHECK-BE-NEXT: movne r4, r0
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB10_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-BE-LABEL: test11:
; CHECK-THUMB-BE: @ %bb.0:
@@ -1220,28 +1220,28 @@ define i64 @test11(ptr %ptr, i64 %val) {
define i64 @test12(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test12:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB11_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: mov r7, r2
-; CHECK-LE-NEXT: subs r3, r1, r4
-; CHECK-LE-NEXT: sbcs r3, r2, r5
-; CHECK-LE-NEXT: mov r3, #0
-; CHECK-LE-NEXT: movwlt r3, #1
-; CHECK-LE-NEXT: cmp r3, #0
-; CHECK-LE-NEXT: movne r7, r5
-; CHECK-LE-NEXT: mov r6, r1
-; CHECK-LE-NEXT: movne r6, r4
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: subs r5, r9, r0
+; CHECK-LE-NEXT: sbcs r5, r2, r1
+; CHECK-LE-NEXT: mov r5, #0
+; CHECK-LE-NEXT: movwlt r5, #1
+; CHECK-LE-NEXT: cmp r5, #0
+; CHECK-LE-NEXT: mov r5, r2
+; CHECK-LE-NEXT: movne r5, r1
+; CHECK-LE-NEXT: mov r4, r9
+; CHECK-LE-NEXT: movne r4, r0
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB11_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LE-LABEL: test12:
; CHECK-THUMB-LE: @ %bb.0:
@@ -1272,28 +1272,28 @@ define i64 @test12(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test12:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB11_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: mov r7, r2
-; CHECK-BE-NEXT: subs r3, r2, r5
-; CHECK-BE-NEXT: sbcs r3, r1, r4
-; CHECK-BE-NEXT: mov r3, #0
-; CHECK-BE-NEXT: movwlt r3, #1
-; CHECK-BE-NEXT: cmp r3, #0
-; CHECK-BE-NEXT: movne r7, r5
-; CHECK-BE-NEXT: mov r6, r1
-; CHECK-BE-NEXT: movne r6, r4
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: subs r5, r2, r1
+; CHECK-BE-NEXT: sbcs r5, r12, r0
+; CHECK-BE-NEXT: mov r5, #0
+; CHECK-BE-NEXT: movwlt r5, #1
+; CHECK-BE-NEXT: cmp r5, #0
+; CHECK-BE-NEXT: mov r5, r2
+; CHECK-BE-NEXT: movne r5, r1
+; CHECK-BE-NEXT: mov r4, r12
+; CHECK-BE-NEXT: movne r4, r0
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB11_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-BE-LABEL: test12:
; CHECK-THUMB-BE: @ %bb.0:
@@ -1407,28 +1407,28 @@ define i64 @test12(ptr %ptr, i64 %val) {
define i64 @test13(ptr %ptr, i64 %val) {
; CHECK-LE-LABEL: test13:
; CHECK-LE: @ %bb.0:
-; CHECK-LE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-LE-NEXT: push {r4, r5, lr}
+; CHECK-LE-NEXT: mov r9, r1
+; CHECK-LE-NEXT: mov r12, r0
; CHECK-LE-NEXT: dmb ish
; CHECK-LE-NEXT: LBB12_1: @ %atomicrmw.start
; CHECK-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-LE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-LE-NEXT: mov r7, r2
-; CHECK-LE-NEXT: subs r3, r1, r4
-; CHECK-LE-NEXT: sbcs r3, r2, r5
-; CHECK-LE-NEXT: mov r3, #0
-; CHECK-LE-NEXT: movwlo r3, #1
-; CHECK-LE-NEXT: cmp r3, #0
-; CHECK-LE-NEXT: movne r7, r5
-; CHECK-LE-NEXT: mov r6, r1
-; CHECK-LE-NEXT: movne r6, r4
-; CHECK-LE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-LE-NEXT: ldrexd r0, r1, [r12]
+; CHECK-LE-NEXT: subs r5, r9, r0
+; CHECK-LE-NEXT: sbcs r5, r2, r1
+; CHECK-LE-NEXT: mov r5, #0
+; CHECK-LE-NEXT: movwlo r5, #1
+; CHECK-LE-NEXT: cmp r5, #0
+; CHECK-LE-NEXT: mov r5, r2
+; CHECK-LE-NEXT: movne r5, r1
+; CHECK-LE-NEXT: mov r4, r9
+; CHECK-LE-NEXT: movne r4, r0
+; CHECK-LE-NEXT: strexd r3, r4, r5, [r12]
; CHECK-LE-NEXT: cmp r3, #0
; CHECK-LE-NEXT: bne LBB12_1
; CHECK-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-LE-NEXT: mov r0, r4
-; CHECK-LE-NEXT: mov r1, r5
; CHECK-LE-NEXT: dmb ish
-; CHECK-LE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-LE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-LE-LABEL: test13:
; CHECK-THUMB-LE: @ %bb.0:
@@ -1459,28 +1459,28 @@ define i64 @test13(ptr %ptr, i64 %val) {
;
; CHECK-BE-LABEL: test13:
; CHECK-BE: @ %bb.0:
-; CHECK-BE-NEXT: push {r4, r5, r6, r7, lr}
+; CHECK-BE-NEXT: push {r4, r5, lr}
+; CHECK-BE-NEXT: mov r12, r1
+; CHECK-BE-NEXT: mov lr, r0
; CHECK-BE-NEXT: dmb ish
; CHECK-BE-NEXT: .LBB12_1: @ %atomicrmw.start
; CHECK-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-BE-NEXT: ldrexd r4, r5, [r0]
-; CHECK-BE-NEXT: mov r7, r2
-; CHECK-BE-NEXT: subs r3, r2, r5
-; CHECK-BE-NEXT: sbcs r3, r1, r4
-; CHECK-BE-NEXT: mov r3, #0
-; CHECK-BE-NEXT: movwlo r3, #1
-; CHECK-BE-NEXT: cmp r3, #0
-; CHECK-BE-NEXT: movne r7, r5
-; CHECK-BE-NEXT: mov r6, r1
-; CHECK-BE-NEXT: movne r6, r4
-; CHECK-BE-NEXT: strexd r3, r6, r7, [r0]
+; CHECK-BE-NEXT: ldrexd r0, r1, [lr]
+; CHECK-BE-NEXT: subs r5, r2, r1
+; CHECK-BE-NEXT: sbcs r5, r12, r0
+; CHECK-BE-NEXT: mov r5, #0
+; CHECK-BE-NEXT: movwlo r5, #1
+; CHECK-BE-NEXT: cmp r5, #0
+; CHECK-BE-NEXT: mov r5, r2
+; CHECK-BE-NEXT: movne r5, r1
+; CHECK-BE-NEXT: mov r4, r12
+; CHECK-BE-NEXT: movne r4, r0
+; CHECK-BE-NEXT: strexd r3, r4, r5, [lr]
; CHECK-BE-NEXT: cmp r3, #0
; CHECK-BE-NEXT: bne .LBB12_1
; CHECK-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-BE-NEXT: mov r0, r4
-; CHECK-BE-NEXT: mov r1, r5
; CHECK-BE-NEXT: dmb ish
-; CHECK-BE-NEXT: pop {r4, r5, r6, r7, pc}
+; CHECK-BE-NEXT: pop {r4, r5, pc}
;
; CHECK-THUMB-BE-LABEL: test13:
; CHECK-THUMB-BE: @ %bb.0:
diff --git a/llvm/test/CodeGen/ARM/atomic-ops-v8.ll b/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
index c7d4cf5912d179..cc760d59c20454 100644
--- a/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
+++ b/llvm/test/CodeGen/ARM/atomic-ops-v8.ll
@@ -127,35 +127,35 @@ define void @test_atomic_load_add_i64(i64 %offset) nounwind {
; CHECK-ARM-LE-LABEL: test_atomic_load_add_i64:
; CHECK-ARM-LE: @ %bb.0:
; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-LE-NEXT: .LBB3_1: @ %atomicrmw.start
; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-LE-NEXT: ldrexd r4, r5, [r2]
-; CHECK-ARM-LE-NEXT: adds r6, r4, r0
-; CHECK-ARM-LE-NEXT: adc r7, r5, r1
-; CHECK-ARM-LE-NEXT: strexd r3, r6, r7, [r2]
-; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: ldrexd r6, r7, [r12]
+; CHECK-ARM-LE-NEXT: adds r4, r6, r0
+; CHECK-ARM-LE-NEXT: adc r5, r7, r1
+; CHECK-ARM-LE-NEXT: strexd r2, r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: cmp r2, #0
; CHECK-ARM-LE-NEXT: bne .LBB3_1
; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-ARM-BE-LABEL: test_atomic_load_add_i64:
; CHECK-ARM-BE: @ %bb.0:
; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-BE-NEXT: .LBB3_1: @ %atomicrmw.start
; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-BE-NEXT: ldrexd r4, r5, [r2]
-; CHECK-ARM-BE-NEXT: adds r7, r5, r1
-; CHECK-ARM-BE-NEXT: adc r6, r4, r0
-; CHECK-ARM-BE-NEXT: strexd r3, r6, r7, [r2]
-; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: ldrexd r6, r7, [r12]
+; CHECK-ARM-BE-NEXT: adds r5, r7, r1
+; CHECK-ARM-BE-NEXT: adc r4, r6, r0
+; CHECK-ARM-BE-NEXT: strexd r2, r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: cmp r2, #0
; CHECK-ARM-BE-NEXT: bne .LBB3_1
; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LE-LABEL: test_atomic_load_add_i64:
@@ -318,35 +318,35 @@ define void @test_atomic_load_sub_i64(i64 %offset) nounwind {
; CHECK-ARM-LE-LABEL: test_atomic_load_sub_i64:
; CHECK-ARM-LE: @ %bb.0:
; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-LE-NEXT: .LBB7_1: @ %atomicrmw.start
; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-LE-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-LE-NEXT: subs r6, r4, r0
-; CHECK-ARM-LE-NEXT: sbc r7, r5, r1
-; CHECK-ARM-LE-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-LE-NEXT: subs r4, r6, r0
+; CHECK-ARM-LE-NEXT: sbc r5, r7, r1
+; CHECK-ARM-LE-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: cmp r2, #0
; CHECK-ARM-LE-NEXT: bne .LBB7_1
; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-ARM-BE-LABEL: test_atomic_load_sub_i64:
; CHECK-ARM-BE: @ %bb.0:
; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-BE-NEXT: .LBB7_1: @ %atomicrmw.start
; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-BE-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-BE-NEXT: subs r7, r5, r1
-; CHECK-ARM-BE-NEXT: sbc r6, r4, r0
-; CHECK-ARM-BE-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-BE-NEXT: subs r5, r7, r1
+; CHECK-ARM-BE-NEXT: sbc r4, r6, r0
+; CHECK-ARM-BE-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: cmp r2, #0
; CHECK-ARM-BE-NEXT: bne .LBB7_1
; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LE-LABEL: test_atomic_load_sub_i64:
@@ -509,18 +509,18 @@ define void @test_atomic_load_and_i64(i64 %offset) nounwind {
; CHECK-ARM-LABEL: test_atomic_load_and_i64:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-NEXT: movt r12, :upper16:var64
; CHECK-ARM-NEXT: .LBB11_1: @ %atomicrmw.start
; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-NEXT: and r7, r5, r1
-; CHECK-ARM-NEXT: and r6, r4, r0
-; CHECK-ARM-NEXT: strexd r3, r6, r7, [r2]
-; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-NEXT: and r5, r7, r1
+; CHECK-ARM-NEXT: and r4, r6, r0
+; CHECK-ARM-NEXT: strexd r2, r4, r5, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
; CHECK-ARM-NEXT: bne .LBB11_1
; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-NEXT: strd r6, r7, [r12]
; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LABEL: test_atomic_load_and_i64:
@@ -666,18 +666,18 @@ define void @test_atomic_load_or_i64(i64 %offset) nounwind {
; CHECK-ARM-LABEL: test_atomic_load_or_i64:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-NEXT: movt r12, :upper16:var64
; CHECK-ARM-NEXT: .LBB15_1: @ %atomicrmw.start
; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-NEXT: ldrexd r4, r5, [r2]
-; CHECK-ARM-NEXT: orr r7, r5, r1
-; CHECK-ARM-NEXT: orr r6, r4, r0
-; CHECK-ARM-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: ldrexd r6, r7, [r12]
+; CHECK-ARM-NEXT: orr r5, r7, r1
+; CHECK-ARM-NEXT: orr r4, r6, r0
+; CHECK-ARM-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
; CHECK-ARM-NEXT: bne .LBB15_1
; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-NEXT: strd r6, r7, [r12]
; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LABEL: test_atomic_load_or_i64:
@@ -823,18 +823,18 @@ define void @test_atomic_load_xor_i64(i64 %offset) nounwind {
; CHECK-ARM-LABEL: test_atomic_load_xor_i64:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-NEXT: movt r12, :upper16:var64
; CHECK-ARM-NEXT: .LBB19_1: @ %atomicrmw.start
; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-NEXT: ldrexd r4, r5, [r2]
-; CHECK-ARM-NEXT: eor r7, r5, r1
-; CHECK-ARM-NEXT: eor r6, r4, r0
-; CHECK-ARM-NEXT: strexd r3, r6, r7, [r2]
-; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: ldrexd r6, r7, [r12]
+; CHECK-ARM-NEXT: eor r5, r7, r1
+; CHECK-ARM-NEXT: eor r4, r6, r0
+; CHECK-ARM-NEXT: strexd r2, r4, r5, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
; CHECK-ARM-NEXT: bne .LBB19_1
; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-NEXT: strd r6, r7, [r12]
; CHECK-ARM-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LABEL: test_atomic_load_xor_i64:
@@ -932,18 +932,18 @@ define void @test_atomic_load_xchg_i64(i64 %offset) nounwind {
; CHECK-ARM-LABEL: test_atomic_load_xchg_i64:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: push {r4, r5, r11, lr}
-; CHECK-ARM-NEXT: movw r2, :lower16:var64
+; CHECK-ARM-NEXT: movw r12, :lower16:var64
; CHECK-ARM-NEXT: @ kill: def $r1 killed $r1 killed $r0_r1 def $r0_r1
-; CHECK-ARM-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-NEXT: movt r12, :upper16:var64
; CHECK-ARM-NEXT: @ kill: def $r0 killed $r0 killed $r0_r1 def $r0_r1
; CHECK-ARM-NEXT: .LBB23_1: @ %atomicrmw.start
; CHECK-ARM-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-NEXT: strexd r3, r0, r1, [r2]
-; CHECK-ARM-NEXT: cmp r3, #0
+; CHECK-ARM-NEXT: ldaexd r4, r5, [r12]
+; CHECK-ARM-NEXT: strexd r2, r0, r1, [r12]
+; CHECK-ARM-NEXT: cmp r2, #0
; CHECK-ARM-NEXT: bne .LBB23_1
; CHECK-ARM-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-NEXT: strd r4, r5, [r12]
; CHECK-ARM-NEXT: pop {r4, r5, r11, pc}
;
; CHECK-THUMB-LABEL: test_atomic_load_xchg_i64:
@@ -1109,49 +1109,49 @@ define void @test_atomic_load_min_i64(i64 %offset) nounwind {
; CHECK-ARM-LE-LABEL: test_atomic_load_min_i64:
; CHECK-ARM-LE: @ %bb.0:
; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-LE-NEXT: .LBB27_1: @ %atomicrmw.start
; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-LE-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-LE-NEXT: mov r7, r1
-; CHECK-ARM-LE-NEXT: subs r3, r0, r4
-; CHECK-ARM-LE-NEXT: sbcs r3, r1, r5
-; CHECK-ARM-LE-NEXT: mov r3, #0
-; CHECK-ARM-LE-NEXT: movwge r3, #1
-; CHECK-ARM-LE-NEXT: cmp r3, #0
-; CHECK-ARM-LE-NEXT: movne r7, r5
-; CHECK-ARM-LE-NEXT: mov r6, r0
-; CHECK-ARM-LE-NEXT: movne r6, r4
-; CHECK-ARM-LE-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-LE-NEXT: subs r5, r0, r6
+; CHECK-ARM-LE-NEXT: sbcs r5, r1, r7
+; CHECK-ARM-LE-NEXT: mov r5, #0
+; CHECK-ARM-LE-NEXT: movwge r5, #1
+; CHECK-ARM-LE-NEXT: cmp r5, #0
+; CHECK-ARM-LE-NEXT: mov r5, r1
+; CHECK-ARM-LE-NEXT: movne r5, r7
+; CHECK-ARM-LE-NEXT: mov r4, r0
+; CHECK-ARM-LE-NEXT: movne r4, r6
+; CHECK-ARM-LE-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: cmp r2, #0
; CHECK-ARM-LE-NEXT: bne .LBB27_1
; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-ARM-BE-LABEL: test_atomic_load_min_i64:
; CHECK-ARM-BE: @ %bb.0:
; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-BE-NEXT: .LBB27_1: @ %atomicrmw.start
; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-BE-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-BE-NEXT: mov r7, r1
-; CHECK-ARM-BE-NEXT: subs r3, r1, r5
-; CHECK-ARM-BE-NEXT: sbcs r3, r0, r4
-; CHECK-ARM-BE-NEXT: mov r3, #0
-; CHECK-ARM-BE-NEXT: movwge r3, #1
-; CHECK-ARM-BE-NEXT: cmp r3, #0
-; CHECK-ARM-BE-NEXT: movne r7, r5
-; CHECK-ARM-BE-NEXT: mov r6, r0
-; CHECK-ARM-BE-NEXT: movne r6, r4
-; CHECK-ARM-BE-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-BE-NEXT: subs r5, r1, r7
+; CHECK-ARM-BE-NEXT: sbcs r5, r0, r6
+; CHECK-ARM-BE-NEXT: mov r5, #0
+; CHECK-ARM-BE-NEXT: movwge r5, #1
+; CHECK-ARM-BE-NEXT: cmp r5, #0
+; CHECK-ARM-BE-NEXT: mov r5, r1
+; CHECK-ARM-BE-NEXT: movne r5, r7
+; CHECK-ARM-BE-NEXT: mov r4, r0
+; CHECK-ARM-BE-NEXT: movne r4, r6
+; CHECK-ARM-BE-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: cmp r2, #0
; CHECK-ARM-BE-NEXT: bne .LBB27_1
; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LE-LABEL: test_atomic_load_min_i64:
@@ -1354,49 +1354,49 @@ define void @test_atomic_load_max_i64(i64 %offset) nounwind {
; CHECK-ARM-LE-LABEL: test_atomic_load_max_i64:
; CHECK-ARM-LE: @ %bb.0:
; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-LE-NEXT: .LBB31_1: @ %atomicrmw.start
; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-LE-NEXT: ldrexd r4, r5, [r2]
-; CHECK-ARM-LE-NEXT: mov r7, r1
-; CHECK-ARM-LE-NEXT: subs r3, r0, r4
-; CHECK-ARM-LE-NEXT: sbcs r3, r1, r5
-; CHECK-ARM-LE-NEXT: mov r3, #0
-; CHECK-ARM-LE-NEXT: movwlt r3, #1
-; CHECK-ARM-LE-NEXT: cmp r3, #0
-; CHECK-ARM-LE-NEXT: movne r7, r5
-; CHECK-ARM-LE-NEXT: mov r6, r0
-; CHECK-ARM-LE-NEXT: movne r6, r4
-; CHECK-ARM-LE-NEXT: strexd r3, r6, r7, [r2]
-; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: ldrexd r6, r7, [r12]
+; CHECK-ARM-LE-NEXT: subs r5, r0, r6
+; CHECK-ARM-LE-NEXT: sbcs r5, r1, r7
+; CHECK-ARM-LE-NEXT: mov r5, #0
+; CHECK-ARM-LE-NEXT: movwlt r5, #1
+; CHECK-ARM-LE-NEXT: cmp r5, #0
+; CHECK-ARM-LE-NEXT: mov r5, r1
+; CHECK-ARM-LE-NEXT: movne r5, r7
+; CHECK-ARM-LE-NEXT: mov r4, r0
+; CHECK-ARM-LE-NEXT: movne r4, r6
+; CHECK-ARM-LE-NEXT: strexd r2, r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: cmp r2, #0
; CHECK-ARM-LE-NEXT: bne .LBB31_1
; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-ARM-BE-LABEL: test_atomic_load_max_i64:
; CHECK-ARM-BE: @ %bb.0:
; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-BE-NEXT: .LBB31_1: @ %atomicrmw.start
; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-BE-NEXT: ldrexd r4, r5, [r2]
-; CHECK-ARM-BE-NEXT: mov r7, r1
-; CHECK-ARM-BE-NEXT: subs r3, r1, r5
-; CHECK-ARM-BE-NEXT: sbcs r3, r0, r4
-; CHECK-ARM-BE-NEXT: mov r3, #0
-; CHECK-ARM-BE-NEXT: movwlt r3, #1
-; CHECK-ARM-BE-NEXT: cmp r3, #0
-; CHECK-ARM-BE-NEXT: movne r7, r5
-; CHECK-ARM-BE-NEXT: mov r6, r0
-; CHECK-ARM-BE-NEXT: movne r6, r4
-; CHECK-ARM-BE-NEXT: strexd r3, r6, r7, [r2]
-; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: ldrexd r6, r7, [r12]
+; CHECK-ARM-BE-NEXT: subs r5, r1, r7
+; CHECK-ARM-BE-NEXT: sbcs r5, r0, r6
+; CHECK-ARM-BE-NEXT: mov r5, #0
+; CHECK-ARM-BE-NEXT: movwlt r5, #1
+; CHECK-ARM-BE-NEXT: cmp r5, #0
+; CHECK-ARM-BE-NEXT: mov r5, r1
+; CHECK-ARM-BE-NEXT: movne r5, r7
+; CHECK-ARM-BE-NEXT: mov r4, r0
+; CHECK-ARM-BE-NEXT: movne r4, r6
+; CHECK-ARM-BE-NEXT: strexd r2, r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: cmp r2, #0
; CHECK-ARM-BE-NEXT: bne .LBB31_1
; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LE-LABEL: test_atomic_load_max_i64:
@@ -1595,49 +1595,49 @@ define void @test_atomic_load_umin_i64(i64 %offset) nounwind {
; CHECK-ARM-LE-LABEL: test_atomic_load_umin_i64:
; CHECK-ARM-LE: @ %bb.0:
; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-LE-NEXT: .LBB35_1: @ %atomicrmw.start
; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-LE-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-LE-NEXT: mov r7, r1
-; CHECK-ARM-LE-NEXT: subs r3, r0, r4
-; CHECK-ARM-LE-NEXT: sbcs r3, r1, r5
-; CHECK-ARM-LE-NEXT: mov r3, #0
-; CHECK-ARM-LE-NEXT: movwhs r3, #1
-; CHECK-ARM-LE-NEXT: cmp r3, #0
-; CHECK-ARM-LE-NEXT: movne r7, r5
-; CHECK-ARM-LE-NEXT: mov r6, r0
-; CHECK-ARM-LE-NEXT: movne r6, r4
-; CHECK-ARM-LE-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-LE-NEXT: subs r5, r0, r6
+; CHECK-ARM-LE-NEXT: sbcs r5, r1, r7
+; CHECK-ARM-LE-NEXT: mov r5, #0
+; CHECK-ARM-LE-NEXT: movwhs r5, #1
+; CHECK-ARM-LE-NEXT: cmp r5, #0
+; CHECK-ARM-LE-NEXT: mov r5, r1
+; CHECK-ARM-LE-NEXT: movne r5, r7
+; CHECK-ARM-LE-NEXT: mov r4, r0
+; CHECK-ARM-LE-NEXT: movne r4, r6
+; CHECK-ARM-LE-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: cmp r2, #0
; CHECK-ARM-LE-NEXT: bne .LBB35_1
; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-ARM-BE-LABEL: test_atomic_load_umin_i64:
; CHECK-ARM-BE: @ %bb.0:
; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-BE-NEXT: .LBB35_1: @ %atomicrmw.start
; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-BE-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-BE-NEXT: mov r7, r1
-; CHECK-ARM-BE-NEXT: subs r3, r1, r5
-; CHECK-ARM-BE-NEXT: sbcs r3, r0, r4
-; CHECK-ARM-BE-NEXT: mov r3, #0
-; CHECK-ARM-BE-NEXT: movwhs r3, #1
-; CHECK-ARM-BE-NEXT: cmp r3, #0
-; CHECK-ARM-BE-NEXT: movne r7, r5
-; CHECK-ARM-BE-NEXT: mov r6, r0
-; CHECK-ARM-BE-NEXT: movne r6, r4
-; CHECK-ARM-BE-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-BE-NEXT: subs r5, r1, r7
+; CHECK-ARM-BE-NEXT: sbcs r5, r0, r6
+; CHECK-ARM-BE-NEXT: mov r5, #0
+; CHECK-ARM-BE-NEXT: movwhs r5, #1
+; CHECK-ARM-BE-NEXT: cmp r5, #0
+; CHECK-ARM-BE-NEXT: mov r5, r1
+; CHECK-ARM-BE-NEXT: movne r5, r7
+; CHECK-ARM-BE-NEXT: mov r4, r0
+; CHECK-ARM-BE-NEXT: movne r4, r6
+; CHECK-ARM-BE-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: cmp r2, #0
; CHECK-ARM-BE-NEXT: bne .LBB35_1
; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LE-LABEL: test_atomic_load_umin_i64:
@@ -1836,49 +1836,49 @@ define void @test_atomic_load_umax_i64(i64 %offset) nounwind {
; CHECK-ARM-LE-LABEL: test_atomic_load_umax_i64:
; CHECK-ARM-LE: @ %bb.0:
; CHECK-ARM-LE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-LE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-LE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-LE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-LE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-LE-NEXT: .LBB39_1: @ %atomicrmw.start
; CHECK-ARM-LE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-LE-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-LE-NEXT: mov r7, r1
-; CHECK-ARM-LE-NEXT: subs r3, r0, r4
-; CHECK-ARM-LE-NEXT: sbcs r3, r1, r5
-; CHECK-ARM-LE-NEXT: mov r3, #0
-; CHECK-ARM-LE-NEXT: movwlo r3, #1
-; CHECK-ARM-LE-NEXT: cmp r3, #0
-; CHECK-ARM-LE-NEXT: movne r7, r5
-; CHECK-ARM-LE-NEXT: mov r6, r0
-; CHECK-ARM-LE-NEXT: movne r6, r4
-; CHECK-ARM-LE-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-LE-NEXT: cmp r3, #0
+; CHECK-ARM-LE-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-LE-NEXT: subs r5, r0, r6
+; CHECK-ARM-LE-NEXT: sbcs r5, r1, r7
+; CHECK-ARM-LE-NEXT: mov r5, #0
+; CHECK-ARM-LE-NEXT: movwlo r5, #1
+; CHECK-ARM-LE-NEXT: cmp r5, #0
+; CHECK-ARM-LE-NEXT: mov r5, r1
+; CHECK-ARM-LE-NEXT: movne r5, r7
+; CHECK-ARM-LE-NEXT: mov r4, r0
+; CHECK-ARM-LE-NEXT: movne r4, r6
+; CHECK-ARM-LE-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-LE-NEXT: cmp r2, #0
; CHECK-ARM-LE-NEXT: bne .LBB39_1
; CHECK-ARM-LE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-LE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-LE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-LE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-ARM-BE-LABEL: test_atomic_load_umax_i64:
; CHECK-ARM-BE: @ %bb.0:
; CHECK-ARM-BE-NEXT: push {r4, r5, r6, r7, r11, lr}
-; CHECK-ARM-BE-NEXT: movw r2, :lower16:var64
-; CHECK-ARM-BE-NEXT: movt r2, :upper16:var64
+; CHECK-ARM-BE-NEXT: movw r12, :lower16:var64
+; CHECK-ARM-BE-NEXT: movt r12, :upper16:var64
; CHECK-ARM-BE-NEXT: .LBB39_1: @ %atomicrmw.start
; CHECK-ARM-BE-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-ARM-BE-NEXT: ldaexd r4, r5, [r2]
-; CHECK-ARM-BE-NEXT: mov r7, r1
-; CHECK-ARM-BE-NEXT: subs r3, r1, r5
-; CHECK-ARM-BE-NEXT: sbcs r3, r0, r4
-; CHECK-ARM-BE-NEXT: mov r3, #0
-; CHECK-ARM-BE-NEXT: movwlo r3, #1
-; CHECK-ARM-BE-NEXT: cmp r3, #0
-; CHECK-ARM-BE-NEXT: movne r7, r5
-; CHECK-ARM-BE-NEXT: mov r6, r0
-; CHECK-ARM-BE-NEXT: movne r6, r4
-; CHECK-ARM-BE-NEXT: stlexd r3, r6, r7, [r2]
-; CHECK-ARM-BE-NEXT: cmp r3, #0
+; CHECK-ARM-BE-NEXT: ldaexd r6, r7, [r12]
+; CHECK-ARM-BE-NEXT: subs r5, r1, r7
+; CHECK-ARM-BE-NEXT: sbcs r5, r0, r6
+; CHECK-ARM-BE-NEXT: mov r5, #0
+; CHECK-ARM-BE-NEXT: movwlo r5, #1
+; CHECK-ARM-BE-NEXT: cmp r5, #0
+; CHECK-ARM-BE-NEXT: mov r5, r1
+; CHECK-ARM-BE-NEXT: movne r5, r7
+; CHECK-ARM-BE-NEXT: mov r4, r0
+; CHECK-ARM-BE-NEXT: movne r4, r6
+; CHECK-ARM-BE-NEXT: stlexd r2, r4, r5, [r12]
+; CHECK-ARM-BE-NEXT: cmp r2, #0
; CHECK-ARM-BE-NEXT: bne .LBB39_1
; CHECK-ARM-BE-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-ARM-BE-NEXT: strd r4, r5, [r2]
+; CHECK-ARM-BE-NEXT: strd r6, r7, [r12]
; CHECK-ARM-BE-NEXT: pop {r4, r5, r6, r7, r11, pc}
;
; CHECK-THUMB-LE-LABEL: test_atomic_load_umax_i64:
diff --git a/llvm/test/CodeGen/ARM/atomicrmw-uinc-udec-wrap.ll b/llvm/test/CodeGen/ARM/atomicrmw-uinc-udec-wrap.ll
index 243ec4deecdb84..f4e25916694ed5 100644
--- a/llvm/test/CodeGen/ARM/atomicrmw-uinc-udec-wrap.ll
+++ b/llvm/test/CodeGen/ARM/atomicrmw-uinc-udec-wrap.ll
@@ -69,29 +69,28 @@ define i32 @atomicrmw_uinc_wrap_i32(ptr %ptr, i32 %val) {
define i64 @atomicrmw_uinc_wrap_i64(ptr %ptr, i64 %val) {
; CHECK-LABEL: atomicrmw_uinc_wrap_i64:
; CHECK: @ %bb.0:
-; CHECK-NEXT: .save {r4, r5, r6, r7, r11, lr}
-; CHECK-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-NEXT: .save {r4, r6, r7, lr}
+; CHECK-NEXT: push {r4, r6, r7, lr}
+; CHECK-NEXT: mov r12, r0
; CHECK-NEXT: dmb ish
; CHECK-NEXT: .LBB3_1: @ %atomicrmw.start
; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexd r4, r5, [r0]
-; CHECK-NEXT: adds r6, r4, #1
-; CHECK-NEXT: adc r7, r5, #0
-; CHECK-NEXT: subs r1, r4, r2
-; CHECK-NEXT: sbcs r1, r5, r3
-; CHECK-NEXT: mov r1, #0
-; CHECK-NEXT: movwhs r1, #1
-; CHECK-NEXT: cmp r1, #0
+; CHECK-NEXT: ldrexd r0, r1, [r12]
+; CHECK-NEXT: adds r6, r0, #1
+; CHECK-NEXT: adc r7, r1, #0
+; CHECK-NEXT: subs r4, r0, r2
+; CHECK-NEXT: sbcs r4, r1, r3
+; CHECK-NEXT: mov r4, #0
+; CHECK-NEXT: movwhs r4, #1
+; CHECK-NEXT: cmp r4, #0
; CHECK-NEXT: movwne r7, #0
; CHECK-NEXT: movwne r6, #0
-; CHECK-NEXT: strexd r1, r6, r7, [r0]
-; CHECK-NEXT: cmp r1, #0
+; CHECK-NEXT: strexd r4, r6, r7, [r12]
+; CHECK-NEXT: cmp r4, #0
; CHECK-NEXT: bne .LBB3_1
; CHECK-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-NEXT: mov r0, r4
-; CHECK-NEXT: mov r1, r5
; CHECK-NEXT: dmb ish
-; CHECK-NEXT: pop {r4, r5, r6, r7, r11, pc}
+; CHECK-NEXT: pop {r4, r6, r7, pc}
%result = atomicrmw uinc_wrap ptr %ptr, i64 %val seq_cst
ret i64 %result
}
@@ -172,29 +171,28 @@ define i64 @atomicrmw_udec_wrap_i64(ptr %ptr, i64 %val) {
; CHECK: @ %bb.0:
; CHECK-NEXT: .save {r4, r5, r6, r7, r11, lr}
; CHECK-NEXT: push {r4, r5, r6, r7, r11, lr}
+; CHECK-NEXT: mov r12, r0
; CHECK-NEXT: dmb ish
; CHECK-NEXT: .LBB7_1: @ %atomicrmw.start
; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: ldrexd r4, r5, [r0]
-; CHECK-NEXT: mov r12, #0
-; CHECK-NEXT: subs r1, r2, r4
-; CHECK-NEXT: sbcs r1, r3, r5
-; CHECK-NEXT: orr r1, r4, r5
-; CHECK-NEXT: clz r1, r1
-; CHECK-NEXT: movwlo r12, #1
-; CHECK-NEXT: lsr r1, r1, #5
-; CHECK-NEXT: subs r6, r4, #1
-; CHECK-NEXT: sbc r7, r5, #0
-; CHECK-NEXT: orr r1, r1, r12
-; CHECK-NEXT: cmp r1, #0
+; CHECK-NEXT: ldrexd r0, r1, [r12]
+; CHECK-NEXT: orr r4, r0, r1
+; CHECK-NEXT: subs r5, r2, r0
+; CHECK-NEXT: clz r4, r4
+; CHECK-NEXT: sbcs r5, r3, r1
+; CHECK-NEXT: lsr r4, r4, #5
+; CHECK-NEXT: mov r5, #0
+; CHECK-NEXT: movwlo r5, #1
+; CHECK-NEXT: subs r6, r0, #1
+; CHECK-NEXT: orr lr, r4, r5
+; CHECK-NEXT: sbc r7, r1, #0
+; CHECK-NEXT: cmp lr, #0
; CHECK-NEXT: movne r7, r3
; CHECK-NEXT: movne r6, r2
-; CHECK-NEXT: strexd r1, r6, r7, [r0]
-; CHECK-NEXT: cmp r1, #0
+; CHECK-NEXT: strexd r4, r6, r7, [r12]
+; CHECK-NEXT: cmp r4, #0
; CHECK-NEXT: bne .LBB7_1
; CHECK-NEXT: @ %bb.2: @ %atomicrmw.end
-; CHECK-NEXT: mov r0, r4
-; CHECK-NEXT: mov r1, r5
; CHECK-NEXT: dmb ish
; CHECK-NEXT: pop {r4, r5, r6, r7, r11, pc}
%result = atomicrmw udec_wrap ptr %ptr, i64 %val seq_cst
More information about the llvm-commits
mailing list