Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -157,6 +157,8 @@ if (Features[RISCV::FeatureStdExtC]) EFlags |= ELF::EF_RISCV_RVC; + if (Features(RISCV::FeatureStdExtZtso)) + EFlags |= ELF::EF_RISCV_TSO; switch (ABI) { case RISCVABI::ABI_ILP32: @@ -177,6 +179,7 @@ llvm_unreachable("Improperly initialised target ABI"); } + MCA.setELFHeaderEFlags(EFlags); } Index: llvm/lib/Target/RISCV/RISCV.td =================================================================== --- llvm/lib/Target/RISCV/RISCV.td +++ llvm/lib/Target/RISCV/RISCV.td @@ -454,6 +454,14 @@ AssemblerPredicate<(all_of FeatureStdExtZicbop), "'Zicbop' (Cache-Block Prefetch Instructions)">; +def FeatureStdExtZtso + : SubtargetFeature<"experimental-ztso", "HasStdExtZtso", "true", + "'Ztso' (Memory Model - Total Store Order)">; +def HasStdExtZtso : Predicate<"Subtarget->hasStdExtZTso()">, + AssemblerPredicate<(all_of FeatureStdExtZtso), + "'Ztso' (Memory Model - Total Store Order)">; + + // Feature32Bit exists to mark CPUs that support RV32 to distinquish them from // tuning CPU names. def Feature32Bit Index: llvm/lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- llvm/lib/Target/RISCV/RISCVSubtarget.h +++ llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -92,6 +92,7 @@ bool HasStdExtZicboz = false; bool HasStdExtZicbop = false; bool HasStdExtZmmul = false; + bool HasStdExtZtso = false; bool HasRV32 = false; bool HasRV64 = false; bool IsRV32E = false; @@ -192,6 +193,7 @@ bool hasStdExtZicboz() const { return HasStdExtZicboz; } bool hasStdExtZicbop() const { return HasStdExtZicbop; } bool hasStdExtZmmul() const { return HasStdExtZmmul; } + bool hasStdExtZtso() const { return HasStdExtZtso; } bool is64Bit() const { return HasRV64; } bool isRV32E() const { return IsRV32E; } bool enableLinkerRelax() const { return EnableLinkerRelax; } Index: llvm/test/MC/RISCV/Ztso.s =================================================================== --- /dev/null +++ llvm/test/MC/RISCV/Ztso.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-ztso -riscv-no-aliases 2>&1 | FileCheck %s +# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-ztso -riscv-no-aliases 2>&1 | FileCheck %s + +# Note: Ztso doesn't add or remove any instructions, so this is basically +# just checking that a) we accepted the attribute name, and b) codegen did +# not change. The ELF header flag is tested in elf-flags.s + +# CHECK-NOT: not a recognized feature + +# CHECK: fence iorw, iorw +fence iorw, iorw +# CHECK: fence.tso +fence.tso +# CHECK: fence.i +fence.i Index: llvm/test/MC/RISCV/elf-flags.s =================================================================== --- llvm/test/MC/RISCV/elf-flags.s +++ llvm/test/MC/RISCV/elf-flags.s @@ -5,6 +5,8 @@ # RUN: llvm-mc -triple=riscv32 -mattr=+e -filetype=obj < %s \ # RUN: | llvm-readobj --file-headers - \ # RUN: | FileCheck -check-prefix=CHECK-RVE %s +# RUN: llvm-mc -triple=riscv32 -mattr=+experimental-ztso -filetype=obj < %s | llvm-readobj --file-headers - | FileCheck -check-prefixes=CHECK-TSO %s +# RUN: llvm-mc -triple=riscv64 -mattr=+experimental-ztso -filetype=obj < %s | llvm-readobj --file-headers - | FileCheck -check-prefixes=CHECK-TSO %s # CHECK-RVI: Flags [ (0x0) # CHECK-RVI-NEXT: ] @@ -17,4 +19,8 @@ # CHECK-RVE-NEXT: EF_RISCV_RVE (0x8) # CHECK-RVE-NEXT: ] +# CHECK-TSO: Flags [ (0x10) +# CHECK-NEXT-TSO EF_RISCV_TSO (0x10) +# CHECK-NEXT-TSO ] + nop