From 1714ccb73767e830bda454ea9e94e807f74d3f47 Mon Sep 17 00:00:00 2001 From: Liao Chunyu Date: Thu, 31 Jul 2025 21:25:21 -0400 Subject: [PATCH 1/2] [RISC-V]Implement -m{,no}fence-tso Some processors from T-Head don't implement the `fence.tso` instruction natively and instead trap to firmware. So just add an option to disable emitting it. The requirement comes from Debian, link: https://bugs.debian.org/cgi-bin/bugreport.cgi? --- clang/include/clang/Driver/Options.td | 7 +++++++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp | 7 +++++++ clang/test/Driver/riscv-features.c | 8 ++++++++ llvm/lib/Target/RISCV/RISCVFeatures.td | 3 +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 10 ++++++++++ llvm/test/CodeGen/RISCV/atomic-fence.ll | 20 ++++++++++++++++++++ llvm/test/CodeGen/RISCV/features-info.ll | 1 + 7 files changed, 56 insertions(+) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 3c04aeb5af59c..2ded1b9a4f51c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5120,6 +5120,13 @@ def msave_restore : Flag<["-"], "msave-restore">, Group, HelpText<"Enable using library calls for save and restore">; def mno_save_restore : Flag<["-"], "mno-save-restore">, Group, HelpText<"Disable using library calls for save and restore">; +def mfence_tso : Flag<["-"], "mfence-tso">, + Group, + HelpText<"Enable using fence-tso">; +def mno_fence_tso : Flag<["-"], "mno-fence-tso">, + Group, + HelpText<"Disable using fence-tso">; + } // let Flags = [TargetSpecific] let Flags = [TargetSpecific] in { def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group, diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index baa2c8c0bcfb2..6d63555f8e980 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -142,6 +142,13 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("-relax"); } + // -mfence-tso is default, unless -mno-fence-tso is specified. + if (Args.hasFlag(options::OPT_mfence_tso, options::OPT_mno_fence_tso, true)) { + Features.push_back("-no-fence-tso"); + } else { + Features.push_back("+no-fence-tso"); + } + // If -mstrict-align, -mno-strict-align, -mscalar-strict-align, or // -mno-scalar-strict-align is passed, use it. Otherwise, the // unaligned-scalar-mem is enabled if the CPU supports it or the target is diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index 80dec2c71f985..ef003fddb692b 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -29,6 +29,14 @@ // DEFAULT-NOT: "-target-feature" "-save-restore" // DEFAULT-NOT: "-target-feature" "+save-restore" +// RUN: %clang --target=riscv32-unknown-elf -### %s -mfence-tso 2>&1 | FileCheck %s -check-prefix=FENCE-TSO +// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-fence-tso 2>&1 | FileCheck %s -check-prefix=NO-FENCE-TSO + +// FENCE-TSO: "-target-feature" "-no-fence-tso" +// NO-FENCE-TSO: "-target-feature" "+no-fence-tso" +// DEFAULT: "-target-feature" "-no-fence-tso" +// DEFAULT-NOT: "-target-feature" "+no-fence-tso" + // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align 2>&1 | FileCheck %s -check-prefixes=FAST-SCALAR-UNALIGNED-ACCESS,FAST-VECTOR-UNALIGNED-ACCESS // RUN: %clang --target=riscv32-unknown-elf -### %s -mstrict-align 2>&1 | FileCheck %s -check-prefixes=NO-FAST-SCALAR-UNALIGNED-ACCESS,NO-FAST-VECTOR-UNALIGNED-ACCESS // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-scalar-strict-align 2>&1 | FileCheck %s -check-prefix=FAST-SCALAR-UNALIGNED-ACCESS diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 171940e149815..abcf6cd5f8699 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -1678,6 +1678,9 @@ foreach i = {1-31} in def FeatureSaveRestore : SubtargetFeature<"save-restore", "EnableSaveRestore", "true", "Enable save/restore.">; +def FeatureNoFenceTso : SubtargetFeature<"no-fence-tso", "EnableFenceTso", + "false", "Don't use fence.tso.">; + def FeatureNoTrailingSeqCstFence : SubtargetFeature<"no-trailing-seq-cst-fence", "EnableTrailingSeqCstFence", "false", diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index c0ada51ef4403..bdaa85ff4076e 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -6688,6 +6688,16 @@ static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, // MEMBARRIER is a compiler barrier; it codegens to a no-op. return DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0)); + if (!Subtarget.enableFenceTso() && + FenceOrdering == AtomicOrdering::AcquireRelease) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + SDValue Op1 = + DAG.getTargetConstant((unsigned)AtomicOrdering::SequentiallyConsistent, + dl, TLI.getFenceOperandTy(DAG.getDataLayout())); + return DAG.getNode(ISD::ATOMIC_FENCE, dl, MVT::Other, Op.getOperand(0), Op1, + Op.getOperand(2)); + } + return Op; } diff --git a/llvm/test/CodeGen/RISCV/atomic-fence.ll b/llvm/test/CodeGen/RISCV/atomic-fence.ll index 7103345ce7bc2..74312c6396105 100644 --- a/llvm/test/CodeGen/RISCV/atomic-fence.ll +++ b/llvm/test/CodeGen/RISCV/atomic-fence.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: | FileCheck --check-prefixes=CHECK,WMO %s +; RUN: llc -mtriple=riscv32 -mattr=+no-fence-tso -verify-machineinstrs < %s \ +; RUN: | FileCheck --check-prefixes=CHECK,NTSO %s ; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \ ; RUN: | FileCheck --check-prefixes=CHECK,WMO %s ; RUN: llc -mtriple=riscv32 -mattr=+a,+ztso -verify-machineinstrs < %s \ @@ -11,6 +13,9 @@ ; RUN: | FileCheck --check-prefixes=CHECK,WMO %s ; RUN: llc -mtriple=riscv64 -mattr=+a,+ztso -verify-machineinstrs < %s \ ; RUN: | FileCheck --check-prefixes=CHECK,TSO %s +; RUN: llc -mtriple=riscv64 -mattr=+no-fence-tso -verify-machineinstrs < %s \ +; RUN: | FileCheck --check-prefixes=CHECK,NTSO %s + define void @fence_acquire() nounwind { ; WMO-LABEL: fence_acquire: @@ -18,6 +23,11 @@ define void @fence_acquire() nounwind { ; WMO-NEXT: fence r, rw ; WMO-NEXT: ret ; +; NTSO-LABEL: fence_acquire: +; NTSO: # %bb.0: +; NTSO-NEXT: fence r, rw +; NTSO-NEXT: ret +; ; TSO-LABEL: fence_acquire: ; TSO: # %bb.0: ; TSO-NEXT: #MEMBARRIER @@ -32,6 +42,11 @@ define void @fence_release() nounwind { ; WMO-NEXT: fence rw, w ; WMO-NEXT: ret ; +; NTSO-LABEL: fence_release: +; NTSO: # %bb.0: +; NTSO-NEXT: fence rw, w +; NTSO-NEXT: ret +; ; TSO-LABEL: fence_release: ; TSO: # %bb.0: ; TSO-NEXT: #MEMBARRIER @@ -46,6 +61,11 @@ define void @fence_acq_rel() nounwind { ; WMO-NEXT: fence.tso ; WMO-NEXT: ret ; +; NTSO-LABEL: fence_acq_rel: +; NTSO: # %bb.0: +; NTSO-NEXT: fence rw, rw +; NTSO-NEXT: ret +; ; TSO-LABEL: fence_acq_rel: ; TSO: # %bb.0: ; TSO-NEXT: #MEMBARRIER diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll index b94665b718ae7..5d1be56382d46 100644 --- a/llvm/test/CodeGen/RISCV/features-info.ll +++ b/llvm/test/CodeGen/RISCV/features-info.ll @@ -61,6 +61,7 @@ ; CHECK-NEXT: m - 'M' (Integer Multiplication and Division). ; CHECK-NEXT: mips-p8700 - MIPS p8700 processor. ; CHECK-NEXT: no-default-unroll - Disable default unroll preference.. +; CHECK-NEXT: no-fence-tso - Don't use fence.tso.. ; CHECK-NEXT: no-sink-splat-operands - Disable sink splat operands to enable .vx, .vf,.wx, and .wf instructions. ; CHECK-NEXT: no-trailing-seq-cst-fence - Disable trailing fence for seq-cst store.. ; CHECK-NEXT: optimized-nf2-segment-load-store - vlseg2eN.v and vsseg2eN.v are implemented as a wide memory op and shuffle. From 3544707be65daf8669828a0403167d9baf4a8182 Mon Sep 17 00:00:00 2001 From: Liao Chunyu Date: Fri, 1 Aug 2025 04:16:48 -0400 Subject: [PATCH 2/2] making the default case command line shorter, not add -no-fence-tso --- clang/lib/Driver/ToolChains/Arch/RISCV.cpp | 5 +---- clang/test/Driver/riscv-features.c | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 6d63555f8e980..e7eb6eccc698d 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -143,11 +143,8 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, } // -mfence-tso is default, unless -mno-fence-tso is specified. - if (Args.hasFlag(options::OPT_mfence_tso, options::OPT_mno_fence_tso, true)) { - Features.push_back("-no-fence-tso"); - } else { + if (Args.hasFlag(options::OPT_mno_fence_tso, options::OPT_mfence_tso, false)) Features.push_back("+no-fence-tso"); - } // If -mstrict-align, -mno-strict-align, -mscalar-strict-align, or // -mno-scalar-strict-align is passed, use it. Otherwise, the diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index ef003fddb692b..b71736fa1464c 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -32,9 +32,9 @@ // RUN: %clang --target=riscv32-unknown-elf -### %s -mfence-tso 2>&1 | FileCheck %s -check-prefix=FENCE-TSO // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-fence-tso 2>&1 | FileCheck %s -check-prefix=NO-FENCE-TSO -// FENCE-TSO: "-target-feature" "-no-fence-tso" +// FENCE-TSO-NOT: "-target-feature" "-no-fence-tso" // NO-FENCE-TSO: "-target-feature" "+no-fence-tso" -// DEFAULT: "-target-feature" "-no-fence-tso" +// DEFAULT-NOT: "-target-feature" "-no-fence-tso" // DEFAULT-NOT: "-target-feature" "+no-fence-tso" // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align 2>&1 | FileCheck %s -check-prefixes=FAST-SCALAR-UNALIGNED-ACCESS,FAST-VECTOR-UNALIGNED-ACCESS