https://github.com/arichardson updated 
https://github.com/llvm/llvm-project/pull/227865

>From 47c03528cd0595bc454c6a183604968f228f6ea9 Mon Sep 17 00:00:00 2001
From: Alex Richardson <[email protected]>
Date: Tue, 20 Oct 2026 10:24:07 -0700
Subject: [PATCH] [nspr] initial commit

---
 .../Driver/print-supported-extensions-riscv.c |  2 +-
 lld/test/ELF/riscv-attributes.s               |  4 +-
 llvm/lib/Support/RISCVISAUtils.cpp            |  6 +-
 llvm/lib/TargetParser/RISCVISAInfo.cpp        | 38 ++++----
 llvm/test/CodeGen/RISCV/attributes.ll         |  2 +-
 llvm/test/MC/RISCV/rvy-build-attributes.s     | 37 +++++---
 .../ELF/RISCV/unknown-arch-attr.test          |  6 +-
 .../TargetParser/RISCVISAInfoTest.cpp         | 95 ++++++++++++++++---
 8 files changed, 135 insertions(+), 55 deletions(-)

diff --git a/clang/test/Driver/print-supported-extensions-riscv.c 
b/clang/test/Driver/print-supported-extensions-riscv.c
index f916bef0a6519a..1d1714314d6e26 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -247,8 +247,8 @@
 // CHECK-NEXT:     xwchc                2.2       'Xwchc' (WCH/QingKe 
additional compressed opcodes)
 // CHECK-EMPTY:
 // CHECK-NEXT: Experimental extensions
-// CHECK-NEXT:     p                    0.21      'P' ('Base P' (Packed SIMD))
 // CHECK-NEXT:     y                    0.910     'Y' ('Base Y' (CHERI))
+// CHECK-NEXT:     p                    0.21      'P' ('Base P' (Packed SIMD))
 // CHECK-NEXT:     zibi                 0.1       'Zibi' (Branch with 
Immediate)
 // CHECK-NEXT:     zicfilp              1.0       'Zicfilp' (Landing pad)
 // CHECK-NEXT:     zilx                 0.1       'Zilx' (Indexed Integer Load 
Instructions)
diff --git a/lld/test/ELF/riscv-attributes.s b/lld/test/ELF/riscv-attributes.s
index c6666063396d46..02a83dc9afd743 100644
--- a/lld/test/ELF/riscv-attributes.s
+++ b/lld/test/ELF/riscv-attributes.s
@@ -220,7 +220,7 @@
 # UNRECOGNIZED_EXT1-NEXT:       Attribute {
 # UNRECOGNIZED_EXT1-NEXT:         Tag: 5
 # UNRECOGNIZED_EXT1-NEXT:         TagName: arch
-# UNRECOGNIZED_EXT1-NEXT:         Value: rv64i2p1_y2p0{{$}}
+# UNRECOGNIZED_EXT1-NEXT:         Value: rv64i2p1_w2p0{{$}}
 # UNRECOGNIZED_EXT1-NEXT:       }
 # UNRECOGNIZED_EXT1-NEXT:     }
 # UNRECOGNIZED_EXT1-NEXT:   }
@@ -233,7 +233,7 @@
 .byte 1  # Tag_File
 .long .Lend-.Lbegin
 .byte 5  # Tag_RISCV_arch
-.asciz "rv64i2p1_y2p0"
+.asciz "rv64i2p1_w2p0"
 .Lend:
 
 #--- unrecognized_ext2.s
diff --git a/llvm/lib/Support/RISCVISAUtils.cpp 
b/llvm/lib/Support/RISCVISAUtils.cpp
index d6b002e66e7ab2..2166d2f30bbb96 100644
--- a/llvm/lib/Support/RISCVISAUtils.cpp
+++ b/llvm/lib/Support/RISCVISAUtils.cpp
@@ -44,15 +44,17 @@ static unsigned singleLetterExtensionRank(char Ext) {
     return 0;
   case 'e':
     return 1;
+  case 'y':
+    return 2;
   }
 
   size_t Pos = RISCVISAUtils::AllStdExts.find(Ext);
   if (Pos != StringRef::npos)
