efriedma created this revision.
efriedma added reviewers: nikic, t.p.northover, john.brawn, joerg, tomhughes, 
alanphipps, aykevl.
Herald added subscribers: s.egerton, simoncook, hiraditya, kristof.beyls.
Herald added a project: All.
efriedma requested review of this revision.
Herald added subscribers: cfe-commits, pcwang-thead.
Herald added projects: clang, LLVM.

Trying to accurately model what the hardware actually supports seems to lead to 
a lot of people complaining, and nobody saying it's actually helpful. So just 
pretend everything is lock-free, and let users deal with ensuring that the 
__sync_* routines are actually lock-free. If anyone complains, we can just say 
"gcc does the same thing".

Partially reverts D120026 <https://reviews.llvm.org/D120026>.  Makes D130480 
<https://reviews.llvm.org/D130480> unnecessary.

Fixes https://github.com/llvm/llvm-project/issues/58603


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137980

Files:
  clang/lib/Basic/Targets/ARM.cpp
  clang/test/CodeGen/arm-atomics-m0.c
  clang/test/CodeGen/atomic-ops-libcall.c
  clang/test/CodeGen/atomics-inlining.c
  clang/test/CodeGen/c11atomics.c
  clang/test/CodeGen/pr45476.cpp
  clang/test/CodeGenCXX/threadsafe-statics-no-atomic.cpp
  clang/test/CodeGenOpenCL/atomic-ops-libcall.cl
  llvm/lib/Target/ARM/ARMISelLowering.cpp
  llvm/test/CodeGen/ARM/atomic-64bit.ll
  llvm/test/CodeGen/ARM/atomic-load-store.ll
  llvm/test/CodeGen/ARM/atomic-op.ll
  llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll

