Skip to content

Commit be6fe95

Browse files
committed
[RISCV] Implement a proposed mapping for Ztso
This change implements a proposed lowering from LLVM's memory model to the TSO memory model defined by the Ztso extension. Selecting the proposed mapping turns out to be an involved conversation that really didn't fit within a review description, so let me refer you to https://github.com/preames/public-notes/blob/master/riscv-tso-mappings.rst. This review implements the WMO compatible variant (the proposed one in that document). Ztso is currently accepted as an experimental extension in LLVM. Despite the fact the extension was recently ratified, I think we need to leave it as experimental until we have wide agreement on the chosen mapping for ABI purposes. I need to note that the current in-tree implementation defaults to generating WMO compatible fences. This is entirely compatible with the proposed mapping in this patch, but is unfortunately not compatible with the major alternative. The in tree implementation is explicitly experimental so the impact of this is limited, but it is worth calling out that if settle on the alternative we will have a minor ABI break. My apologies for not calling this out in the original patch; I had not realized at the time that one of our realistic choices for mappings wouldn't be WMO compatible. This patch only contains the changes for load/store and fence. That is, it does not change the lowering for atomicrmw operations. This is a sound thing to do under the proposed mapping since the existing WMO mappings remain compatible. I do plan to change these; I'm just working incrementally. Differential Revision: https://reviews.llvm.org/D143076
1 parent 20fba03 commit be6fe95

File tree

4 files changed

+357
-172
lines changed

4 files changed

+357
-172
lines changed

llvm/docs/RISCVUsage.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ The primary goal of experimental support is to assist in the process of ratifica
151151
LLVM implements the `0.2 draft specification <https://github.com/riscv/riscv-isa-manual/releases/tag/draft-20220831-bf5a151>`_.
152152

153153
``experimental-ztso``
154-
LLVM implements the `v0.1 proposed specification <https://github.com/riscv/riscv-isa-manual/releases/download/draft-20220723-10eea63/riscv-spec.pdf>`_ (see Chapter 25). Using will set appropriate ELF flags and attributes, but does not yet change code generation.
154+
LLVM implements the `v0.1 proposed specification <https://github.com/riscv/riscv-isa-manual/releases/download/draft-20220723-10eea63/riscv-spec.pdf>`_ (see Chapter 25). The mapping from the C/C++ memory model to Ztso has not yet been ratified in any standards document. There are multiple possible mappings, and they are *not* mutually ABI compatible. The mapping LLVM implements is ABI compatible with the default WMO mapping. This mapping may change and there is *explicitly* no ABI stability offered while the extension remains in experimental status. User beware.
155155

156156
``experimental-zvfh``
157157
LLVM implements `this draft text <https://github.com/riscv/riscv-v-spec/pull/780>`_.

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3721,11 +3721,25 @@ static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG,
37213721
return SDValue();
37223722
}
37233723