-    return Pos + 2; // Skip 'e' and 'i' from above.
+    return Pos + 3; // Skip 'e', 'i', and 'y' from above.
 
   // If we got an unknown extension letter, then give it an alphabetical
   // order, but after all known standard extensions.
-  return 2 + RISCVISAUtils::AllStdExts.size() + (Ext - 'a');
+  return 3 + RISCVISAUtils::AllStdExts.size() + (Ext - 'a');
 }
 
 // Get the rank for multi-letter extension, lower value meaning higher
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp 
b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index a8f4d3469ef20c..ca2e269386be71 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -12,6 +12,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 
 #include <atomic>
@@ -483,7 +484,7 @@ RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
   else if (Arch.consume_front("rv64"))
     XLen = 64;
 
-  auto IsBaseISA = [](char C) { return C == 'i' || C == 'e'; };
+  auto IsBaseISA = [](char C) { return C == 'i' || C == 'e' || C == 'y'; };
   if (XLen == 0 || Arch.empty() || !IsBaseISA(Arch[0]))
     return getError("arch string must begin with valid base ISA");
   char BaseISA = Arch[0];
@@ -556,6 +557,10 @@ RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
              .second)
       return getError("duplicate extension '" + ExtName + "'");
   }
+  // Plain 'y' always implies 'i' (which is omitted in the normalized arch
+  // string). Y+E requires a long base name arch string.
+  if (BaseISA == "y")
+    ISAInfo->Exts["i"] = *findDefaultVersion("i");
   ISAInfo->updateImpliedLengths();
   return std::move(ISAInfo);
 }
@@ -628,7 +633,11 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool 
EnableExperimentalExtension,
                     "\' should be 'e', 'i', 'g' or 'y'");
   case 'e':
   case 'i':
-    // Baseline is `i` or `e`
+  case 'y':
+    // Baseline is 'i', 'e', or 'y' (which implies 'i' in updateImplication).
+    // TODO: arch string syntax for RVE+RVY (and y in non-first position) will
+    // be included following conclusion of "long base name" syntax
+    // https://lists.riscv.org/g/tech-unprivileged/message/1134
     if (auto E = getExtensionVersion(
             StringRef(&Baseline, 1), Arch, Major, Minor, ConsumeLength,
             EnableExperimentalExtension, ExperimentalExtensionVersionCheck))
@@ -636,22 +645,6 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool 
EnableExperimentalExtension,
 
     ISAInfo->Exts[std::string(1, Baseline)] = {Major, Minor};
     break;
-  case 'y': {
-    // If the first character is 'y', this is equivalent to "iy".
-    // TODO: arch string syntax for RVE+RVY (and y in non-first position) will
-    // be included following conclusion of "long base name" syntax
-    // https://lists.riscv.org/g/tech-unprivileged/message/1134
-    if (auto E = getExtensionVersion("y", Arch, Major, Minor, ConsumeLength,
-                                     EnableExperimentalExtension,
-                                     ExperimentalExtensionVersionCheck))
-      return std::move(E);
-
-    ISAInfo->Exts["y"] = {Major, Minor};
-    auto IVersion = findDefaultVersion("i");
-    assert(IVersion && "Default 'i' extension version not found?");
-    ISAInfo->Exts["i"] = {IVersion->Major, IVersion->Minor};
-    break;
-  }
   case 'g':
     // g expands to extensions in RISCVGImplications.
     if (!Arch.empty() && isDigit(Arch.front()))
