diff --git a/llvm/lib/Target/AArch64/AArch64InstrAtomics.td b/llvm/lib/Target/AArch64/AArch64InstrAtomics.td --- a/llvm/lib/Target/AArch64/AArch64InstrAtomics.td +++ b/llvm/lib/Target/AArch64/AArch64InstrAtomics.td @@ -27,11 +27,18 @@ // supported, but when they're relaxed and anything can be used, all the // standard modes would be valid and may give efficiency gains. -// A atomic load operation that actually needs acquire semantics. +// An atomic load operation that needs sequential consistency. +class seq_cst_load + : PatFrag<(ops node:$ptr), (base node:$ptr)> { + let IsAtomic = 1; + let IsAtomicOrderingSequentiallyConsistent = 1; +} + +// An atomic load operation that needs acquire semantics. class acquiring_load : PatFrag<(ops node:$ptr), (base node:$ptr)> { let IsAtomic = 1; - let IsAtomicOrderingAcquireOrStronger = 1; + let IsAtomicOrderingAcquire = 1; } // An atomic load operation that does not need either acquire or release @@ -42,7 +49,20 @@ let IsAtomicOrderingAcquireOrStronger = 0; } +let Predicates = [HasRCPC] in { + // v8.3 Release Consistent Processor Consistent support, optional in v8.2. + // 8-bit loads + def : Pat<(acquiring_load GPR64sp:$ptr), (LDAPRB GPR64sp:$ptr)>; + // 16-bit loads + def : Pat<(acquiring_load GPR64sp:$ptr), (LDAPRH GPR64sp:$ptr)>; + // 32-bit loads + def : Pat<(acquiring_load GPR64sp:$ptr), (LDAPRW GPR64sp:$ptr)>; + // 64-bit loads + def : Pat<(acquiring_load GPR64sp:$ptr), (LDAPRX GPR64sp:$ptr)>; +} + // 8-bit loads +def : Pat<(seq_cst_load GPR64sp:$ptr), (LDARB GPR64sp:$ptr)>; def : Pat<(acquiring_load GPR64sp:$ptr), (LDARB GPR64sp:$ptr)>; def : Pat<(relaxed_load (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$offset)), @@ -58,6 +78,7 @@ (LDURBBi GPR64sp:$Rn, simm9:$offset)>; // 16-bit loads +def : Pat<(seq_cst_load GPR64sp:$ptr), (LDARH GPR64sp:$ptr)>; def : Pat<(acquiring_load GPR64sp:$ptr), (LDARH GPR64sp:$ptr)>; def : Pat<(relaxed_load (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend)), @@ -73,6 +94,7 @@ (LDURHHi GPR64sp:$Rn, simm9:$offset)>; // 32-bit loads +def : Pat<(seq_cst_load GPR64sp:$ptr), (LDARW GPR64sp:$ptr)>; def : Pat<(acquiring_load GPR64sp:$ptr), (LDARW GPR64sp:$ptr)>; def : Pat<(relaxed_load (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend)), @@ -88,6 +110,7 @@ (LDURWi GPR64sp:$Rn, simm9:$offset)>; // 64-bit loads +def : Pat<(seq_cst_load GPR64sp:$ptr), (LDARX GPR64sp:$ptr)>; def : Pat<(acquiring_load GPR64sp:$ptr), (LDARX GPR64sp:$ptr)>; def : Pat<(relaxed_load (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend)), diff --git a/llvm/test/CodeGen/AArch64/atomics-rcpc.ll b/llvm/test/CodeGen/AArch64/atomics-rcpc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/atomics-rcpc.ll @@ -0,0 +1,57 @@ +; RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+rcpc -verify-machineinstrs < %s | FileCheck %s + +define i8 @test_load_8_rcpc(i8* %addr) { +; CHECK-LABEL: test_load_8_rcpc: +; CHECK: ldaprb w0, [x0] + %val = load atomic i8, i8* %addr acquire, align 1 + ret i8 %val +} + +define i8 @test_load_8_rcsc(i8* %addr) { +; CHECK-LABEL: test_load_8_rcsc: +; CHECK: ldarb w0, [x0] + %val = load atomic i8, i8* %addr seq_cst, align 1 + ret i8 %val +} + +define i16 @test_load_16_rcpc(i16* %addr) { +; CHECK-LABEL: test_load_16_rcpc: +; CHECK: ldaprh w0, [x0] + %val = load atomic i16, i16* %addr acquire, align 2 + ret i16 %val +} + +define i16 @test_load_16_rcsc(i16* %addr) { +; CHECK-LABEL: test_load_16_rcsc: +; CHECK: ldarh w0, [x0] + %val = load atomic i16, i16* %addr seq_cst, align 2 + ret i16 %val +} + +define i32 @test_load_32_rcpc(i32* %addr) { +; CHECK-LABEL: test_load_32_rcpc: +; CHECK: ldapr w0, [x0] + %val = load atomic i32, i32* %addr acquire, align 4 + ret i32 %val +} + +define i32 @test_load_32_rcsc(i32* %addr) { +; CHECK-LABEL: test_load_32_rcsc: +; CHECK: ldar w0, [x0] + %val = load atomic i32, i32* %addr seq_cst, align 4 + ret i32 %val +} + +define i64 @test_load_64_rcpc(i64* %addr) { +; CHECK-LABEL: test_load_64_rcpc: +; CHECK: ldapr x0, [x0] + %val = load atomic i64, i64* %addr acquire, align 8 + ret i64 %val +} + +define i64 @test_load_64_rcsc(i64* %addr) { +; CHECK-LABEL: test_load_64_rcsc: +; CHECK: ldar x0, [x0] + %val = load atomic i64, i64* %addr seq_cst, align 8 + ret i64 %val +}