Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISCV] Support RISCV Atomics ABI attributes #84597

Merged

Conversation

ilovepi
Copy link
Contributor

@ilovepi ilovepi commented Mar 9, 2024

This patch adds support for the atomic_abi attribute, specifid in
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#tag_riscv_atomic_abi-14-uleb128version.

The atomics_abi tag merging is conducted as follows:

  • UNKNOWN is safe to merge with all other values.
  • A6C is compatible with A6S, and results in the A6C ABI.
  • A6C is incompatible with A7, and results in an error.
  • A6S and A7 are compatible, and merging results in the A7 ABI.

Note: the A7 is not yet supported in either LLVM or in any current hardware,
and is therefore ommited from attribute generation in RISCVTargetStreamer.

Created using spr 1.3.4
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 9, 2024

@llvm/pr-subscribers-llvm-support
@llvm/pr-subscribers-lld
@llvm/pr-subscribers-backend-risc-v
@llvm/pr-subscribers-mc

@llvm/pr-subscribers-lld-elf

Author: Paul Kirth (ilovepi)

Changes

This patch adds support for the atomic_abi attribute, specifid in
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#tag_riscv_atomic_abi-14-uleb128version.

The atomics_abi tag merging is conducted as follows:

  • UNKNOWN is safe to merge with all other values.
  • A6C is compatible with A6S, and results in the A6C ABI.
  • A6C is incompatible with A7, and results in an error.
  • A6S and A7 are compatible, and merging results in the A7 ABI.

Note: the A7 is not yet supported in either LLVM or in any current hardware,
and is therefore ommited from attribute generation in RISCVTargetStreamer.

With the tag merging in place, we can safely change the default for
+seq-cst-trailing-fence to the default, according to the recommendation in
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-atomic.adoc


Patch is 20.19 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/84597.diff

13 Files Affected:

  • (modified) lld/ELF/Arch/RISCV.cpp (+90)
  • (modified) lld/test/ELF/riscv-attributes.s (+126)
  • (modified) llvm/include/llvm/Support/RISCVAttributeParser.h (+1)
  • (modified) llvm/include/llvm/Support/RISCVAttributes.h (+13)
  • (modified) llvm/lib/Support/RISCVAttributeParser.cpp (+17-1)
  • (modified) llvm/lib/Support/RISCVAttributes.cpp (+1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp (+7)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+3-3)
  • (modified) llvm/test/CodeGen/RISCV/atomic-load-store.ll (+8-8)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+9-1)
  • (modified) llvm/test/CodeGen/RISCV/forced-atomics.ll (+6-6)
  • (modified) llvm/test/MC/RISCV/attribute.s (+3)
  • (modified) llvm/test/MC/RISCV/invalid-attribute.s (+3)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 4798c86f7d1b61..e44583fb80fd31 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1084,10 +1084,88 @@ static void mergeArch(RISCVISAInfo::OrderedExtensionMap &mergedExts,
   }
 }
 