@@ -1075,9 +1068,18 @@ std::string RISCVISAInfo::toString() const {
 
   Arch << "rv" << XLen;
 
+  bool HasY = Exts.count("y") != 0;
   ListSeparator LS("_");
   for (auto const &Ext : Exts) {
     StringRef ExtName = Ext.first;
+    if (HasY) {
+      // Plain 'y' always implies 'i' (which is omitted in the normalized arch
+      // string). Y+E requires a long base name arch string.
+      if (ExtName == "i")
+        continue;
+      if (ExtName == "e")
+        reportFatalUsageError("Y+E is not supported yet");
+    }
     auto ExtInfo = Ext.second;
     Arch << LS << ExtName;
     Arch << ExtInfo.Major << "p" << ExtInfo.Minor;
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll 
b/llvm/test/CodeGen/RISCV/attributes.ll
index 765245ef4db725..554188c084a270 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -711,7 +711,7 @@
 ; RV64SDEXT: .attribute 5, "rv64i2p1_sdext1p0"
 ; RV64SDTRIG: .attribute 5, "rv64i2p1_sdtrig1p0"
 ; RV64P: .attribute 5, "rv64i2p1_p0p21_zicsr2p0_zmmul1p0_zba1p0_zbb1p0"
-; RV64Y: .attribute 5, "rv64i2p1_y0p910"
+; RV64Y: .attribute 5, "rv64y0p910"
 ; RV64ZIBI: .attribute 5, "rv64i2p1_zibi0p1"
 ; RV64ZVQWBDOTA8I: .attribute 5, 
"rv64i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_zvqwbdota8i0p2"
 ; RV64ZVQWBDOTA16I: .attribute 5, 
"rv64i2p1_zicsr2p0_zve32x1p0_zve64x1p0_zvl32b1p0_zvl64b1p0_zvqwbdota16i0p2"
diff --git a/llvm/test/MC/RISCV/rvy-build-attributes.s 
b/llvm/test/MC/RISCV/rvy-build-attributes.s
index f7db55b382ec81..512db1e95f5291 100644
--- a/llvm/test/MC/RISCV/rvy-build-attributes.s
+++ b/llvm/test/MC/RISCV/rvy-build-attributes.s
@@ -1,35 +1,44 @@
+## Pipe the assembly output through a second llvm-mc invocation to ensure the
+## emitted '.attribute 5, "..."' arch string round-trips cleanly.
 # RUN: llvm-mc %s -triple=riscv64 -filetype=asm -riscv-add-build-attributes \
-# RUN:   -mattr=+experimental-y,+d,+c | FileCheck %s --check-prefix=RV64YDC
+# RUN:   -mattr=+experimental-y,+d,+c | llvm-mc -triple=riscv64 -filetype=asm \
+# RUN:   | FileCheck %s --check-prefix=RV64YDC
 # RUN: llvm-mc %s -triple=riscv32 -filetype=asm -riscv-add-build-attributes \
-# RUN:   -mattr=+experimental-y,+f,+c | FileCheck %s --check-prefix=RV32YFC
+# RUN:   -mattr=+experimental-y,+f,+c | llvm-mc -triple=riscv32 -filetype=asm \
+# RUN:   | FileCheck %s --check-prefix=RV32YFC
 # RUN: llvm-mc %s -triple=riscv32 -filetype=asm -riscv-add-build-attributes \
-# RUN:   -mattr=+experimental-y,+zca,+f | FileCheck %s 
--check-prefix=RV32Y-ZCA-F
+# RUN:   -mattr=+experimental-y,+zca,+f | llvm-mc -triple=riscv32 
-filetype=asm \
+# RUN:   | FileCheck %s --check-prefix=RV32Y-ZCA-F
 # RUN: llvm-mc %s -triple=riscv64 -filetype=asm -riscv-add-build-attributes \
-# RUN:   -mattr=+experimental-y,+zca,+d | FileCheck %s 
--check-prefix=RV64Y-ZCA-D
+# RUN:   -mattr=+experimental-y,+zca,+d | llvm-mc -triple=riscv64 
-filetype=asm \
+# RUN:   | FileCheck %s --check-prefix=RV64Y-ZCA-D
 # RUN: llvm-mc %s -triple=riscv64 -filetype=asm -riscv-add-build-attributes \
-# RUN:   -mattr=+experimental-y,+zca,+zcb | FileCheck %s 
--check-prefix=RV64Y-ZCA-ZCB
+# RUN:   -mattr=+experimental-y,+zca,+zcb | llvm-mc -triple=riscv64 
-filetype=asm \
+# RUN:   | FileCheck %s --check-prefix=RV64Y-ZCA-ZCB
 # RUN: llvm-mc %s -triple=riscv32 -filetype=asm -riscv-add-build-attributes \
-# RUN:   -mattr=+experimental-y,+zce | FileCheck %s --check-prefix=RV32Y-ZCE
+# RUN:   -mattr=+experimental-y,+zce | llvm-mc -triple=riscv32 -filetype=asm \
+# RUN:   | FileCheck %s --check-prefix=RV32Y-ZCE
 # RUN: llvm-mc %s -triple=riscv32 -filetype=asm -riscv-add-build-attributes \
-# RUN:   -mattr=+experimental-y,+zce,+f | FileCheck %s 
--check-prefix=RV32Y-ZCE-F
+# RUN:   -mattr=+experimental-y,+zce,+f | llvm-mc -triple=riscv32 
-filetype=asm \
+# RUN:   | FileCheck %s --check-prefix=RV32Y-ZCE-F
 
 ## RV64Y + D + C: y is enabled, so zcd is not implied.
-# RV64YDC: .attribute 5, "rv64i2p1_f2p2_d2p2_c2p0_y0p910_zicsr2p0_zca1p0"
+# RV64YDC: .attribute 5, "rv64y0p910_f2p2_d2p2_c2p0_zicsr2p0_zca1p0"
 
 ## RV32Y + F + C: y is enabled, so zcf is not implied.
-# RV32YFC: .attribute 5, "rv32i2p1_f2p2_c2p0_y0p910_zicsr2p0_zca1p0"
+# RV32YFC: .attribute 5, "rv32y0p910_f2p2_c2p0_zicsr2p0_zca1p0"
 
 ## RV32Y + ZCA + F: zca + y implies c on RV32 (y replaces zcf in the 
implication).
-# RV32Y-ZCA-F: .attribute 5, "rv32i2p1_f2p2_c2p0_y0p910_zicsr2p0_zca1p0"
+# RV32Y-ZCA-F: .attribute 5, "rv32y0p910_f2p2_c2p0_zicsr2p0_zca1p0"
 
 ## RV64Y + ZCA + D: zca + y implies c on RV64 (y replaces zcd in the 
implication).
-# RV64Y-ZCA-D: .attribute 5, "rv64i2p1_f2p2_d2p2_c2p0_y0p910_zicsr2p0_zca1p0"
+# RV64Y-ZCA-D: .attribute 5, "rv64y0p910_f2p2_d2p2_c2p0_zicsr2p0_zca1p0"
 
 ## RV64Y + ZCA + ZCB: zca + zcb + y does NOT imply zce on RV64Y because Zce is 
