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..e7eb6eccc698d 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -142,6 +142,10 @@ 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_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 // 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..b71736fa1464c 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-NOT: "-target-feature" "-no-fence-tso" +// NO-FENCE-TSO: "-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 // 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.