+static void mergeAtomic(DenseMap<unsigned, unsigned> &intAttr,
+                        const InputSectionBase *oldSection,
+                        const InputSectionBase *newSection,
+                        unsigned int oldTag,
+                        unsigned int newTag) {
+  using RISCVAttrs::RISCVAtomicAbiTag::AtomicABI;
+  llvm::errs() << "oldTag=" << oldTag << ", newTag=" << newTag <<"\n";
+  // Same tags stay the same, and UNKNOWN is compatible with anything
+  if (oldTag == newTag || newTag == AtomicABI::UNKNOWN)
+    return;
+
+  auto attr = RISCVAttrs::ATOMIC_ABI;
+  switch (oldTag) {
+  case AtomicABI::UNKNOWN:
+    intAttr[attr] = newTag;
+    return;
+  case AtomicABI::A6C:
+    switch (newTag) {
+    case AtomicABI::A6S:
+      intAttr[attr] = AtomicABI::A6C;
+      return;
+    case AtomicABI::A7:
+      errorOrWarn(toString(oldSection) + " has atomic_abi=" + Twine(oldTag) +
+                  " but " + toString(newSection) +
+                  " has atomic_abi=" + Twine(newTag));
+      return;
+    };
+
+  case AtomicABI::A6S:
+    switch (newTag) {
+    case AtomicABI::A6C:
+      intAttr[attr] = AtomicABI::A6C;
+      return;
+    case AtomicABI::A7:
+      intAttr[attr] = AtomicABI::A7;
+      return;
+    };
+
+  case AtomicABI::A7:
+    switch (newTag) {
+    case AtomicABI::A6S:
+      intAttr[attr] = AtomicABI::A7;
+      return;
+    case AtomicABI::A6C:
+      errorOrWarn(toString(oldSection) + " has atomic_abi=" + Twine(oldTag) +
+                  " but " + toString(newSection) +
+                  " has atomic_abi=" + Twine(newTag));
+      return;
+    };
+  default:
+    llvm_unreachable("unknown AtomicABI");
+  };
+}
+
+static void mergeX3RegUse(DenseMap<unsigned, unsigned> &intAttr,
+                        const InputSectionBase *oldSection,
+                        const InputSectionBase *newSection,
+                        unsigned int oldTag,
+                        unsigned int newTag) {
+  // X3/GP register usage ar incompatible and cannot be merged, with the
+  // exception of the UNKNOWN or 0 value
+  using RISCVAttrs::RISCVX3RegUse::X3RegUsage;
+  auto attr = RISCVAttrs::X3_REG_USAGE;
+  if (newTag == X3RegUsage::UNKNOWN)
+    return;
+  if (oldTag == X3RegUsage::UNKNOWN)
+    intAttr[attr] = newTag;
+  if (oldTag != newTag) {
+    errorOrWarn(toString(oldSection) + " has x3_reg_usage=" + Twine(oldTag) +
+                " but " + toString(newSection) +
+                " has x3_reg_usage=" + Twine(newTag));
+    return;
+  }
+  // TODO: do we need to check the tags are < 2047?
+}
+ 
 static RISCVAttributesSection *
 mergeAttributesSection(const SmallVector<InputSectionBase *, 0> &sections) {
   RISCVISAInfo::OrderedExtensionMap exts;
   const InputSectionBase *firstStackAlign = nullptr;
+  const InputSectionBase *firstAtomicAbi = nullptr;
+  const InputSectionBase *firstX3RegUse = nullptr;
   unsigned firstStackAlignValue = 0, xlen = 0;
   bool hasArch = false;
 
@@ -1134,6 +1212,18 @@ mergeAttributesSection(const SmallVector<InputSectionBase *, 0> &sections) {
       case RISCVAttrs::PRIV_SPEC_MINOR:
       case RISCVAttrs::PRIV_SPEC_REVISION:
         break;
+
+      case llvm::RISCVAttrs::AttrType::ATOMIC_ABI:
+        if (auto i = parser.getAttributeValue(tag.attr)) {
+          auto r = merged.intAttr.try_emplace(tag.attr, *i);
+          if (r.second) {
+            firstAtomicAbi = sec;
+          } else {
+            mergeAtomic(merged.intAttr, firstAtomicAbi, sec, r.first->getSecond(),  *i);
+            llvm::errs() << "Merged Attr = " <<merged.intAttr[tag.attr] << "\n";
+          }
+        }
+        continue;
       }
 
       // Fallback for deprecated priv_spec* and other unknown attributes: retain
diff --git a/lld/test/ELF/riscv-attributes.s b/lld/test/ELF/riscv-attributes.s
index d0ce0941269ec4..964fec43b52847 100644
--- a/lld/test/ELF/riscv-attributes.s
+++ b/lld/test/ELF/riscv-attributes.s
@@ -44,6 +44,30 @@
 # RUN: not ld.lld a.o b.o c.o diff_stack_align.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=STACK_ALIGN --implicit-check-not=error:
 # STACK_ALIGN: error: diff_stack_align.o:(.riscv.attributes) has stack_align=32 but a.o:(.riscv.attributes) has stack_align=16
 
+## merging atomic_abi values for A6C and A7 lead to an error.
+# RUN: llvm-mc -filetype=obj -triple=riscv64  atomic_abi_A6C.s -o atomic_abi_A6C.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64  atomic_abi_A7.s -o atomic_abi_A7.o
+# RUN: not ld.lld atomic_abi_A6C.o atomic_abi_A7.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ATOMIC_ABI_ERROR --implicit-check-not=error:
+# ATOMIC_ABI_ERROR: error: atomic_abi_A6C.o:(.riscv.attributes) has atomic_abi=1 but atomic_abi_A7.o:(.riscv.attributes) has atomic_abi=3
+
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64  atomic_abi_A6S.s -o atomic_abi_A6S.o
+# RUN: ld.lld atomic_abi_A6S.o atomic_abi_A6C.o -o atomic_abi_A6C_A6S
+# RUN: llvm-readobj -A atomic_abi_A6C_A6S | FileCheck %s --check-prefix=A6C_A6S
+
+# RUN: ld.lld atomic_abi_A6S.o atomic_abi_A7.o -o atomic_abi_A6S_A7
+# RUN: llvm-readobj -A atomic_abi_A6S_A7 | FileCheck %s --check-prefix=A6S_A7
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64  atomic_abi_unknown.s -o atomic_abi_unknown.o
+# RUN: ld.lld atomic_abi_unknown.o atomic_abi_A6C.o -o atomic_abi_A6C_unknown
+# RUN: llvm-readobj -A atomic_abi_A6C_unknown | FileCheck %s --check-prefixes=UNKNOWN_A6C
+
+# RUN: ld.lld atomic_abi_unknown.o atomic_abi_A6S.o -o atomic_abi_A6S_unknown
+# RUN: llvm-readobj -A atomic_abi_A6S_unknown | FileCheck %s --check-prefix=UNKNOWN_A6S
+
+# RUN: ld.lld atomic_abi_unknown.o atomic_abi_A7.o -o atomic_abi_A7_unknown
+# RUN: llvm-readobj -A atomic_abi_A7_unknown | FileCheck %s --check-prefix=UNKNOWN_A7
+
 ## The deprecated priv_spec is not handled as GNU ld does.
 ## Differing priv_spec attributes lead to an absent attribute.
 # RUN: llvm-mc -filetype=obj -triple=riscv64 diff_priv_spec.s -o diff_priv_spec.o
@@ -286,6 +310,108 @@
 .attribute priv_spec, 3
 .attribute priv_spec_minor, 3
 
+#--- atomic_abi_unknown.s
+.attribute atomic_abi, 0
+
+#--- atomic_abi_A6C.s
+.attribute atomic_abi, 1
+
+#--- atomic_abi_A6S.s
+.attribute atomic_abi, 2
+
+#--- atomic_abi_A7.s
+.attribute atomic_abi, 3
+
+# UNKNOWN_A6C: BuildAttributes {
+# UNKNOWN_A6C:   FormatVersion: 0x41
+# UNKNOWN_A6C:   Section 1 {
+# UNKNOWN_A6C:     SectionLength: 17
+# UNKNOWN_A6C:     Vendor: riscv
+# UNKNOWN_A6C:     Tag: Tag_File (0x1)
+# UNKNOWN_A6C:     Size: 7
+# UNKNOWN_A6C:     FileAttributes {
+# UNKNOWN_A6C:       Attribute {
+# UNKNOWN_A6C:         Tag: 14
+# UNKNOWN_A6C:         Value: 1
+# UNKNOWN_A6C:         TagName: atomic_abi
+# UNKNOWN_A6C:         Description: Atomic ABI is 1
+# UNKNOWN_A6C:       }
+# UNKNOWN_A6C:     }
+# UNKNOWN_A6C:   }
+# UNKNOWN_A6C: }
+
+# UNKNOWN_A6S: BuildAttributes {
+# UNKNOWN_A6S:   FormatVersion: 0x41
+# UNKNOWN_A6S:   Section 1 {
+# UNKNOWN_A6S:     SectionLength: 17
+# UNKNOWN_A6S:     Vendor: riscv
+# UNKNOWN_A6S:     Tag: Tag_File (0x1)
+# UNKNOWN_A6S:     Size: 7
+# UNKNOWN_A6S:     FileAttributes {
+# UNKNOWN_A6S:       Attribute {
+# UNKNOWN_A6S:         Tag: 14
+# UNKNOWN_A6S:         Value: 2
+# UNKNOWN_A6S:         TagName: atomic_abi
+# UNKNOWN_A6S:         Description: Atomic ABI is 2
+# UNKNOWN_A6S:       }
+# UNKNOWN_A6S:     }
+# UNKNOWN_A6S:   }
+# UNKNOWN_A6S: }
+
+# UNKNOWN_A7: BuildAttributes {
+# UNKNOWN_A7:   FormatVersion: 0x41
+# UNKNOWN_A7:   Section 1 {
+# UNKNOWN_A7:     SectionLength: 17
+# UNKNOWN_A7:     Vendor: riscv
+# UNKNOWN_A7:     Tag: Tag_File (0x1)
+# UNKNOWN_A7:     Size: 7
+# UNKNOWN_A7:     FileAttributes {
+# UNKNOWN_A7:       Attribute {
+# UNKNOWN_A7:         Tag: 14
+# UNKNOWN_A7:         Value: 3
+# UNKNOWN_A7:         TagName: atomic_abi
+# UNKNOWN_A7:         Description: Atomic ABI is 3
+# UNKNOWN_A7:       }
+# UNKNOWN_A7:     }
+# UNKNOWN_A7:   }
+# UNKNOWN_A7: }
+
+# A6C_A6S: BuildAttributes {
+# A6C_A6S:   FormatVersion: 0x41
+# A6C_A6S:   Section 1 {
+# A6C_A6S:     SectionLength: 17
+# A6C_A6S:     Vendor: riscv
+# A6C_A6S:     Tag: Tag_File (0x1)
+# A6C_A6S:     Size: 7
+# A6C_A6S:     FileAttributes {
+# A6C_A6S:       Attribute {
+# A6C_A6S:         Tag: 14
+# A6C_A6S:         Value: 1
+# A6C_A6S:         TagName: atomic_abi
+# A6C_A6S:         Description: Atomic ABI is 1
+# A6C_A6S:       }
+# A6C_A6S:     }
+# A6C_A6S:   }
+# A6C_A6S: }
+
+# A6S_A7: BuildAttributes {
+# A6S_A7:   FormatVersion: 0x41
+# A6S_A7:   Section 1 {
+# A6S_A7:     SectionLength: 17
+# A6S_A7:     Vendor: riscv
+# A6S_A7:     Tag: Tag_File (0x1)
+# A6S_A7:     Size: 7
+# A6S_A7:     FileAttributes {
+# A6S_A7:       Attribute {
+# A6S_A7:         Tag: 14
+# A6S_A7:         Value: 3
+# A6S_A7:         TagName: atomic_abi
+# A6S_A7:         Description: Atomic ABI is 3
+# A6S_A7:       }
+# A6S_A7:     }
+# A6S_A7:   }
+# A6S_A7: }
+
 #--- unknown13.s
 .attribute 13, "0"
 #--- unknown13a.s
diff --git a/llvm/include/llvm/Support/RISCVAttributeParser.h b/llvm/include/llvm/Support/RISCVAttributeParser.h
index 305adffbe851e7..9f295504de959e 100644
--- a/llvm/include/llvm/Support/RISCVAttributeParser.h
+++ b/llvm/include/llvm/Support/RISCVAttributeParser.h
@@ -24,6 +24,7 @@ class RISCVAttributeParser : public ELFAttributeParser {
 
   Error unalignedAccess(unsigned tag);
   Error stackAlign(unsigned tag);
+  Error atomicAbi(unsigned tag);
 
 public:
   RISCVAttributeParser(ScopedPrinter *sw)
diff --git a/llvm/include/llvm/Support/RISCVAttributes.h b/llvm/include/llvm/Support/RISCVAttributes.h
index 18f5a84d21f250..5def890a727355 100644
--- a/llvm/include/llvm/Support/RISCVAttributes.h
+++ b/llvm/include/llvm/Support/RISCVAttributes.h
@@ -32,8 +32,21 @@ enum AttrType : unsigned {
   PRIV_SPEC = 8,
   PRIV_SPEC_MINOR = 10,
   PRIV_SPEC_REVISION = 12,
+  ATOMIC_ABI = 14,
 };
 
+namespace RISCVAtomicAbiTag {
+enum AtomicABI : unsigned {
+  // Values for Tag_RISCV_atomic_abi
+  // Defined at
+  // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#tag_riscv_atomic_abi-14-uleb128version
+  UNKNOWN = 0,
+  A6C = 1,
+  A6S = 2,
+  A7 = 3,
+};
+} // namespace RISCVAtomicAbiTag
+
 enum { NOT_ALLOWED = 0, ALLOWED = 1 };
 
 } // namespace RISCVAttrs
diff --git a/llvm/lib/Support/RISCVAttributeParser.cpp b/llvm/lib/Support/RISCVAttributeParser.cpp
index 7ce4b6ab161cd3..b9515134181edb 100644
--- a/llvm/lib/Support/RISCVAttributeParser.cpp
+++ b/llvm/lib/Support/RISCVAttributeParser.cpp
@@ -36,7 +36,23 @@ const RISCVAttributeParser::DisplayHandler
         {
             RISCVAttrs::UNALIGNED_ACCESS,
             &RISCVAttributeParser::unalignedAccess,
-        }};
+        },
+        {
+            RISCVAttrs::ATOMIC_ABI,
+            &RISCVAttributeParser::atomicAbi,
+        },
+        {
+            RISCVAttrs::X3_REG_USAGE,
+            &RISCVAttributeParser::x3RegUsage,
+        },
+};
+
+Error RISCVAttributeParser::atomicAbi(unsigned Tag) {
+  uint64_t Value = de.getULEB128(cursor);
+  std::string Description = "Atomic ABI is " + utostr(Value);
+  printAttribute(Tag, Value, Description);
+  return Error::success();
+}
 
 Error RISCVAttributeParser::unalignedAccess(unsigned tag) {
   static const char *strings[] = {"No unaligned access", "Unaligned access"};
diff --git a/llvm/lib/Support/RISCVAttributes.cpp b/llvm/lib/Support/RISCVAttributes.cpp
index 9e629760d3d842..dc70d65acba063 100644
--- a/llvm/lib/Support/RISCVAttributes.cpp
+++ b/llvm/lib/Support/RISCVAttributes.cpp
@@ -18,6 +18,7 @@ static constexpr TagNameItem tagData[] = {
     {PRIV_SPEC, "Tag_priv_spec"},
     {PRIV_SPEC_MINOR, "Tag_priv_spec_minor"},
     {PRIV_SPEC_REVISION, "Tag_priv_spec_revision"},
+    {ATOMIC_ABI, "Tag_atomic_abi"},
 };
 
 constexpr TagNameMap RISCVAttributeTags{tagData};
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
index 4a4b1e13c2b9ec..3f4d6921841a27 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
@@ -75,6 +75,13 @@ void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI,
     auto &ISAInfo = *ParseResult;
     emitTextAttribute(RISCVAttrs::ARCH, ISAInfo->toString());
   }