incompatible. zca also implies c.
-# RV64Y-ZCA-ZCB: .attribute 5, "rv64i2p1_c2p0_y0p910_zca1p0_zcb1p0"
+# RV64Y-ZCA-ZCB: .attribute 5, "rv64y0p910_c2p0_zca1p0_zcb1p0"
 
 ## RV32Y + ZCE: zce implies zca, zcb, zcmp, zcmt. zca implies c.
-# RV32Y-ZCE: .attribute 5, 
"rv32i2p1_c2p0_y0p910_zicsr2p0_zca1p0_zcb1p0_zce1p0_zcmp1p0_zcmt1p0"
+# RV32Y-ZCE: .attribute 5, 
"rv32y0p910_c2p0_zicsr2p0_zca1p0_zcb1p0_zce1p0_zcmp1p0_zcmt1p0"
 
 ## RV32Y + ZCE + F: y is enabled, so zcf is not implied by zce + f. zca + y + 
f implies c.
-# RV32Y-ZCE-F: .attribute 5, 
"rv32i2p1_f2p2_c2p0_y0p910_zicsr2p0_zca1p0_zcb1p0_zce1p0_zcmp1p0_zcmt1p0"
+# RV32Y-ZCE-F: .attribute 5, 
"rv32y0p910_f2p2_c2p0_zicsr2p0_zca1p0_zcb1p0_zce1p0_zcmp1p0_zcmt1p0"
diff --git a/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test 
b/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test
index 704c9d4add0d1d..59750e867c4e23 100644
--- a/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test
+++ b/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test
@@ -3,7 +3,7 @@
 ## The expected behavior is to ignore the unrecognized arch feature and
 ## continue to process the following arch features.
 ##
-## The object file has the "rv32i2p0_m2p0_y1p0" arch feature. "y1p0" is an
+## The object file has the "rv32i2p0_m2p0_w1p0" arch feature. "w1p0" is an
 ## unrecognized architecture extension. llvm-objdump will ignore it and decode
 ## "mul" instruction correctly according to "m2p0" in the arch feature.
 ##
@@ -34,5 +34,5 @@ Sections:
     Content: 3385C502
   - Name:    .riscv.attributes
     Type:    SHT_RISCV_ATTRIBUTES
-## The content is the encoding of the arch feature "rv32i2p0_m2p0_y1p0"
-    Content: 
412300000072697363760001190000000572763332693270305F6D3270305F7931703000
+## The content is the encoding of the arch feature "rv32i2p0_m2p0_w1p0"
+    Content: 
412300000072697363760001190000000572763332693270305F6D3270305F7731703000
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp 
b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index fc258241d0ef98..978c8fb3c9f315 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -48,6 +48,26 @@ TEST(ParseNormalizedArchString, RejectsConflictingBaseISAs) {
         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
         "conflicting base ISAs 'e' and 'i'");
   }
+  for (StringRef Input : {"rv32y0p910_i2p1", "rv64y0p910_m2p0_i2p1"}) {
+    EXPECT_EQ(
+        toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
+        "conflicting base ISAs 'y' and 'i'");
+  }
+  for (StringRef Input : {"rv32y0p910_e2p0", "rv64y0p910_m2p0_e2p0"}) {
+    EXPECT_EQ(
+        toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
+        "conflicting base ISAs 'y' and 'e'");
+  }
+  for (StringRef Input : {"rv32i2p0_y0p910", "rv32i2p0_m2p0_y1p0"}) {
+    EXPECT_EQ(
+        toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
+        "conflicting base ISAs 'i' and 'y'");
+  }
+  for (StringRef Input : {"rv32e2p0_y0p910", "rv64e2p0_m2p0_y0p910"}) {
+    EXPECT_EQ(
+        toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
+        "conflicting base ISAs 'e' and 'y'");
+  }
 }
 
 TEST(ParseNormalizedArchString, RejectsMalformedInputs) {
@@ -69,6 +89,12 @@ TEST(ParseNormalizedArchString, RejectsMalformedInputs) {
         "base ISA 'e' is missing version number");
   }
 
+  for (StringRef Input : {"rv64ya2p0", "rv32i2p0_ym2p0"}) {
+    EXPECT_EQ(
+        toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
+        "base ISA 'y' is missing version number");
+  }
+
   EXPECT_EQ(toString(RISCVISAInfo::parseNormalizedArchString("rv32i2p0_ma2p0")
                          .takeError()),
             "extension 'm' is missing version number");
