Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions clang/lib/Basic/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,24 @@ void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
}

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) {
// M-class only ever supports 32-bit atomics. Cortex-M0 doesn't have
// any atomics.
MaxAtomicPromoteWidth = 32;
if (ShouldUseInlineAtomic)
if (ArchVersion >= 7)
MaxAtomicInlineWidth = 32;
} else {
// A-class targets have up to 64-bit atomics.
//
// On Linux, 64-bit atomics are always available through kernel helpers
// (which are lock-free). Otherwise, atomics are available on v6 or later.
//
// (Thumb doesn't matter; for Thumbv6, we just use a library call which
// switches out of Thumb mode.)
//
// This should match setMaxAtomicSizeInBitsSupported() in the backend.
MaxAtomicPromoteWidth = 64;
if (ShouldUseInlineAtomic)
if (getTriple().getOS() == llvm::Triple::Linux || ArchVersion >= 6)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused by the word Inline in the identifier. Surely in the case where Linux does the atomic operation by calling a kernel helper function, the one thing it isn't is inline!

But I see that CodeGenFunction::EmitAtomicExpr really seems to be treating it as "maximum efficient atomic size", in that it emits a warning for anything bigger saying that it might be slow.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, "inline" in this context really means lock-free. Which is often the same thing, but there are various edge cases (https://llvm.org/docs/Atomics.html#libcalls-sync).

MaxAtomicInlineWidth = 64;
}
}
Expand Down
13 changes: 8 additions & 5 deletions clang/test/CodeGen/atomic-arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// RUN: %clang_cc1 -triple thumbv7m-apple-unknown-macho %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-V7M
// RUN: %clang_cc1 -triple thumbv7-apple-ios13.0 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HOSTED
// RUN: %clang_cc1 -triple thumbv7k-apple-watchos5.0 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HOSTED

// RUN: %clang_cc1 -triple arm-linux-gnueabi %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HOSTED
// RUN: %clang_cc1 -triple armv7-none-eabi %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HOSTED
// RUN: %clang_cc1 -triple thumbv6k-none-eabi %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HOSTED
// RUN: %clang_cc1 -triple armv5-none-eabi %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-V6M

// CHECK-V6M: @always1 = global i32 0
// CHECK-V6M: @always4 = global i32 0
Expand All @@ -22,7 +25,7 @@ int always8 = __atomic_always_lock_free(8, 0);

int lock_free_1() {
// CHECK-LABEL: @lock_free_1
// CHECK-V6M: [[RES:%.*]] = call arm_aapcscc zeroext i1 @__atomic_is_lock_free(i32 noundef 1, ptr noundef null)
// CHECK-V6M: [[RES:%.*]] = call{{.*}}zeroext i1 @__atomic_is_lock_free(i32 noundef 1, ptr noundef null)
// CHECK-V6M: [[RES32:%.*]] = zext i1 [[RES]] to i32
// CHECK-V6M: ret i32 [[RES32]]

Expand All @@ -33,7 +36,7 @@ int lock_free_1() {

int lock_free_4() {
// CHECK-LABEL: @lock_free_4
// CHECK-V6M: [[RES:%.*]] = call arm_aapcscc zeroext i1 @__atomic_is_lock_free(i32 noundef 4, ptr noundef null)
// CHECK-V6M: [[RES:%.*]] = call{{.*}}zeroext i1 @__atomic_is_lock_free(i32 noundef 4, ptr noundef null)
// CHECK-V6M: [[RES32:%.*]] = zext i1 [[RES]] to i32
// CHECK-V6M: ret i32 [[RES32]]

Expand All @@ -44,11 +47,11 @@ int lock_free_4() {

int lock_free_8() {
// CHECK-LABEL: @lock_free_8
// CHECK-V6M: [[RES:%.*]] = call arm_aapcscc zeroext i1 @__atomic_is_lock_free(i32 noundef 8, ptr noundef null)
// CHECK-V6M: [[RES:%.*]] = call{{.*}}zeroext i1 @__atomic_is_lock_free(i32 noundef 8, ptr noundef null)
// CHECK-V6M: [[RES32:%.*]] = zext i1 [[RES]] to i32
// CHECK-V6M: ret i32 [[RES32]]

// CHECK-V7M: [[RES:%.*]] = call arm_aapcscc zeroext i1 @__atomic_is_lock_free(i32 noundef 8, ptr noundef null)
// CHECK-V7M: [[RES:%.*]] = call{{.*}}zeroext i1 @__atomic_is_lock_free(i32 noundef 8, ptr noundef null)
// CHECK-V7M: [[RES32:%.*]] = zext i1 [[RES]] to i32
// CHECK-V7M: ret i32 [[RES32]]

Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/pr45476.cpp
Original file line number Diff line number Diff line change
@@ -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 armv6m-eabi -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

Expand Down