+
+  if (STI.hasFeature(RISCV::FeatureStdExtA)) {
+    unsigned AtomicABITag = STI.hasFeature(RISCV::FeatureTrailingSeqCstFence)
+                             ? RISCVAttrs::RISCVAtomicAbiTag::AtomicABI::A6S
+                             : RISCVAttrs::RISCVAtomicAbiTag::AtomicABI::A6C;
+    emitAttribute(RISCVAttrs::ATOMIC_ABI, AtomicABITag);
+  }
 }
 
 // This part is for ascii assembly output
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 83619ccb24baa3..e3ce527b84a985 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1154,10 +1154,10 @@ foreach i = {1-31} in
 def FeatureSaveRestore : SubtargetFeature<"save-restore", "EnableSaveRestore",
                                           "true", "Enable save/restore.">;
 
-def FeatureTrailingSeqCstFence : SubtargetFeature<"seq-cst-trailing-fence",
+def FeatureTrailingSeqCstFence : SubtargetFeature<"no-seq-cst-trailing-fence",
                                           "EnableSeqCstTrailingFence",
-                                          "true",
-                                          "Enable trailing fence for seq-cst store.">;
+                                          "false",
+                                          "Disable trailing fence for seq-cst store.">;
 
 def FeatureFastUnalignedAccess
    : SubtargetFeature<"fast-unaligned-access", "HasFastUnalignedAccess",