@@ -121,6 +147,10 @@ TEST(ParseNormalizedArchString, DuplicateExtension) {
         toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
         "duplicate extension 'a'");
   }
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseNormalizedArchString("rv64y0p910_y0p910")
+                   .takeError()),
+      "duplicate extension 'y'");
 }
 
 TEST(ParseNormalizedArchString, AcceptsValidBaseISAsAndSetsXLen) {
@@ -140,6 +170,17 @@ TEST(ParseNormalizedArchString, 
AcceptsValidBaseISAsAndSetsXLen) {
               (RISCVISAUtils::ExtensionVersion{2, 0}));
   EXPECT_EQ(InfoRV32E.getXLen(), 32U);
 
+  auto MaybeRV32Y = RISCVISAInfo::parseNormalizedArchString("rv32y0p910");
+  ASSERT_THAT_EXPECTED(MaybeRV32Y, Succeeded());
+  RISCVISAInfo &InfoRV32Y = **MaybeRV32Y;
+  EXPECT_EQ(InfoRV32Y.getExtensions().size(), 2UL);
+  EXPECT_TRUE(InfoRV32Y.getExtensions().at("i") ==
+              (RISCVISAUtils::ExtensionVersion{2, 1}));
+  EXPECT_TRUE(InfoRV32Y.getExtensions().at("y") ==
+              (RISCVISAUtils::ExtensionVersion{0, 910}));
+  EXPECT_EQ(InfoRV32Y.getXLen(), 32U);
+  EXPECT_EQ(InfoRV32Y.toString(), "rv32y0p910");
+
   auto MaybeRV64I = RISCVISAInfo::parseNormalizedArchString("rv64i2p0");
   ASSERT_THAT_EXPECTED(MaybeRV64I, Succeeded());
   RISCVISAInfo &InfoRV64I = **MaybeRV64I;
@@ -155,6 +196,17 @@ TEST(ParseNormalizedArchString, 
AcceptsValidBaseISAsAndSetsXLen) {
   EXPECT_TRUE(InfoRV64E.getExtensions().at("e") ==
               (RISCVISAUtils::ExtensionVersion{2, 0}));
   EXPECT_EQ(InfoRV64E.getXLen(), 64U);
+
+  auto MaybeRV64Y = RISCVISAInfo::parseNormalizedArchString("rv64y0p910");
+  ASSERT_THAT_EXPECTED(MaybeRV64Y, Succeeded());
+  RISCVISAInfo &InfoRV64Y = **MaybeRV64Y;
+  EXPECT_EQ(InfoRV64Y.getExtensions().size(), 2UL);
+  EXPECT_TRUE(InfoRV64Y.getExtensions().at("i") ==
+              (RISCVISAUtils::ExtensionVersion{2, 1}));
+  EXPECT_TRUE(InfoRV64Y.getExtensions().at("y") ==
+              (RISCVISAUtils::ExtensionVersion{0, 910}));
+  EXPECT_EQ(InfoRV64Y.getXLen(), 64U);
+  EXPECT_EQ(InfoRV64Y.toString(), "rv64y0p910");
 }
 
 TEST(ParseNormalizedArchString, AcceptsArbitraryExtensionsAndVersions) {
@@ -189,10 +241,10 @@ TEST(ParseNormalizedArchString, 
UpdatesFLenMinVLenMaxELen) {
 
 TEST(ParseNormalizedArchString, AcceptsUnknownMultiletter) {
   auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
-      "rv64i2p0_f2p0_d2p0_zicsr2p0_ykk1p0");
+      "rv64i2p0_f2p0_d2p0_zicsr2p0_wkk1p0");
   ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
   RISCVISAInfo &Info = **MaybeISAInfo;
-  EXPECT_EQ(Info.toString(), "rv64i2p0_f2p0_d2p0_zicsr2p0_ykk1p0");
+  EXPECT_EQ(Info.toString(), "rv64i2p0_f2p0_d2p0_zicsr2p0_wkk1p0");
 }
 
 TEST(ParseArchString, RejectsInvalidChars) {
@@ -244,20 +296,24 @@ TEST(ParseArchString, RejectsInvalidBaseISA) {
 }
 
 TEST(ParseArchString, RejectsInvalidYPosition) {
-  // y in non-first position is rejected.
+  // 'y' is only allowed as a base ISA ('rv32y' or 'rv64y'). Anything else
+  // should be rejected as an invalid extension.
   for (StringRef Input :
-       {"rv32ey0p910", "rv64ey0p910", "rv32iy0p910", "rv64iy0p910"}) {
+       {"rv32ey0p910", "rv64ey0p910", "rv32iy0p910", "rv64iy0p910",
+        "rv32gy0p910", "rv64gy0p910", "rv32imy0p910", "rv64imy0p910",
+        "rv32i2p1_y0p910", "rv32i_m_y0p910", "rv64y0p910_y0p910"}) {
     EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
               "invalid standard user-level extension 'y'");
   }
-  for (StringRef Input : {"rv32ey", "rv64ey", "rv32iy", "rv64iy"}) {
+  for (StringRef Input : {"rv32ey", "rv64ey", "rv32iy", "rv64iy", "rv32gy",
+                          "rv64gy", "rv32imy", "rv64imy", "rv32yy", "rv64yy"}) 
{
     EXPECT_EQ(
         toString(RISCVISAInfo::parseArchString(Input, true, 
false).takeError()),
         "invalid standard user-level extension 'y'");
   }
 }
 
-TEST(ParseArchString, MissingBaseISA) {
+TEST(ParseArchString, AcceptsRVYBaseISA) {
   // With version check enabled (default), we must specify the version for
   // experimental extension 'y'.
   auto MaybeRV32Y = RISCVISAInfo::parseArchString("rv32y0p910", true);
@@ -268,8 +324,10 @@ TEST(ParseArchString, MissingBaseISA) {
   EXPECT_TRUE(ExtsRV32Y.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
   EXPECT_TRUE(ExtsRV32Y.at("y") == (RISCVISAUtils::ExtensionVersion{0, 910}));
   EXPECT_EQ(InfoRV32Y.getXLen(), 32U);
+  EXPECT_EQ(InfoRV32Y.toString(), "rv32y0p910");
 
-  // rv32y0p910m should succeed and contain i, m, y0p910, zmmul
+  // rv32y0p910m should succeed and contain i, m, y0p910, zmmul, with 'i'
+  // omitted and 'y' ordered before 'm', round-tripping through both parsers.
   auto MaybeRV32YM = RISCVISAInfo::parseArchString("rv32y0p910m", true);
   ASSERT_THAT_EXPECTED(MaybeRV32YM, Succeeded());
   RISCVISAInfo &InfoRV32YM = **MaybeRV32YM;
@@ -280,11 +338,19 @@ TEST(ParseArchString, MissingBaseISA) {
               (RISCVISAUtils::ExtensionVersion{2, 0}));
   EXPECT_TRUE(InfoRV32YM.getExtensions().at("y") ==
               (RISCVISAUtils::ExtensionVersion{0, 910}));
+  std::string RV32YMStr = InfoRV32YM.toString();
+  EXPECT_EQ(RV32YMStr, "rv32y0p910_m2p0_zmmul1p0");
+  auto RoundTripArch = RISCVISAInfo::parseArchString(RV32YMStr, true);
+  ASSERT_THAT_EXPECTED(RoundTripArch, Succeeded());
+  EXPECT_EQ((*RoundTripArch)->toString(), RV32YMStr);
+  auto RoundTripNorm = RISCVISAInfo::parseNormalizedArchString(RV32YMStr);
+  ASSERT_THAT_EXPECTED(RoundTripNorm, Succeeded());
+  EXPECT_EQ((*RoundTripNorm)->toString(), RV32YMStr);
 
   // We can also parse it without version if we disable the version check.
-  auto MaybeRV32YNoVal = RISCVISAInfo::parseArchString("rv32y", true, false);
-  ASSERT_THAT_EXPECTED(MaybeRV32YNoVal, Succeeded());
-  EXPECT_EQ((*MaybeRV32YNoVal)->getExtensions().size(), 2UL);
+  auto MaybeNoVal = RISCVISAInfo::parseArchString("rv32y", true, false);
+  ASSERT_THAT_EXPECTED(MaybeNoVal, Succeeded());
+  EXPECT_EQ((*MaybeNoVal)->getExtensions().size(), 2UL);
 
   auto MaybeRV64Y = RISCVISAInfo::parseArchString("rv64y0p910", true);
   ASSERT_THAT_EXPECTED(MaybeRV64Y, Succeeded());
@@ -294,6 +360,7 @@ TEST(ParseArchString, MissingBaseISA) {
   EXPECT_TRUE(ExtsRV64Y.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
   EXPECT_TRUE(ExtsRV64Y.at("y") == (RISCVISAUtils::ExtensionVersion{0, 910}));
   EXPECT_EQ(InfoRV64Y.getXLen(), 64U);
+  EXPECT_EQ(InfoRV64Y.toString(), "rv64y0p910");
 }
 
 TEST(ParseArchString, RejectsUnsupportedBaseISA) {
@@ -1036,10 +1103,10 @@ TEST(OrderedExtensionMap, 
ExtensionsAreCorrectlyOrdered) {
   for (const auto &Ext : Exts)
     ExtNames.push_back(Ext.first);
 
-  // FIXME: 'l' and 'y' should be ordered after 'i', 'm', 'c'.
+  // FIXME: 'l' should be ordered after 'i', 'm', 'c'.
   EXPECT_THAT(ExtNames,
-              ElementsAre("i", "m", "l", "c", "y", "zicsr", "zmfoo", "zfinx",
-                           "zzfoo", "sbar", "sfoo", "xbar", "xfoo"));
+              ElementsAre("i", "y", "m", "l", "c", "zicsr", "zmfoo", "zfinx",
+                          "zzfoo", "sbar", "sfoo", "xbar", "xfoo"));
 }
 
 TEST(ParseArchString, ZceImplication) {
@@ -1705,8 +1772,8 @@ R"(All available -march extensions for RISC-V
     xwchc                2.2
 
 Experimental extensions
-    p                    0.21
     y                    0.910
+    p                    0.21
     zibi                 0.1
     zicfilp              1.0       This is a long dummy description
     zilx                 0.1

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to