3724-
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) {
3724+
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG,
3725+
const RISCVSubtarget &Subtarget) {
37253726
SDLoc dl(Op);
3727+
AtomicOrdering FenceOrdering =
3728+
static_cast<AtomicOrdering>(Op.getConstantOperandVal(1));
37263729
SyncScope::ID FenceSSID =
37273730
static_cast<SyncScope::ID>(Op.getConstantOperandVal(2));
37283731

3732+
if (Subtarget.hasStdExtZtso()) {
3733+
// The only fence that needs an instruction is a sequentially-consistent
3734+
// cross-thread fence.
3735+
if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
3736+
FenceSSID == SyncScope::System)
3737+
return Op;
3738+
3739+
// MEMBARRIER is a compiler barrier; it codegens to a no-op.
3740+
return DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0));
3741+
}
3742+
37293743
// singlethread fences only synchronize with signal handlers on the same
37303744
// thread and thus only need to preserve instruction order, not actually
37313745
// enforce memory ordering.
@@ -3742,7 +3756,7 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
37423756
default:
37433757
report_fatal_error("unimplemented operand");
37443758
case ISD::ATOMIC_FENCE:
3745-
return LowerATOMIC_FENCE(Op, DAG);
3759+
return LowerATOMIC_FENCE(Op, DAG, Subtarget);
37463760
case ISD::GlobalAddress:
37473761
return lowerGlobalAddress(Op, DAG);
37483762
case ISD::BlockAddress:
@@ -13759,6 +13773,12 @@ void RISCVTargetLowering::LowerAsmOperandForConstraint(
1375913773
Instruction *RISCVTargetLowering::emitLeadingFence(IRBuilderBase &Builder,
1376013774
Instruction *Inst,
1376113775
AtomicOrdering Ord) const {
13776+
if (Subtarget.hasStdExtZtso()) {
13777+
if (isa<LoadInst>(Inst) && Ord == AtomicOrdering::SequentiallyConsistent)
13778+
return Builder.CreateFence(Ord);
13779+
return nullptr;
13780+
}
13781+
1376213782
if (isa<LoadInst>(Inst) && Ord == AtomicOrdering::SequentiallyConsistent)
1376313783
return Builder.CreateFence(Ord);
1376413784
if (isa<StoreInst>(Inst) && isReleaseOrStronger(Ord))
@@ -13769,6 +13789,9 @@ Instruction *RISCVTargetLowering::emitLeadingFence(IRBuilderBase &Builder,
1376913789
Instruction *RISCVTargetLowering::emitTrailingFence(IRBuilderBase &Builder,
1377013790
Instruction *Inst,
1377113791
AtomicOrdering Ord) const {
13792+
if (Subtarget.hasStdExtZtso())
13793+
return nullptr;
13794+
1377213795
if (isa<LoadInst>(Inst) && isAcquireOrStronger(Ord))
1377313796
return Builder.CreateFence(AtomicOrdering::Acquire);
1377413797
return nullptr;

llvm/test/CodeGen/RISCV/atomic-fence.ll

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,55 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
22
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3-
; RUN: | FileCheck %s
3+
; RUN: | FileCheck --check-prefixes=CHECK,WMO %s
44
; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
5-
; RUN: | FileCheck %s
5+
; RUN: | FileCheck --check-prefixes=CHECK,WMO %s
66
; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
7-
; RUN: | FileCheck %s
7+
; RUN: | FileCheck --check-prefixes=CHECK,TSO %s
88
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
9-
; RUN: | FileCheck %s
9+
; RUN: | FileCheck --check-prefixes=CHECK,WMO %s
1010
; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
11-
; RUN: | FileCheck %s
11+
; RUN: | FileCheck --check-prefixes=CHECK,WMO %s
1212
; RUN: llc -mtriple=riscv64 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
13-
; RUN: | FileCheck %s
13+
; RUN: | FileCheck --check-prefixes=CHECK,TSO %s
1414

1515
define void @fence_acquire() nounwind {
16-
; CHECK-LABEL: fence_acquire:
17-
; CHECK: # %bb.0:
18-
; CHECK-NEXT: fence r, rw
19-
; CHECK-NEXT: ret
16+
; WMO-LABEL: fence_acquire:
17+
; WMO: # %bb.0:
18+
; WMO-NEXT: fence r, rw
19+
; WMO-NEXT: ret
20+
;
21+
; TSO-LABEL: fence_acquire:
22+
; TSO: # %bb.0:
23+
; TSO-NEXT: #MEMBARRIER
24+
; TSO-NEXT: ret
2025
fence acquire
2126
ret void
2227
}
2328

2429
define void @fence_release() nounwind {
25-
; CHECK-LABEL: fence_release:
26-
; CHECK: # %bb.0:
27-
; CHECK-NEXT: fence rw, w
28-
; CHECK-NEXT: ret
30+
; WMO-LABEL: fence_release:
31+
; WMO: # %bb.0:
32+
; WMO-NEXT: fence rw, w
33+
; WMO-NEXT: ret
34+
;
35+
; TSO-LABEL: fence_release:
36+
; TSO: # %bb.0:
37+
; TSO-NEXT: #MEMBARRIER
38+
; TSO-NEXT: ret
2939
fence release
3040
ret void
3141
}
3242

3343
define void @fence_acq_rel() nounwind {
34-
; CHECK-LABEL: fence_acq_rel:
35-
; CHECK: # %bb.0:
36-
; CHECK-NEXT: fence.tso
37-
; CHECK-NEXT: ret
44+
; WMO-LABEL: fence_acq_rel:
45+
; WMO: # %bb.0:
46+
; WMO-NEXT: fence.tso
47+
; WMO-NEXT: ret
48+
;
49+
; TSO-LABEL: fence_acq_rel:
50+
; TSO: # %bb.0:
51+
; TSO-NEXT: #MEMBARRIER
52+
; TSO-NEXT: ret
3853
fence acq_rel
3954
ret void
4055
}

0 commit comments

Comments
 (0)