diff --git a/llvm/test/CodeGen/RISCV/atomic-load-store.ll b/llvm/test/CodeGen/RISCV/atomic-load-store.ll
index 2d1fc21cda89b0..30680957ecbc6b 100644
--- a/llvm/test/CodeGen/RISCV/atomic-load-store.ll
+++ b/llvm/test/CodeGen/RISCV/atomic-load-store.ll
@@ -1,26 +1,26 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV32I %s
-; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv32 -mattr=+a,+no-seq-cst-trailing-fence -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-WMO %s
-; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv32 -mattr=+a,+no-seq-cst-trailing-fence,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-TSO %s
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I %s
-; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv64 -mattr=+a,+no-seq-cst-trailing-fence -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-WMO %s
-; RUN: llc -mtriple=riscv64 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv64 -mattr=+a,+no-seq-cst-trailing-fence,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-TSO %s
 
 
-; RUN: llc -mtriple=riscv32 -mattr=+a,+seq-cst-trailing-fence -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-WMO-TRAILING-FENCE %s
-; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-ztso,+seq-cst-trailing-fence -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv32 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32IA,RV32IA-TSO-TRAILING-FENCE %s
 
-; RUN: llc -mtriple=riscv64 -mattr=+a,+seq-cst-trailing-fence -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-WMO-TRAILING-FENCE %s
-; RUN: llc -mtriple=riscv64 -mattr=+a,+experimental-ztso,+seq-cst-trailing-fence -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv64 -mattr=+a,+experimental-ztso -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64IA,RV64IA-TSO-TRAILING-FENCE %s
 
 
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index cc332df271043f..95bce2ae8a071a 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -128,7 +128,8 @@
 ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefixes=CHECK,RV64M %s
 ; RUN: llc -mtriple=riscv64 -mattr=+zmmul %s -o - | FileCheck --check-prefixes=CHECK,RV64ZMMUL %s
 ; RUN: llc -mtriple=riscv64 -mattr=+m,+zmmul %s -o - | FileCheck --check-prefixes=CHECK,RV64MZMMUL %s
-; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefixes=CHECK,RV64A %s
+; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefixes=CHECK,RV64A,A6C %s
+; RUN: llc -mtriple=riscv64 -mattr=+a,+no-seq-cst-trailing-fence %s -o - | FileCheck --check-prefixes=CHECK,RV64A,A6S %s
 ; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefixes=CHECK,RV64F %s
 ; RUN: llc -mtriple=riscv64 -mattr=+d %s -o - | FileCheck --check-prefixes=CHECK,RV64D %s
 ; RUN: llc -mtriple=riscv64 -mattr=+c %s -o - | FileCheck --check-prefixes=CHECK,RV64C %s
@@ -512,3 +513,10 @@ define i32 @addi(i32 %a) {
   %1 = add i32 %a, 1
   ret i32 %1
 }
+
+define i8 @atomic_load_i8_seq_cst(ptr %a) nounwind {
+  %1 = load atomic i8, ptr %a seq_cst, align 1
+  ret i8 %1
+; A6S: .attribute 14, 2
+; A6C: .attribute 14, 1
+}
diff --git a/llvm/test/CodeGen/RISCV/forced-atomics.ll b/llvm/test/CodeGen/RISCV/forced-atomics.ll
index f6a53a9d76dd35..96d3eede524510 100644
--- a/llvm/test/CodeGen/RISCV/forced-atomics.ll
+++ b/llvm/test/CodeGen/RISCV/forced-atomics.ll
@@ -1,12 +1,12 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=riscv32 -mattr=+seq-cst-trailing-fence < %s | FileCheck %s --check-prefixes=RV32,RV32-NO-ATOMIC
+; RUN: llc -mtriple=riscv32 -mattr=+no-seq-cst-trailing-fence < %s | FileCheck %s --check-prefixes=RV32,RV32-NO-ATOMIC
 ; RUN: llc -mtriple=riscv32 < %s | FileCheck %s --check-prefixes=RV32,RV32-NO-ATOMIC