Index: llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll
===================================================================
--- llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll
+++ llvm/test/CodeGen/ARM/thumbv6m-atomic32.ll
@@ -3,285 +3,156 @@
 ; RUN: llc -mtriple=thumbv6m-none-eabi -mattr=+atomics-32 < %s | FileCheck %s --check-prefixes=CHECK,ATOMIC32
 
 define i8 @load8(ptr %p) {
-; NO-ATOMIC32-LABEL: load8:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_load_1
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: load8:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    ldrb r0, [r0]
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    bx lr
+; CHECK-LABEL: load8:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    ldrb r0, [r0]
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    bx lr
   %v = load atomic i8, ptr %p seq_cst, align 1
   ret i8 %v
 }
 
 define void @store8(ptr %p) {
-; NO-ATOMIC32-LABEL: store8:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #0
-; NO-ATOMIC32-NEXT:    movs r2, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_store_1
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: store8:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #0
-; ATOMIC32-NEXT:    strb r1, [r0]
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    bx lr
+; CHECK-LABEL: store8:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #0
+; CHECK-NEXT:    strb r1, [r0]
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    bx lr
   store atomic i8 0, ptr %p seq_cst, align 1
   ret void
 }
 
 define i8 @rmw8(ptr %p) {
-; NO-ATOMIC32-LABEL: rmw8:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #1
-; NO-ATOMIC32-NEXT:    movs r2, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_fetch_add_1
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: rmw8:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    .save {r7, lr}
-; ATOMIC32-NEXT:    push {r7, lr}
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #1
-; ATOMIC32-NEXT:    bl __sync_fetch_and_add_1
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    pop {r7, pc}
+; CHECK-LABEL: rmw8:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r7, lr}
+; CHECK-NEXT:    push {r7, lr}
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #1
+; CHECK-NEXT:    bl __sync_fetch_and_add_1
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    pop {r7, pc}
   %v = atomicrmw add ptr %p, i8 1 seq_cst, align 1
   ret i8 %v
 }
 
 define i8 @cmpxchg8(ptr %p) {
-; NO-ATOMIC32-LABEL: cmpxchg8:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    .pad #8
-; NO-ATOMIC32-NEXT:    sub sp, #8
-; NO-ATOMIC32-NEXT:    add r1, sp, #4
-; NO-ATOMIC32-NEXT:    movs r2, #0
-; NO-ATOMIC32-NEXT:    strb r2, [r1]
-; NO-ATOMIC32-NEXT:    movs r3, #5
-; NO-ATOMIC32-NEXT:    str r3, [sp]
-; NO-ATOMIC32-NEXT:    movs r2, #1
-; NO-ATOMIC32-NEXT:    bl __atomic_compare_exchange_1
-; NO-ATOMIC32-NEXT:    ldr r0, [sp, #4]
-; NO-ATOMIC32-NEXT:    add sp, #8
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: cmpxchg8:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    .save {r7, lr}
-; ATOMIC32-NEXT:    push {r7, lr}
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #0
-; ATOMIC32-NEXT:    movs r2, #1
-; ATOMIC32-NEXT:    bl __sync_val_compare_and_swap_1
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    pop {r7, pc}
+; CHECK-LABEL: cmpxchg8:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r7, lr}
+; CHECK-NEXT:    push {r7, lr}
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #0
+; CHECK-NEXT:    movs r2, #1
+; CHECK-NEXT:    bl __sync_val_compare_and_swap_1
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    pop {r7, pc}
   %res = cmpxchg ptr %p, i8 0, i8 1 seq_cst seq_cst
   %res.0 = extractvalue { i8, i1 } %res, 0
   ret i8 %res.0
 }
 
 define i16 @load16(ptr %p) {
-; NO-ATOMIC32-LABEL: load16:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_load_2
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: load16:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    ldrh r0, [r0]
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    bx lr
+; CHECK-LABEL: load16:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    ldrh r0, [r0]
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    bx lr
   %v = load atomic i16, ptr %p seq_cst, align 2
   ret i16 %v
 }
 
 define void @store16(ptr %p) {
-; NO-ATOMIC32-LABEL: store16:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #0
-; NO-ATOMIC32-NEXT:    movs r2, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_store_2
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: store16:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #0
-; ATOMIC32-NEXT:    strh r1, [r0]
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    bx lr
+; CHECK-LABEL: store16:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #0
+; CHECK-NEXT:    strh r1, [r0]
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    bx lr
   store atomic i16 0, ptr %p seq_cst, align 2
   ret void
 }
 
 define i16 @rmw16(ptr %p) {
-; NO-ATOMIC32-LABEL: rmw16:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #1
-; NO-ATOMIC32-NEXT:    movs r2, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_fetch_add_2
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: rmw16:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    .save {r7, lr}
-; ATOMIC32-NEXT:    push {r7, lr}
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #1
-; ATOMIC32-NEXT:    bl __sync_fetch_and_add_2
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    pop {r7, pc}
+; CHECK-LABEL: rmw16:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r7, lr}
+; CHECK-NEXT:    push {r7, lr}
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #1
+; CHECK-NEXT:    bl __sync_fetch_and_add_2
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    pop {r7, pc}
   %v = atomicrmw add ptr %p, i16 1 seq_cst, align 2
   ret i16 %v
 }
 
 define i16 @cmpxchg16(ptr %p) {
-; NO-ATOMIC32-LABEL: cmpxchg16:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    .pad #8
-; NO-ATOMIC32-NEXT:    sub sp, #8
-; NO-ATOMIC32-NEXT:    add r1, sp, #4
-; NO-ATOMIC32-NEXT:    movs r2, #0
-; NO-ATOMIC32-NEXT:    strh r2, [r1]
-; NO-ATOMIC32-NEXT:    movs r3, #5
-; NO-ATOMIC32-NEXT:    str r3, [sp]
-; NO-ATOMIC32-NEXT:    movs r2, #1
-; NO-ATOMIC32-NEXT:    bl __atomic_compare_exchange_2
-; NO-ATOMIC32-NEXT:    ldr r0, [sp, #4]
-; NO-ATOMIC32-NEXT:    add sp, #8
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: cmpxchg16:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    .save {r7, lr}
-; ATOMIC32-NEXT:    push {r7, lr}
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #0
-; ATOMIC32-NEXT:    movs r2, #1
-; ATOMIC32-NEXT:    bl __sync_val_compare_and_swap_2
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    pop {r7, pc}
+; CHECK-LABEL: cmpxchg16:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r7, lr}
+; CHECK-NEXT:    push {r7, lr}
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #0
+; CHECK-NEXT:    movs r2, #1
+; CHECK-NEXT:    bl __sync_val_compare_and_swap_2
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    pop {r7, pc}
   %res = cmpxchg ptr %p, i16 0, i16 1 seq_cst seq_cst
   %res.0 = extractvalue { i16, i1 } %res, 0
   ret i16 %res.0
 }
 
 define i32 @load32(ptr %p) {
-; NO-ATOMIC32-LABEL: load32:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_load_4
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: load32:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    ldr r0, [r0]
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    bx lr
+; CHECK-LABEL: load32:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    ldr r0, [r0]
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    bx lr
   %v = load atomic i32, ptr %p seq_cst, align 4
   ret i32 %v
 }
 
 define void @store32(ptr %p) {
-; NO-ATOMIC32-LABEL: store32:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #0
-; NO-ATOMIC32-NEXT:    movs r2, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_store_4
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: store32:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #0
-; ATOMIC32-NEXT:    str r1, [r0]
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    bx lr
+; CHECK-LABEL: store32:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #0
+; CHECK-NEXT:    str r1, [r0]
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    bx lr
   store atomic i32 0, ptr %p seq_cst, align 4
   ret void
 }
 
 define i32 @rmw32(ptr %p) {
-; NO-ATOMIC32-LABEL: rmw32:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    movs r1, #1
-; NO-ATOMIC32-NEXT:    movs r2, #5
-; NO-ATOMIC32-NEXT:    bl __atomic_fetch_add_4
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: rmw32:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    .save {r7, lr}
-; ATOMIC32-NEXT:    push {r7, lr}
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #1
-; ATOMIC32-NEXT:    bl __sync_fetch_and_add_4
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    pop {r7, pc}
+; CHECK-LABEL: rmw32:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r7, lr}
+; CHECK-NEXT:    push {r7, lr}
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #1
+; CHECK-NEXT:    bl __sync_fetch_and_add_4
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    pop {r7, pc}
   %v = atomicrmw add ptr %p, i32 1 seq_cst, align 4
   ret i32 %v
 }
 
 define i32 @cmpxchg32(ptr %p) {
-; NO-ATOMIC32-LABEL: cmpxchg32:
-; NO-ATOMIC32:       @ %bb.0:
-; NO-ATOMIC32-NEXT:    .save {r7, lr}
-; NO-ATOMIC32-NEXT:    push {r7, lr}
-; NO-ATOMIC32-NEXT:    .pad #8
-; NO-ATOMIC32-NEXT:    sub sp, #8
-; NO-ATOMIC32-NEXT:    movs r1, #0
-; NO-ATOMIC32-NEXT:    str r1, [sp, #4]
-; NO-ATOMIC32-NEXT:    movs r3, #5
-; NO-ATOMIC32-NEXT:    str r3, [sp]
-; NO-ATOMIC32-NEXT:    add r1, sp, #4
-; NO-ATOMIC32-NEXT:    movs r2, #1
-; NO-ATOMIC32-NEXT:    bl __atomic_compare_exchange_4
-; NO-ATOMIC32-NEXT:    ldr r0, [sp, #4]
-; NO-ATOMIC32-NEXT:    add sp, #8
-; NO-ATOMIC32-NEXT:    pop {r7, pc}
-;
-; ATOMIC32-LABEL: cmpxchg32:
-; ATOMIC32:       @ %bb.0:
-; ATOMIC32-NEXT:    .save {r7, lr}
-; ATOMIC32-NEXT:    push {r7, lr}
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    movs r1, #0
-; ATOMIC32-NEXT:    movs r2, #1
-; ATOMIC32-NEXT:    bl __sync_val_compare_and_swap_4
-; ATOMIC32-NEXT:    dmb sy
-; ATOMIC32-NEXT:    pop {r7, pc}
+; CHECK-LABEL: cmpxchg32:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r7, lr}
+; CHECK-NEXT:    push {r7, lr}
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    movs r1, #0
+; CHECK-NEXT:    movs r2, #1
+; CHECK-NEXT:    bl __sync_val_compare_and_swap_4
+; CHECK-NEXT:    dmb sy
+; CHECK-NEXT:    pop {r7, pc}
   %res = cmpxchg ptr %p, i32 0, i32 1 seq_cst seq_cst
   %res.0 = extractvalue { i32, i1 } %res, 0
   ret i32 %res.0
@@ -359,3 +230,6 @@
   %res.0 = extractvalue { i64, i1 } %res, 0
   ret i64 %res.0
 }
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; ATOMIC32: {{.*}}
+; NO-ATOMIC32: {{.*}}
Index: llvm/test/CodeGen/ARM/atomic-op.ll
===================================================================
--- llvm/test/CodeGen/ARM/atomic-op.ll
+++ llvm/test/CodeGen/ARM/atomic-op.ll
@@ -1,12 +1,12 @@
-; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix CHECK-ARMV7
-; RUN: llc < %s -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-T2
-; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-T1
-; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs -mcpu=cortex-m0 | FileCheck %s --check-prefix=CHECK-T1-M0
-; RUN: llc < %s -mtriple=thumbv7--none-eabi -thread-model single -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-BAREMETAL
+; RUN: llc < %s -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefixes=CHECKALL,CHECK,CHECK-ARMV7
+; RUN: llc < %s -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefixes=CHECKALL,CHECK,CHECK-T2
+; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs | FileCheck %s --check-prefixes=CHECKALL,CHECK-T1
+; RUN: llc < %s -mtriple=thumbv6-apple-ios -verify-machineinstrs -mcpu=cortex-m0 | FileCheck %s --check-prefixes=CHECKALL,CHECK-T1-M0
+; RUN: llc < %s -mtriple=thumbv7--none-eabi -thread-model single -verify-machineinstrs | FileCheck %s  --check-prefixes=CHECKALL,CHECK-BAREMETAL
 
 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
 
-; CHECK-LABEL: _func:
+; CHECKALL-LABEL: func:
 define void @func(i32 %argc, i8** %argv) nounwind {
 entry:
 	%argc.addr = alloca i32		; <i32*> [#uses=1]
@@ -32,7 +32,7 @@
   ; CHECK: add
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_add_4
-  ; CHECK-T1-M0: bl ___atomic_fetch_add_4
+  ; CHECK-T1-M0: bl ___sync_fetch_and_add_4
   ; CHECK-BAREMETAL: add
   ; CHECK-BAREMETAL-NOT: __sync
   %0 = atomicrmw add i32* %val1, i32 %tmp monotonic
@@ -42,7 +42,7 @@
   ; CHECK: sub
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_sub_4
-  ; CHECK-T1-M0: bl ___atomic_fetch_sub_4
+  ; CHECK-T1-M0: bl ___sync_fetch_and_sub_4
   ; CHECK-BAREMETAL: sub
   ; CHECK-BAREMETAL-NOT: __sync
   %1 = atomicrmw sub i32* %val2, i32 30 monotonic
@@ -52,7 +52,7 @@
   ; CHECK: add
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_add_4
-  ; CHECK-T1-M0: bl ___atomic_fetch_add_4
+  ; CHECK-T1-M0: bl ___sync_fetch_and_add_4
   ; CHECK-BAREMETAL: add
   ; CHECK-BAREMETAL-NOT: __sync
   %2 = atomicrmw add i32* %val2, i32 1 monotonic
@@ -62,7 +62,7 @@
   ; CHECK: sub
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_sub_4
-  ; CHECK-T1-M0: bl ___atomic_fetch_sub_4
+  ; CHECK-T1-M0: bl ___sync_fetch_and_sub_4
   ; CHECK-BAREMETAL: sub
   ; CHECK-BAREMETAL-NOT: __sync
   %3 = atomicrmw sub i32* %val2, i32 1 monotonic
@@ -72,7 +72,7 @@
   ; CHECK: and
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_and_4
-  ; CHECK-T1-M0: bl ___atomic_fetch_and_4
+  ; CHECK-T1-M0: bl ___sync_fetch_and_and_4
   ; CHECK-BAREMETAL: and
   ; CHECK-BAREMETAL-NOT: __sync
   %4 = atomicrmw and i32* %andt, i32 4080 monotonic
@@ -82,7 +82,7 @@
   ; CHECK: or
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_or_4
-  ; CHECK-T1-M0: bl ___atomic_fetch_or_4
+  ; CHECK-T1-M0: bl ___sync_fetch_and_or_4
   ; CHECK-BAREMETAL: or
   ; CHECK-BAREMETAL-NOT: __sync
   %5 = atomicrmw or i32* %ort, i32 4080 monotonic
@@ -92,7 +92,7 @@
   ; CHECK: eor
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_xor_4
-  ; CHECK-T1-M0: bl ___atomic_fetch_xor_4
+  ; CHECK-T1-M0: bl ___sync_fetch_and_xor_4
   ; CHECK-BAREMETAL: eor
   ; CHECK-BAREMETAL-NOT: __sync
   %6 = atomicrmw xor i32* %xort, i32 4080 monotonic
@@ -102,8 +102,7 @@
   ; CHECK: cmp
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_min_4
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_4
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_min_4
   ; CHECK-BAREMETAL-NOT: __sync
   %7 = atomicrmw min i32* %val2, i32 16 monotonic
 	store i32 %7, i32* %old
@@ -113,8 +112,7 @@
   ; CHECK: cmp
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_min_4
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_4
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_min_4
   ; CHECK-BAREMETAL-NOT: __sync
   %8 = atomicrmw min i32* %val2, i32 %neg monotonic
 	store i32 %8, i32* %old
@@ -123,8 +121,7 @@
   ; CHECK: cmp
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_max_4
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_4
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_max_4
   ; CHECK-BAREMETAL-NOT: __sync
   %9 = atomicrmw max i32* %val2, i32 1 monotonic
 	store i32 %9, i32* %old
@@ -134,7 +131,7 @@
   ; CHECK-NOT: cmp
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_max_4
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_4
+  ; CHECK-T1-M0: bl ___sync_fetch_and_max_4
   ; CHECK-BAREMETAL: bic
   ; CHECK-BAREMETAL-NOT: __sync
   %10 = atomicrmw max i32* %val2, i32 0 monotonic
@@ -144,8 +141,7 @@
   ; CHECK: cmp
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_umin_4
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_4
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umin_4
   ; CHECK-BAREMETAL-NOT: __sync
   %11 = atomicrmw umin i32* %val2, i32 16 monotonic
 	store i32 %11, i32* %old
@@ -155,8 +151,7 @@
   ; CHECK: cmp
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_umin_4
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_4
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umin_4
   ; CHECK-BAREMETAL-NOT: __sync
   %12 = atomicrmw umin i32* %val2, i32 %uneg monotonic
 	store i32 %12, i32* %old
@@ -165,8 +160,7 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umax_4
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_4
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umax_4
   ; CHECK-BAREMETAL-NOT: __sync
   %13 = atomicrmw umax i32* %val2, i32 1 monotonic
 	store i32 %13, i32* %old
@@ -175,8 +169,7 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umax_4
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_4
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umax_4
   ; CHECK-BAREMETAL-NOT: __sync
   %14 = atomicrmw umax i32* %val2, i32 0 monotonic
 	store i32 %14, i32* %old
@@ -184,7 +177,7 @@
   ret void
 }
 
-; CHECK-LABEL: _func2:
+; CHECKALL-LABEL: func2:
 define void @func2() nounwind {
 entry:
   %val = alloca i16
@@ -194,8 +187,7 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umin_2
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_2
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umin_2
   ; CHECK-BAREMETAL-NOT: __sync
   %0 = atomicrmw umin i16* %val, i16 16 monotonic
   store i16 %0, i16* %old
@@ -204,8 +196,7 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umin_2
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_2
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umin_2
   ; CHECK-BAREMETAL-NOT: __sync
   %1 = atomicrmw umin i16* %val, i16 %uneg monotonic
   store i16 %1, i16* %old
@@ -213,8 +204,7 @@
   ; CHECK: cmp
   ; CHECK: strex
   ; CHECK-T1: bl ___sync_fetch_and_umax_2
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_2
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umax_2
   ; CHECK-BAREMETAL-NOT: __sync
   %2 = atomicrmw umax i16* %val, i16 1 monotonic
   store i16 %2, i16* %old
@@ -222,15 +212,14 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umax_2
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_2
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umax_2
   ; CHECK-BAREMETAL-NOT: __sync
   %3 = atomicrmw umax i16* %val, i16 0 monotonic
   store i16 %3, i16* %old
   ret void
 }
 
-; CHECK-LABEL: _func3:
+; CHECKALL-LABEL: func3:
 define void @func3() nounwind {
 entry:
   %val = alloca i8
@@ -240,8 +229,7 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umin_1
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_1
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umin_1
   ; CHECK-BAREMETAL-NOT: __sync
   %0 = atomicrmw umin i8* %val, i8 16 monotonic
   store i8 %0, i8* %old
@@ -249,8 +237,7 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umin_1
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_1
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umin_1
   ; CHECK-BAREMETAL-NOT: __sync
   %uneg = sub i8 0, 1
   %1 = atomicrmw umin i8* %val, i8 %uneg monotonic
@@ -259,8 +246,7 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umax_1
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_1
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umax_1
   ; CHECK-BAREMETAL-NOT: __sync
   %2 = atomicrmw umax i8* %val, i8 1 monotonic
   store i8 %2, i8* %old
@@ -268,15 +254,14 @@
   ; CHECK: strex
   ; CHECK: cmp
   ; CHECK-T1: bl ___sync_fetch_and_umax_1
-  ; CHECK-T1-M0: bl ___atomic_compare_exchange_1
-  ; CHECK-BAREMETAL: cmp
+  ; CHECK-T1-M0: bl ___sync_fetch_and_umax_1
   ; CHECK-BAREMETAL-NOT: __sync
   %3 = atomicrmw umax i8* %val, i8 0 monotonic
   store i8 %3, i8* %old
   ret void
 }
 
-; CHECK-LABEL: _func4:
+; CHECKALL-LABEL: func4:
 ; This function should not need to use callee-saved registers.
 ; rdar://problem/12203728
 ; CHECK-NOT: r4
@@ -287,7 +272,7 @@
 }
 
 define i32 @test_cmpxchg_fail_order(i32 *%addr, i32 %desired, i32 %new) {
-; CHECK-LABEL: test_cmpxchg_fail_order:
+; CHECKALL-LABEL: test_cmpxchg_fail_order:
 
   %pair = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst monotonic
   %oldval = extractvalue { i32, i1 } %pair, 0
@@ -329,7 +314,7 @@
 }
 
 define i32 @test_cmpxchg_fail_order1(i32 *%addr, i32 %desired, i32 %new) {
-; CHECK-LABEL: test_cmpxchg_fail_order1:
+; CHECKALL-LABEL: test_cmpxchg_fail_order1:
 
   %pair = cmpxchg i32* %addr, i32 %desired, i32 %new acquire acquire
   %oldval = extractvalue { i32, i1 } %pair, 0
@@ -352,7 +337,7 @@
 }
 
 define i32 @load_load_add_acquire(i32* %mem1, i32* %mem2) nounwind {
-; CHECK-LABEL: load_load_add_acquire
+; CHECKALL-LABEL: load_load_add_acquire
   %val1 = load atomic i32, i32* %mem1 acquire, align 4
   %val2 = load atomic i32, i32* %mem2 acquire, align 4
   %tmp = add i32 %val1, %val2
@@ -363,23 +348,26 @@
 ; CHECK: dmb
 ; CHECK: add r0,
 
-; CHECK-T1-M0: __atomic_load_4
-; CHECK-T1-M0: __atomic_load_4
+; CHECK-T1-M0: ldr {{r[0-9]}}, [r0]
+; CHECK-T1-M0: dmb
+; CHECK-T1-M0: ldr {{r[0-9]}}, [r1]
+; CHECK-T1-M0: adds r0,
+; CHECK-T1-M0: dmb
 
 ; CHECK-T1: ___sync_val_compare_and_swap_4
 ; CHECK-T1: ___sync_val_compare_and_swap_4
 
-; CHECK-BAREMETAL: ldr {{r[0-9]}}, [r0]
-; CHECK-BAREMETAL-NOT: dmb
 ; CHECK-BAREMETAL: ldr {{r[0-9]}}, [r1]
 ; CHECK-BAREMETAL-NOT: dmb
+; CHECK-BAREMETAL: ldr {{r[0-9]}}, [r0]
+; CHECK-BAREMETAL-NOT: dmb
 ; CHECK-BAREMETAL: add r0,
 
   ret i32 %tmp
 }
 
 define void @store_store_release(i32* %mem1, i32 %val1, i32* %mem2, i32 %val2) {
-; CHECK-LABEL: store_store_release
+; CHECKALL-LABEL: store_store_release
   store atomic i32 %val1, i32* %mem1 release, align 4
   store atomic i32 %val2, i32* %mem2 release, align 4
 
@@ -391,8 +379,10 @@
 ; CHECK-T1: ___sync_lock_test_and_set
 ; CHECK-T1: ___sync_lock_test_and_set
 
-; CHECK-T1-M0: __atomic_store_4
-; CHECK-T1-M0: __atomic_store_4
+; CHECK-T1-M0: dmb
+; CHECK-T1-M0: str r1, [r0]
+; CHECK-T1-M0: dmb
+; CHECK-T1-M0: str r3, [r2]
 
 ; CHECK-BAREMETAL-NOT: dmb
 ; CHECK-BAREMETAL: str r1, [r0]
@@ -403,7 +393,7 @@
 }
 
 define void @load_fence_store_monotonic(i32* %mem1, i32* %mem2) {
-; CHECK-LABEL: load_fence_store_monotonic
+; CHECKALL-LABEL: load_fence_store_monotonic
   %val = load atomic i32, i32* %mem1 monotonic, align 4
   fence seq_cst
   store atomic i32 %val, i32* %mem2 monotonic, align 4
@@ -412,9 +402,9 @@
 ; CHECK: dmb
 ; CHECK: str [[R0]], [r1]
 
-; CHECK-T1-M0: __atomic_load_4
+; CHECK-T1-M0: ldr [[R0:r[0-9]]], [{{r[0-9]+}}]
 ; CHECK-T1-M0: dmb
-; CHECK-T1-M0: __atomic_store_4
+; CHECK-T1-M0: str [[R0]], [{{r[0-9]+}}]
 
 ; CHECK-T1: ldr [[R0:r[0-9]]], [{{r[0-9]+}}]
 ; CHECK-T1: {{dmb|bl ___sync_synchronize}}
Index: llvm/test/CodeGen/ARM/atomic-load-store.ll
===================================================================
--- llvm/test/CodeGen/ARM/atomic-load-store.ll
+++ llvm/test/CodeGen/ARM/atomic-load-store.ll
@@ -38,8 +38,7 @@
 ; ARMV4-LABEL: test1:
 ; ARMV4:       @ %bb.0:
 ; ARMV4-NEXT:    push {r11, lr}
-; ARMV4-NEXT:    mov r2, #5
-; ARMV4-NEXT:    bl __atomic_store_4
+; ARMV4-NEXT:    bl __sync_lock_test_and_set_4
 ; ARMV4-NEXT:    pop {r11, lr}
 ; ARMV4-NEXT:    mov pc, lr
 ;
@@ -91,8 +90,9 @@
 ; ARMV4-LABEL: test2:
 ; ARMV4:       @ %bb.0:
 ; ARMV4-NEXT:    push {r11, lr}
-; ARMV4-NEXT:    mov r1, #5
-; ARMV4-NEXT:    bl __atomic_load_4
+; ARMV4-NEXT:    mov r1, #0
+; ARMV4-NEXT:    mov r2, #0
+; ARMV4-NEXT:    bl __sync_val_compare_and_swap_4
 ; ARMV4-NEXT:    pop {r11, lr}
 ; ARMV4-NEXT:    mov pc, lr
 ;
@@ -139,15 +139,8 @@
 ;
 ; ARMV4-LABEL: test3:
 ; ARMV4:       @ %bb.0:
-; ARMV4-NEXT:    push {r4, lr}
-; ARMV4-NEXT:    mov r4, r1
-; ARMV4-NEXT:    mov r1, #0
-; ARMV4-NEXT:    bl __atomic_load_1
-; ARMV4-NEXT:    mov r1, r0
-; ARMV4-NEXT:    mov r0, r4
-; ARMV4-NEXT:    mov r2, #0
-; ARMV4-NEXT:    bl __atomic_store_1
-; ARMV4-NEXT:    pop {r4, lr}
+; ARMV4-NEXT:    ldrb r0, [r0]
+; ARMV4-NEXT:    strb r0, [r1]
 ; ARMV4-NEXT:    mov pc, lr
 ;
 ; ARMV6-LABEL: test3:
@@ -212,12 +205,12 @@
 ; ARMV4:       @ %bb.0:
 ; ARMV4-NEXT:    push {r4, lr}
 ; ARMV4-NEXT:    mov r4, r1
-; ARMV4-NEXT:    mov r1, #5
-; ARMV4-NEXT:    bl __atomic_load_1
+; ARMV4-NEXT:    mov r1, #0
+; ARMV4-NEXT:    mov r2, #0
+; ARMV4-NEXT:    bl __sync_val_compare_and_swap_1
 ; ARMV4-NEXT:    mov r1, r0
 ; ARMV4-NEXT:    mov r0, r4
-; ARMV4-NEXT:    mov r2, #5
-; ARMV4-NEXT:    bl __atomic_store_1
+; ARMV4-NEXT:    bl __sync_lock_test_and_set_1
 ; ARMV4-NEXT:    pop {r4, lr}
 ; ARMV4-NEXT:    mov pc, lr
 ;
@@ -283,8 +276,14 @@
 ; ARMV4-LABEL: test_old_load_64bit:
 ; ARMV4:       @ %bb.0:
 ; ARMV4-NEXT:    push {r11, lr}
-; ARMV4-NEXT:    mov r1, #5
-; ARMV4-NEXT:    bl __atomic_load_8
+; ARMV4-NEXT:    sub sp, sp, #8
+; ARMV4-NEXT:    mov r1, #0
+; ARMV4-NEXT:    mov r2, #0
+; ARMV4-NEXT:    mov r3, #0
+; ARMV4-NEXT:    str r1, [sp]
+; ARMV4-NEXT:    str r1, [sp, #4]
+; ARMV4-NEXT:    bl __sync_val_compare_and_swap_8
+; ARMV4-NEXT:    add sp, sp, #8
 ; ARMV4-NEXT:    pop {r11, lr}
 ; ARMV4-NEXT:    mov pc, lr
 ;
@@ -401,11 +400,7 @@
 ; ARMV4-LABEL: test_old_store_64bit:
 ; ARMV4:       @ %bb.0:
 ; ARMV4-NEXT:    push {r11, lr}
-; ARMV4-NEXT:    sub sp, sp, #8
-; ARMV4-NEXT:    mov r1, #5
-; ARMV4-NEXT:    str r1, [sp]
-; ARMV4-NEXT:    bl __atomic_store_8
-; ARMV4-NEXT:    add sp, sp, #8
+; ARMV4-NEXT:    bl __sync_lock_test_and_set_8
 ; ARMV4-NEXT:    pop {r11, lr}
 ; ARMV4-NEXT:    mov pc, lr
 ;
Index: llvm/test/CodeGen/ARM/atomic-64bit.ll
===================================================================
--- llvm/test/CodeGen/ARM/atomic-64bit.ll
+++ llvm/test/CodeGen/ARM/atomic-64bit.ll
@@ -3,7 +3,7 @@
 ; 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=armv8m.base--none-eabi | FileCheck %s --check-prefix=CHECK-M
 
 define i64 @test1(i64* %ptr, i64 %val) {
 ; CHECK-LABEL: test1:
Index: llvm/lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1357,27 +1357,20 @@
   }
 
   // Compute supported atomic widths.
-  if (Subtarget->isTargetLinux() ||
-      (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
-    // For targets where __sync_* routines are reliably available, we use them
-    // if necessary.
-    //
-    // ARM Linux always supports 64-bit atomics through kernel-assisted atomic
-    // routines (kernel 3.1 or later). FIXME: Not with compiler-rt?
+  if (Subtarget->isMClass()) {
+    // Cortex-M besides Cortex-M0 has 32-bit atomics.
     //
-    // ARMv6 targets have native instructions in ARM mode. For Thumb mode,
-    // such targets should provide __sync_* routines, which use the ARM mode
-    // instructions. (ARMv6 doesn't have dmb, but it has an equivalent
-    // encoding; see ARMISD::MEMBARRIER_MCR.)
-    setMaxAtomicSizeInBitsSupported(64);
-  } else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
-             Subtarget->hasForced32BitAtomics()) {
-    // Cortex-M (besides Cortex-M0) have 32-bit atomics.
+    // Cortex-M0 is missing ldrex/strex, so we generate __sync_* calls.
+    // We assume the user somehow makes that lock-free.
     setMaxAtomicSizeInBitsSupported(32);
   } else {
-    // We can't assume anything about other targets; just use libatomic
-    // routines.
-    setMaxAtomicSizeInBitsSupported(0);
+    // v7 has 64-bit atomics. Some v6 variants have 64-bit atomics, some
+    // have 32-bit atomics. Older variants have no atomics, but they
+    // might be emulated on some targets.  We completely ignore all this,
+    // and just assume appropriate __sync_* routines are available on targets
+    // that don't have the appropriate native instructions.  (In practice,
+    // such routines exist on Linux. We assume everyone else copies Linux.)
+    setMaxAtomicSizeInBitsSupported(64);
   }
 
   setMaxDivRemBitWidthSupported(64);
Index: clang/test/CodeGenOpenCL/atomic-ops-libcall.cl
===================================================================
--- clang/test/CodeGenOpenCL/atomic-ops-libcall.cl
+++ clang/test/CodeGenOpenCL/atomic-ops-libcall.cl
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -no-opaque-pointers < %s -cl-std=CL2.0 -triple spir64 -emit-llvm | FileCheck -check-prefix=SPIR %s
-// RUN: %clang_cc1 -no-opaque-pointers < %s -cl-std=CL2.0 -triple armv5e-none-linux-gnueabi -emit-llvm | FileCheck -check-prefix=ARM %s
+// RUN: %clang_cc1 -no-opaque-pointers < %s -cl-std=CL2.0 -triple riscv32-none-linux-gnueabi -emit-llvm | FileCheck -check-prefix=ARM %s
 typedef enum memory_order {
   memory_order_relaxed = __ATOMIC_RELAXED,
   memory_order_acquire = __ATOMIC_ACQUIRE,
Index: clang/test/CodeGenCXX/threadsafe-statics-no-atomic.cpp
===================================================================
--- clang/test/CodeGenCXX/threadsafe-statics-no-atomic.cpp
+++ clang/test/CodeGenCXX/threadsafe-statics-no-atomic.cpp
@@ -1,5 +1,5 @@
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
-// RUN: %clang_cc1 -emit-llvm -triple=thumbv6m-eabi -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple=riscv32 -o - %s | FileCheck %s
 
 int f();
 
Index: clang/test/CodeGen/pr45476.cpp
===================================================================
--- clang/test/CodeGen/pr45476.cpp
+++ clang/test/CodeGen/pr45476.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple arm-unknown-linux-gnueabi -emit-llvm %s -o - | FileCheck -check-prefix=LIBCALL %s
+// RUN: %clang_cc1 -triple riscv32-unknown-linux-gnueabi -emit-llvm %s -o - | FileCheck -check-prefix=LIBCALL %s
 // RUN: %clang_cc1 -triple armv8-eabi -emit-llvm %s -o - | FileCheck -check-prefix=NATIVE %s
 // PR45476
 
Index: clang/test/CodeGen/c11atomics.c
===================================================================
--- clang/test/CodeGen/c11atomics.c
+++ clang/test/CodeGen/c11atomics.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=armv5-unknown-freebsd -std=c11 | FileCheck %s
+// RUN: %clang_cc1 -no-opaque-pointers %s -emit-llvm -o - -triple=riscv32-unknown-freebsd -std=c11 | FileCheck %s
 
 // Test that we are generating atomicrmw instructions, rather than
 // compare-exchange loops for common atomic ops.  This makes a big difference
@@ -73,7 +73,7 @@
 // CHECK: testdec
 void testdec(void)
 {
-  // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
+  // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
   b--;
   // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst, align 4
   i--;
@@ -81,7 +81,7 @@
   l--;
   // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst, align 2
   s--;
-  // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
+  // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
   --b;
   // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst, align 4
   // CHECK: sub i32
@@ -96,7 +96,7 @@
 // CHECK: testaddeq
 void testaddeq(void)
 {
-  // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
+  // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
   // CHECK: atomicrmw add i32* @i, i32 42 seq_cst, align 4
   // CHECK: atomicrmw add i64* @l, i64 42 seq_cst, align 8
   // CHECK: atomicrmw add i16* @s, i16 42 seq_cst, align 2
@@ -108,7 +108,7 @@
 // CHECK: testsubeq
 void testsubeq(void)
 {
-  // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
+  // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
   // CHECK: atomicrmw sub i32* @i, i32 42 seq_cst, align 4
   // CHECK: atomicrmw sub i64* @l, i64 42 seq_cst, align 8
   // CHECK: atomicrmw sub i16* @s, i16 42 seq_cst, align 2
@@ -120,7 +120,7 @@
 // CHECK: testxoreq
 void testxoreq(void)
 {
-  // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
+  // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
   // CHECK: atomicrmw xor i32* @i, i32 42 seq_cst, align 4
   // CHECK: atomicrmw xor i64* @l, i64 42 seq_cst, align 8
   // CHECK: atomicrmw xor i16* @s, i16 42 seq_cst, align 2
@@ -132,7 +132,7 @@
 // CHECK: testoreq
 void testoreq(void)
 {
-  // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
+  // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
   // CHECK: atomicrmw or i32* @i, i32 42 seq_cst, align 4
   // CHECK: atomicrmw or i64* @l, i64 42 seq_cst, align 8
   // CHECK: atomicrmw or i16* @s, i16 42 seq_cst, align 2
@@ -144,7 +144,7 @@
 // CHECK: testandeq
 void testandeq(void)
 {
-  // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
+  // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 noundef 1, i8* noundef @b
   // CHECK: atomicrmw and i32* @i, i32 42 seq_cst, align 4
   // CHECK: atomicrmw and i64* @l, i64 42 seq_cst, align 8
   // CHECK: atomicrmw and i16* @s, i16 42 seq_cst, align 2
@@ -154,7 +154,7 @@
   s &= 42;
 }
 
-// CHECK-LABEL: define{{.*}} arm_aapcscc void @testFloat(float*
+// CHECK-LABEL: define{{.*}} void @testFloat(float*
 void testFloat(_Atomic(float) *fp) {
 // CHECK:      [[FP:%.*]] = alloca float*
 // CHECK-NEXT: [[X:%.*]] = alloca float
@@ -173,7 +173,7 @@
 // CHECK-NEXT: [[T0:%.*]] = load float*, float** [[FP]]
 // CHECK-NEXT: [[T1:%.*]] = bitcast float* [[T0]] to i8*
 // CHECK-NEXT: [[T2:%.*]] = bitcast float* [[TMP0]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 noundef 4, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_load(i32 noundef 4, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
 // CHECK-NEXT: [[T3:%.*]] = load float, float* [[TMP0]], align 4
 // CHECK-NEXT: store float [[T3]], float* [[F]]
   float f = *fp;
@@ -183,13 +183,13 @@
 // CHECK-NEXT: store float [[T0]], float* [[TMP1]], align 4
 // CHECK-NEXT: [[T2:%.*]] = bitcast float* [[T1]] to i8*
 // CHECK-NEXT: [[T3:%.*]] = bitcast float* [[TMP1]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 noundef 4, i8* noundef [[T2]], i8* noundef [[T3]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_store(i32 noundef 4, i8* noundef [[T2]], i8* noundef [[T3]], i32 noundef 5)
   *fp = f;
 
 // CHECK-NEXT: ret void
 }
 
-// CHECK: define{{.*}} arm_aapcscc void @testComplexFloat([[CF:{ float, float }]]*
+// CHECK: define{{.*}} void @testComplexFloat([[CF:{ float, float }]]*
 void testComplexFloat(_Atomic(_Complex float) *fp) {
 // CHECK:      [[FP:%.*]] = alloca [[CF]]*, align 4
 // CHECK-NEXT: [[X:%.*]] = alloca [[CF]], align 8
@@ -214,7 +214,7 @@
 // CHECK-NEXT: [[T0:%.*]] = load [[CF]]*, [[CF]]** [[FP]]
 // CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[T0]] to i8*
 // CHECK-NEXT: [[T2:%.*]] = bitcast [[CF]]* [[TMP0]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 noundef 8, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_load(i32 noundef 8, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[TMP0]], i32 0, i32 0
 // CHECK-NEXT: [[R:%.*]] = load float, float* [[T0]]
 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[TMP0]], i32 0, i32 1
@@ -236,7 +236,7 @@
 // CHECK-NEXT: store float [[I]], float* [[T1]]
 // CHECK-NEXT: [[T0:%.*]] = bitcast [[CF]]* [[DEST]] to i8*
 // CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[TMP1]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 noundef 8, i8* noundef [[T0]], i8* noundef [[T1]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_store(i32 noundef 8, i8* noundef [[T0]], i8* noundef [[T1]], i32 noundef 5)
   *fp = f;
 
 // CHECK-NEXT: ret void
@@ -244,7 +244,7 @@
 
 typedef struct { short x, y, z, w; } S;
 _Atomic S testStructGlobal = (S){1, 2, 3, 4};
-// CHECK: define{{.*}} arm_aapcscc void @testStruct([[S:.*]]*
+// CHECK: define{{.*}} void @testStruct([[S:.*]]*
 void testStruct(_Atomic(S) *fp) {
 // CHECK:      [[FP:%.*]] = alloca [[S]]*, align 4
 // CHECK-NEXT: [[X:%.*]] = alloca [[S]], align 8
@@ -276,7 +276,7 @@
 // CHECK-NEXT: [[T0:%.*]] = load [[S]]*, [[S]]** [[FP]]
 // CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[T0]] to i8*
 // CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 noundef 8, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_load(i32 noundef 8, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
   S f = *fp;
 
 // CHECK-NEXT: [[T0:%.*]] = load [[S]]*, [[S]]** [[FP]]
@@ -285,7 +285,7 @@
 // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[T1]], i8* align 2 [[T2]], i32 8, i1 false)
 // CHECK-NEXT: [[T3:%.*]] = bitcast [[S]]* [[T0]] to i8*
 // CHECK-NEXT: [[T4:%.*]] = bitcast [[S]]* [[TMP0]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 noundef 8, i8* noundef [[T3]], i8* noundef [[T4]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_store(i32 noundef 8, i8* noundef [[T3]], i8* noundef [[T4]], i32 noundef 5)
   *fp = f;
 
 // CHECK-NEXT: ret void
@@ -293,7 +293,7 @@
 
 typedef struct { short x, y, z; } PS;
 _Atomic PS testPromotedStructGlobal = (PS){1, 2, 3};
-// CHECK: define{{.*}} arm_aapcscc void @testPromotedStruct([[APS:.*]]*
+// CHECK: define{{.*}} void @testPromotedStruct([[APS:.*]]*
 void testPromotedStruct(_Atomic(PS) *fp) {
 // CHECK:      [[FP:%.*]] = alloca [[APS]]*, align 4
 // CHECK-NEXT: [[X:%.*]] = alloca [[APS]], align 8
@@ -331,7 +331,7 @@
 // CHECK-NEXT: [[T0:%.*]] = load [[APS]]*, [[APS]]** [[FP]]
 // CHECK-NEXT: [[T1:%.*]] = bitcast [[APS]]* [[T0]] to i8*
 // CHECK-NEXT: [[T2:%.*]] = bitcast [[APS]]* [[TMP0]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 noundef 8, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_load(i32 noundef 8, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP0]], i32 0, i32 0
 // CHECK-NEXT: [[T1:%.*]] = bitcast [[PS]]* [[F]] to i8*
 // CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T0]] to i8*
@@ -347,13 +347,13 @@
 // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 [[T2]], i8* align 2 [[T3]], i32 6, i1 false)
 // CHECK-NEXT: [[T4:%.*]] = bitcast [[APS]]* [[T0]] to i8*
 // CHECK-NEXT: [[T5:%.*]] = bitcast [[APS]]* [[TMP1]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 noundef 8, i8* noundef [[T4]], i8* noundef [[T5]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_store(i32 noundef 8, i8* noundef [[T4]], i8* noundef [[T5]], i32 noundef 5)
   *fp = f;
 
 // CHECK-NEXT: [[T0:%.*]] = load [[APS]]*, [[APS]]** [[FP]], align 4
 // CHECK-NEXT: [[T1:%.*]] = bitcast [[APS]]* [[T0]] to i8*
 // CHECK-NEXT: [[T2:%.*]] = bitcast [[APS]]* [[TMP3]] to i8*
-// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 noundef 8, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
+// CHECK-NEXT: call void @__atomic_load(i32 noundef 8, i8* noundef [[T1]], i8* noundef [[T2]], i32 noundef 5)
 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP3]], i32 0, i32 0
 // CHECK-NEXT: [[T1:%.*]] = bitcast %struct.PS* [[TMP2]] to i8*
 // CHECK-NEXT: [[T2:%.*]] = bitcast %struct.PS* [[T0]] to i8*
@@ -368,7 +368,7 @@
 }
 
 PS test_promoted_load(_Atomic(PS) *addr) {
-  // CHECK-LABEL: @test_promoted_load(%struct.PS* noalias sret(%struct.PS) align 2 %agg.result, { %struct.PS, [2 x i8] }* noundef %addr)
+  // CHECK-LABEL: @test_promoted_load({ %struct.PS, [2 x i8] }* noundef %addr)
   // CHECK:   [[ADDR_ARG:%.*]] = alloca { %struct.PS, [2 x i8] }*, align 4
   // CHECK:   [[ATOMIC_RES:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8
   // CHECK:   store { %struct.PS, [2 x i8] }* %addr, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
@@ -376,10 +376,10 @@
   // CHECK:   [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
   // CHECK:   [[ATOMIC_RES64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_RES]] to i64*
   // CHECK:   [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
-  // CHECK:   [[RES:%.*]] = call arm_aapcscc i64 @__atomic_load_8(i8* noundef [[ADDR8]], i32 noundef 5)
+  // CHECK:   [[RES:%.*]] = call i64 @__atomic_load_8(i8* noundef [[ADDR8]], i32 noundef 5)
   // CHECK:   store i64 [[RES]], i64* [[ATOMIC_RES64]], align 8
   // CHECK:   [[ATOMIC_RES_STRUCT:%.*]] = bitcast i64* [[ATOMIC_RES64]] to %struct.PS*
-  // CHECK:   [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %agg.result to i8*
+  // CHECK:   [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %retval to i8*
   // CHECK:   [[ATOMIC_RES8:%.*]] = bitcast %struct.PS* [[ATOMIC_RES_STRUCT]] to i8*
   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[AGG_RESULT8]], i8* align 8 [[ATOMIC_RES8]], i32 6, i1 false)
 
@@ -406,12 +406,12 @@
   // CHECK:   [[ATOMIC_VAL64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i64*
   // CHECK:   [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
   // CHECK:   [[VAL64:%.*]] = load i64, i64* [[ATOMIC_VAL64]], align 2
-  // CHECK:   call arm_aapcscc void @__atomic_store_8(i8* noundef [[ADDR8]], i64 noundef [[VAL64]], i32 noundef 5)
+  // CHECK:   call void @__atomic_store_8(i8* noundef [[ADDR8]], i64 noundef [[VAL64]], i32 noundef 5)
   __c11_atomic_store(addr, *val, 5);
 }
 
 PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) {
-  // CHECK-LABEL: @test_promoted_exchange(%struct.PS* noalias sret(%struct.PS) align 2 %agg.result, { %struct.PS, [2 x i8] }* noundef %addr, %struct.PS* noundef %val)
+  // CHECK-LABEL: @test_promoted_exchange({ %struct.PS, [2 x i8] }* noundef %addr, %struct.PS* noundef %val)
   // CHECK:   [[ADDR_ARG:%.*]] = alloca { %struct.PS, [2 x i8] }*, align 4
   // CHECK:   [[VAL_ARG:%.*]] = alloca %struct.PS*, align 4
   // CHECK:   [[NONATOMIC_TMP:%.*]] = alloca %struct.PS, align 2
@@ -432,10 +432,10 @@
   // CHECK:   [[ATOMIC_RES64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_RES]] to i64*
   // CHECK:   [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
   // CHECK:   [[VAL64:%.*]] = load i64, i64* [[ATOMIC_VAL64]], align 2
-  // CHECK:   [[RES:%.*]] = call arm_aapcscc i64 @__atomic_exchange_8(i8* noundef [[ADDR8]], i64 noundef [[VAL64]], i32 noundef 5)
+  // CHECK:   [[RES:%.*]] = call i64 @__atomic_exchange_8(i8* noundef [[ADDR8]], i64 noundef [[VAL64]], i32 noundef 5)
   // CHECK:   store i64 [[RES]], i64* [[ATOMIC_RES64]], align 8
   // CHECK:   [[ATOMIC_RES_STRUCT:%.*]] = bitcast i64* [[ATOMIC_RES64]] to %struct.PS*
-  // CHECK:   [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %agg.result to i8*
+  // CHECK:   [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %retval to i8*
   // CHECK:   [[ATOMIC_RES8:%.*]] = bitcast %struct.PS* [[ATOMIC_RES_STRUCT]] to i8*
   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 [[AGG_RESULT8]], i8* align 8 [[ATOMIC_RES8]], i32 6, i1 false)
   return __c11_atomic_exchange(addr, *val, 5);
@@ -470,7 +470,7 @@
   // CHECK:   [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
   // CHECK:   [[ATOMIC_DESIRED8:%.*]] = bitcast i64* [[ATOMIC_DESIRED64]] to i8*
   // CHECK:   [[NEW64:%.*]] = load i64, i64* [[ATOMIC_NEW64]], align 2
-  // CHECK:   [[RES:%.*]] = call arm_aapcscc zeroext i1 @__atomic_compare_exchange_8(i8* noundef [[ADDR8]], i8* noundef [[ATOMIC_DESIRED8]], i64 noundef [[NEW64]], i32 noundef 5, i32 noundef 5)
+  // CHECK:   [[RES:%.*]] = call zeroext i1 @__atomic_compare_exchange_8(i8* noundef [[ADDR8]], i8* noundef [[ATOMIC_DESIRED8]], i64 noundef [[NEW64]], i32 noundef 5, i32 noundef 5)
   // CHECK:   ret i1 [[RES]]
   return __c11_atomic_compare_exchange_strong(addr, desired, *new, 5, 5);
 }
@@ -479,12 +479,12 @@
 
 struct Empty test_empty_struct_load(_Atomic(struct Empty)* empty) {
   // CHECK-LABEL: @test_empty_struct_load(
-  // CHECK: call arm_aapcscc zeroext i8 @__atomic_load_1(i8* noundef %{{.*}}, i32 noundef 5)
+  // CHECK: call zeroext i8 @__atomic_load_1(i8* noundef %{{.*}}, i32 noundef 5)
   return __c11_atomic_load(empty, 5);
 }
 
 void test_empty_struct_store(_Atomic(struct Empty)* empty, struct Empty value) {
   // CHECK-LABEL: @test_empty_struct_store(
-  // CHECK: call arm_aapcscc void @__atomic_store_1(i8* noundef %{{.*}}, i8 noundef zeroext %{{.*}}, i32 noundef 5)
+  // CHECK: call void @__atomic_store_1(i8* noundef %{{.*}}, i8 noundef zeroext %{{.*}}, i32 noundef 5)
   __c11_atomic_store(empty, value, 5);
 }
Index: clang/test/CodeGen/atomics-inlining.c
===================================================================
--- clang/test/CodeGen/atomics-inlining.c
+++ clang/test/CodeGen/atomics-inlining.c
@@ -37,16 +37,16 @@
   (void)__atomic_store(&a1, &a2, memory_order_seq_cst);
 
 // ARM-LABEL: define{{.*}} void @test1
-// ARM: = call{{.*}} zeroext i8 @__atomic_load_1(ptr noundef @c1
-// ARM: call{{.*}} void @__atomic_store_1(ptr noundef @c1, i8 noundef zeroext
-// ARM: = call{{.*}} zeroext i16 @__atomic_load_2(ptr noundef @s1
-// ARM: call{{.*}} void @__atomic_store_2(ptr noundef @s1, i16 noundef zeroext
-// ARM: = call{{.*}} i32 @__atomic_load_4(ptr noundef @i1
-// ARM: call{{.*}} void @__atomic_store_4(ptr noundef @i1, i32 noundef
-// ARM: = call{{.*}} i64 @__atomic_load_8(ptr noundef @ll1
-// ARM: call{{.*}} void @__atomic_store_8(ptr noundef @ll1, i64 noundef
-// ARM: call{{.*}} void @__atomic_load(i32 noundef 100, ptr noundef @a1, ptr noundef @a2
-// ARM: call{{.*}} void @__atomic_store(i32 noundef 100, ptr noundef @a1, ptr noundef @a2
+// ARM: = load atomic i8, ptr @c1 seq_cst, align 1
+// ARM: store atomic i8 {{.*}}, ptr @c1 seq_cst, align 1
+// ARM: = load atomic i16, ptr @s1 seq_cst, align 2
+// ARM: store atomic i16 {{.*}}, ptr @s1 seq_cst, align 2
+// ARM: = load atomic i32, ptr @i1 seq_cst, align 4
+// ARM: store atomic i32 {{.*}}, ptr @i1 seq_cst, align 4
+// ARM: = load atomic i64, ptr @ll1 seq_cst, align 8
+// ARM: store atomic i64 {{.*}}, ptr @ll1 seq_cst, align 8
+// ARM: call void @__atomic_load(i32 noundef 100, ptr noundef @a1, ptr noundef @a2
+// ARM: call void @__atomic_store(i32 noundef 100, ptr noundef @a1, ptr noundef @a2
 
 // PPC32-LABEL: define{{.*}} void @test1
 // PPC32: = load atomic i8, ptr @c1 seq_cst, align 1
Index: clang/test/CodeGen/atomic-ops-libcall.c
===================================================================
--- clang/test/CodeGen/atomic-ops-libcall.c
+++ clang/test/CodeGen/atomic-ops-libcall.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -no-opaque-pointers < %s -triple armv5e-none-linux-gnueabi -emit-llvm -O1 | FileCheck %s
+// RUN: %clang_cc1 -no-opaque-pointers < %s -triple riscv32-none-linux-gnueabi -emit-llvm -O1 | FileCheck %s
 
 // FIXME: This file should not be checking -O1 output.
 // Ie, it is testing many IR optimizer passes as part of front-end verification.
Index: clang/test/CodeGen/arm-atomics-m0.c
===================================================================
--- clang/test/CodeGen/arm-atomics-m0.c
+++ clang/test/CodeGen/arm-atomics-m0.c
@@ -11,14 +11,14 @@
 void test_presence(void)
 {
   // CHECK-LABEL: @test_presence
-  // CHECK: __atomic_fetch_add_4
+  // CHECK: atomicrmw add
   __atomic_fetch_add(&i, 1, memory_order_seq_cst);
-  // CHECK: __atomic_fetch_sub_4
+  // CHECK: atomicrmw sub
   __atomic_fetch_sub(&i, 1, memory_order_seq_cst);
-  // CHECK: __atomic_load_4
+  // CHECK: load atomic
   int r;
   __atomic_load(&i, &r, memory_order_seq_cst);
-  // CHECK: __atomic_store_4
+  // CHECK: store atomic
   r = 0;
   __atomic_store(&i, &r, memory_order_seq_cst);
 
Index: clang/lib/Basic/Targets/ARM.cpp
===================================================================
--- clang/lib/Basic/Targets/ARM.cpp
+++ clang/lib/Basic/Targets/ARM.cpp
@@ -138,18 +138,22 @@
 void ARMTargetInfo::setAtomic() {
   // when triple does not specify a sub arch,
   // then we are not using inline atomics
-  bool ShouldUseInlineAtomic =
-      (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||
-      (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);
-  // Cortex M does not support 8 byte atomics, while general Thumb2 does.
   if (ArchProfile == llvm::ARM::ProfileKind::M) {
+    // Cortex-M besides Cortex-M0 has 32-bit atomics.
+    //
+    // Cortex-M0 is missing ldrex/strex, so we generate __sync_* calls. (In
+    // most cases, these can be implemented by disabling interrupts.)
     MaxAtomicPromoteWidth = 32;
-    if (ShouldUseInlineAtomic)
-      MaxAtomicInlineWidth = 32;
+    MaxAtomicInlineWidth = 32;
   } else {
+    // v7 has 64-bit atomics. Some v6 variants have 64-bit atomics, some
+    // have 32-bit atomics. Older variants have no atomics, but they
+    // might be emulated on some targets.  We completely ignore all this,
+    // and just assume appropriate __sync_* routines are available on targets
+    // that don't have the appropriate native instructions.  (In practice,
+    // such routines exist on Linux. We assume everyone else copies Linux.)
     MaxAtomicPromoteWidth = 64;
-    if (ShouldUseInlineAtomic)
-      MaxAtomicInlineWidth = 64;
+    MaxAtomicInlineWidth = 64;
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to