-; RUN: llc -mtriple=riscv32 -mattr=+forced-atomics < %s | FileCheck %s --check-prefixes=RV32,RV32-ATOMIC
-; RUN: llc -mtriple=riscv32 -mattr=+forced-atomics,+seq-cst-trailing-fence < %s | FileCheck %s --check-prefixes=RV32,RV32-ATOMIC-TRAILING
+; RUN: llc -mtriple=riscv32 -mattr=+forced-atomics,+no-seq-cst-trailing-fence < %s | FileCheck %s --check-prefixes=RV32,RV32-ATOMIC
+; RUN: llc -mtriple=riscv32 -mattr=+forced-atomics < %s | FileCheck %s --check-prefixes=RV32,RV32-ATOMIC-TRAILING
 ; RUN: llc -mtriple=riscv64 < %s | FileCheck %s --check-prefixes=RV64,RV64-NO-ATOMIC
-; RUN: llc -mtriple=riscv64 -mattr=+seq-cst-trailing-fence < %s | FileCheck %s --check-prefixes=RV64,RV64-NO-ATOMIC
-; RUN: llc -mtriple=riscv64 -mattr=+forced-atomics < %s | FileCheck %s --check-prefixes=RV64,RV64-ATOMIC
-; RUN: llc -mtriple=riscv64 -mattr=+forced-atomics,+seq-cst-trailing-fence < %s | FileCheck %s --check-prefixes=RV64,RV64-ATOMIC-TRAILING
+; RUN: llc -mtriple=riscv64 -mattr=+no-seq-cst-trailing-fence < %s | FileCheck %s --check-prefixes=RV64,RV64-NO-ATOMIC
+; RUN: llc -mtriple=riscv64 -mattr=+forced-atomics,+no-seq-cst-trailing-fence < %s | FileCheck %s --check-prefixes=RV64,RV64-ATOMIC
+; RUN: llc -mtriple=riscv64 -mattr=+forced-atomics < %s | FileCheck %s --check-prefixes=RV64,RV64-ATOMIC-TRAILING
 
 define i8 @load8(ptr %p) nounwind {
 ; RV32-NO-ATOMIC-LABEL: load8:
diff --git a/llvm/test/MC/RISCV/attribute.s b/llvm/test/MC/RISCV/attribute.s
index 56f0cb1daf176f..0a9d86da55261c 100644
--- a/llvm/test/MC/RISCV/attribute.s
+++ b/llvm/test/MC/RISCV/attribute.s
@@ -24,3 +24,6 @@
 
 .attribute priv_spec_revision, 0
 # CHECK: attribute      12, 0
+.attribute atomic_abi, 0
+# CHECK: attribute      14, 0
+
diff --git a/llvm/test/MC/RISCV/invalid-attribute.s b/llvm/test/MC/RISCV/invalid-attribute.s
index 1d732af83cda35..2ebf7ddc9aff85 100644
--- a/llvm/test/MC/RISCV/invalid-attribute.s
+++ b/llvm/test/MC/RISCV/invalid-attribute...
[truncated]

Copy link

github-actions bot commented Mar 9, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Created using spr 1.3.4
@ilovepi ilovepi requested a review from jrtc27 March 9, 2024 07:12
const InputSectionBase *newSection, unsigned int oldTag,
unsigned int newTag) {
using RISCVAttrs::RISCVAtomicAbiTag::AtomicABI;
llvm::errs() << "oldTag=" << oldTag << ", newTag=" << newTag << "\n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover debug print?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I missed that. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

lld/ELF/Arch/RISCV.cpp Outdated Show resolved Hide resolved
Created using spr 1.3.4
Created using spr 1.3.4
Created using spr 1.3.4
auto attr = RISCVAttrs::ATOMIC_ABI;
switch (oldTag) {
case AtomicABI::UNKNOWN:
intAttr[attr] = newTag;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the original iterator returned by try_emplace to avoid the second map lookup here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

Created using spr 1.3.4
Created using spr 1.3.4
@ilovepi
Copy link
Contributor Author

ilovepi commented Mar 19, 2024

@jrtc27 Do you have thoughts on this change w.r.t. the defaults? I recall you had expressed concerns previously in the psABI, so I want to be sure we're changing the status quo appropriately.

@jrtc27
Copy link
Collaborator

jrtc27 commented Mar 19, 2024

@jrtc27 Do you have thoughts on this change w.r.t. the defaults? I recall you had expressed concerns previously in the psABI, so I want to be sure we're changing the status quo appropriately.

To be clear, without reading the patch in detail, this is making the default be A6S? I don't think I have concerns with that other than to note that transitioning from A6S to A7 will be an ABI break for existing binaries (predating the use of A6S), so the timeline for when that's ok to do is unclear.

Created using spr 1.3.4
@ilovepi
Copy link
Contributor Author

ilovepi commented Mar 29, 2024

ping. I think everything has been addressed.

@asb
Copy link
Contributor

asb commented Apr 2, 2024

Thanks for splitting out that change. I'm thinking you might be missing a test case in lld/test/ELF/riscv-attributes.s. You handle an input file where the atomic_abi attribute is present and explicitly set to UNKNOWN. But what about when merging a file where the attribute was explicitly set, with one where the attribute wasn't present at all?

@ilovepi
Copy link
Contributor Author

ilovepi commented Apr 2, 2024

Thanks for splitting out that change. I'm thinking you might be missing a test case in lld/test/ELF/riscv-attributes.s. You handle an input file where the atomic_abi attribute is present and explicitly set to UNKNOWN. But what about when merging a file where the attribute was explicitly set, with one where the attribute wasn't present at all?

Oh, that's a good catch. I didn't think about that case. Let me see what happens.

Created using spr 1.3.4
Copy link
Contributor

@asb asb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question in line about the observed output when combining a file without the ABI attribute with one that has it set to 'unknown', and two minor nits. If we resolve that question, it all looks good to me - thanks for your patience!

@@ -62,12 +62,21 @@
# RUN: ld.lld atomic_abi_unknown.o atomic_abi_A6C.o -o atomic_abi_A6C_unknown
# RUN: llvm-readobj -A atomic_abi_A6C_unknown | FileCheck %s --check-prefixes=UNKNOWN_A6C

# RUN: ld.lld atomic_abi_unknown.o diff_stack_align.o -o atomic_abi_none_unknown
# RUN: llvm-readobj -A atomic_abi_none_unknown | FileCheck %s --check-prefixes=UNKNOWN_UNKNOWN
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the check-prefix for this be NONE_UNKNOWN to match the convention elsewhere?

# RUN: ld.lld atomic_abi_unknown.o diff_stack_align.o -o atomic_abi_none_unknown
# RUN: llvm-readobj -A atomic_abi_none_unknown | FileCheck %s --check-prefixes=UNKNOWN_UNKNOWN

# RUN: ld.lld diff_stack_align.o atomic_abi_A6C.o -o atomic_abi_A6C_unknown
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the output filename be atomic_abi_A6C_none?

@@ -322,6 +331,49 @@
#--- atomic_abi_A7.s
.attribute atomic_abi, 3


# UNKNOWN_UNKNOWN: BuildAttributes {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My other two comments were minor nits, this is the one where I'm wondering if there's some missing logic.

For every other case where one of the input files has the atomic_abi attribute and we produce an output, the output file also has the attribute. In this case, although one of the inputs had the attribute we end up dropping it in the output. I think that's probably not desired, but maybe I'm missing a reason to do this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, we probably need to double check w/ @MaskRay, but I believe we don't emit attributes w/ 0 value in general. I think the following snippet seems to indicate that from a few lines below the call to mergeAtomics. I assume that is because the default value of 0 is pretty much 'not used', so it isn't emitted normally, and since UNKOWN is 0, it just falls into that case.

size_t size = 5 + merged.vendor.size() + 1 + 5;
  for (auto &attr : merged.intAttr)
    if (attr.second != 0)
      size += getULEB128Size(attr.first) + getULEB128Size(attr.second);

I'll update the patch to address the nits, but I'll try to wait for Fangrui to confirm if thats correct about 0 valued attributes before proceeding.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason it might be helpful to differentiate between the attribute being present but UNKNOWN and the attribute not being present at all, is that if the attribute is there (and emitted when merging UNKNOWN with NONE) you at least know it's been processed by tools that were aware of the attribute. Is that useful? Not sure. It's probably not hugely important either way, but thought I'd check if this was by design or not.

Created using spr 1.3.4
Created using spr 1.3.4
@ilovepi
Copy link
Contributor Author

ilovepi commented Apr 22, 2024

@MaskRay @asb Are we happy w/ this patch? I think I've addressed most of the concerns raised thus far, but I want try and finish the attributes patches this week if possible, since I'm back from EuroLLVM + vacation.

Copy link
Contributor

@asb asb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@ilovepi ilovepi merged commit 9221f3a into main Apr 25, 2024
4 checks passed
@ilovepi ilovepi deleted the users/ilovepi/spr/riscv-support-riscv-atomics-abi-attributes branch April 25, 2024 23:20
@lukel97
Copy link
Contributor

lukel97 commented Apr 26, 2024

Hi, I'm seeing a segfault with GNU ld after this when running clang on a simple C example with -march=rv64g and riscv64-linux-gnu-ld 2.42.

#include <stdio.h>
int main() {
  puts("hello");
}

With LLD 18.1.3 I get a warning:

ld.lld: warning: /var/folders/yl/qbdtspsx7t97vqcl6dm6q9540000gn/T/--4b08f5.o:(.riscv.attributes): invalid tag 0xe at offset 0x45

I haven't tried it with a ToT lld yet but I thought I'd flag this in case something was accidentally made backwards incompatible!

asb added a commit that referenced this pull request Apr 26, 2024
…fault (#87376)"

This reverts commit 733b271.

Reverting in order to revert the companion patch adding the atomics ABI
ELF attributes due to the reported incompatibility with GNU ld.
#84597 (comment)
asb added a commit that referenced this pull request Apr 26, 2024
This reverts commit 9221f3a.

As reported
<#84597 (comment)>
and confirmed by me locally, adding these attributes causes current GNU
ld to segfault when processing the input. Reverted so we can discuss
the best next step.
@asb
Copy link
Contributor

asb commented Apr 26, 2024

Thanks Luke. I can reproduce locally (with GNU ld 2.42) so have gone ahead and reverted so we can decide what to do without breaking people's workflows in the meantime.

CC @kito-cheng

It seems like there are two problems here, the first obviously by far the biggest:

  • There seems to be a bug in GNU ld's elf attribute handling code that causes it to segfault when seeing an unrecognized attribute.
  • Arguably warning whenever an unrecognized tag is encountered (as ld.lld does, via ELFAttributeParser::parseAttributeList) is overly verbose.

@ilovepi
Copy link
Contributor Author

ilovepi commented Apr 26, 2024

@lukel97 Thanks for the report and @asb thanks for the reverts.

It does look like we’ll need to wait for bfd to catch up or at least not crash.

it->getSecond() = AtomicABI::A6C;
return;
case AtomicABI::A7:
error(toString(oldSection) + " has atomic_abi=" + Twine(oldTag) +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use errorOrWarn.

Sorry that I did not follow up the discussion in time, but I'd appreciate that I had the opportunity to give this comment after the patch was approved by @asb ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted. I'll follow up in #90266. I based this on your comment to a similar line in #84598 (comment), but it seems like I misunderstood?

# RUN: llvm-mc -filetype=obj -triple=riscv64 atomic_abi_A7.s -o atomic_abi_A7.o
# RUN: not ld.lld atomic_abi_A6C.o atomic_abi_A7.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ATOMIC_ABI_ERROR --implicit-check-not=error:
# ATOMIC_ABI_ERROR: error: atomic_abi_A6C.o:(.riscv.attributes) has atomic_abi=1 but atomic_abi_A7.o:(.riscv.attributes) has atomic_abi=3

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use double blank lines

# ATOMIC_ABI_ERROR: error: atomic_abi_A6C.o:(.riscv.attributes) has atomic_abi=1 but atomic_abi_A7.o:(.riscv.attributes) has atomic_abi=3


# RUN: llvm-mc -filetype=obj -triple=riscv64 atomic_abi_A6S.s -o atomic_abi_A6S.o
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excess space

@@ -44,6 +44,39 @@
# RUN: not ld.lld a.o b.o c.o diff_stack_align.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=STACK_ALIGN --implicit-check-not=error:
# STACK_ALIGN: error: diff_stack_align.o:(.riscv.attributes) has stack_align=32 but a.o:(.riscv.attributes) has stack_align=16

## merging atomic_abi values for A6C and A7 lead to an error.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mismatched

Upper case. And there is a better word than "merging"

@MaskRay
Copy link
Member

MaskRay commented Apr 29, 2024

@MaskRay @asb Are we happy w/ this patch? I think I've addressed most of the concerns raised thus far, but I want try and finish the attributes patches this week if possible, since I'm back from EuroLLVM + vacation.

I am sorry it took a long time for me to notice the discussion and make some comments about the linker code.
While I appreciate the LGTM, given the number of linker comments I had to give, landing this 7 hours after LGTM feels a bit rushed.
(If asb's LGTM was given on the day you commented, I'd certainly not oppose as it was my fault not noticing the change in 3 days.)

@ilovepi
Copy link
Contributor Author

ilovepi commented Apr 29, 2024

@MaskRay @asb Are we happy w/ this patch? I think I've addressed most of the concerns raised thus far, but I want try and finish the attributes patches this week if possible, since I'm back from EuroLLVM + vacation.

I am sorry it took a long time for me to notice the discussion and make some comments about the linker code. While I appreciate the LGTM, given the number of linker comments I had to give, landing this 7 hours after LGTM feels a bit rushed.

Apologies. That wasn't my intent. I'll be sure to allow some more time in the future.

@asb
Copy link
Contributor

asb commented May 9, 2024

@MaskRay @asb Are we happy w/ this patch? I think I've addressed most of the concerns raised thus far, but I want try and finish the attributes patches this week if possible, since I'm back from EuroLLVM + vacation.

I am sorry it took a long time for me to notice the discussion and make some comments about the linker code. While I appreciate the LGTM, given the number of linker comments I had to give, landing this 7 hours after LGTM feels a bit rushed. (If asb's LGTM was given on the day you commented, I'd certainly not oppose as it was my fault not noticing the change in 3 days.)

Sorry for that @MaskRay. I should have given an LGTM conditional on you or another lld dev explicitly lgtming the linker code. I think given jrtc27 had been involved in the thread and a discussion thread with you was mentioned I'd misjudged the level of attention this had got already from lld folks - so my bad.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants