[llvm] b21fb66 - [RISCV][test] Expand test coverage of RISCVISAInfo

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 13 03:52:37 PDT 2023


Author: Alex Bradbury
Date: 2023-03-13T10:51:15Z
New Revision: b21fb66cb4412256e188de87744ec6adc5869a1c

URL: https://github.com/llvm/llvm-project/commit/b21fb66cb4412256e188de87744ec6adc5869a1c
DIFF: https://github.com/llvm/llvm-project/commit/b21fb66cb4412256e188de87744ec6adc5869a1c.diff

LOG: [RISCV][test] Expand test coverage of RISCVISAInfo

D144343 added C++ unit tests for the newly added
RISCVISAInfo::parseArchStringNormalized. This patch adds test coverage
for parseArchString and the toFeatureVector member method.

Posting for review as it would be useful if someone can take a quick
look to check they don't feel I've missed testing an important aspect of
the current behaviour.

Differential Revision: https://reviews.llvm.org/D145879

Added: 
    

Modified: 
    llvm/unittests/Support/RISCVISAInfoTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp
index 18620180e87f1..2dce4df9d8c2b 100644
--- a/llvm/unittests/Support/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp
@@ -10,6 +10,8 @@
 #include "llvm/Testing/Support/Error.h"
 #include "gtest/gtest.h"
 
+using ::testing::ElementsAre;
+
 using namespace llvm;
 
 bool operator==(const llvm::RISCVExtensionInfo &A,
@@ -103,3 +105,349 @@ TEST(ParseNormalizedArchString, UpdatesFLenMinVLenMaxELen) {
   EXPECT_EQ(Info.getMinVLen(), 64U);
   EXPECT_EQ(Info.getMaxELen(), 64U);
 }
+
+TEST(ParseArchString, RejectsUpperCase) {
+  for (StringRef Input : {"RV32", "rV64", "rv32i2P0", "rv64i2p0_A2p0"}) {
+    EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
+              "string must be lowercase");
+  }
+}
+
+TEST(ParseArchString, RejectsInvalidBaseISA) {
+  for (StringRef Input : {"rv32", "rv64", "rv65i"}) {
+    EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
+              "string must begin with rv32{i,e,g} or rv64{i,g}");
+  }
+  for (StringRef Input : {"rv32j", "rv64k", "rv32_i"}) {
+    EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
+              "first letter should be 'e', 'i' or 'g'");
+  }
+}
+
+TEST(ParseArchString, RejectsUnsupportedBaseISA) {
+  EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64e", true).takeError()),
+            "standard user-level extension 'e' requires 'rv32'");
+  for (StringRef Input : {"rv128i", "rv128g"}) {
+    EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
+              "string must begin with rv32{i,e,g} or rv64{i,g}");
+  }
+}
+
+TEST(ParseArchString, AcceptsSupportedBaseISAsAndSetsXLenAndFLen) {
+  auto MaybeRV32I = RISCVISAInfo::parseArchString("rv32i", true);
+  ASSERT_THAT_EXPECTED(MaybeRV32I, Succeeded());
+  RISCVISAInfo &InfoRV32I = **MaybeRV32I;
+  RISCVISAInfo::OrderedExtensionMap ExtsRV32I = InfoRV32I.getExtensions();
+  EXPECT_EQ(ExtsRV32I.size(), 1UL);
+  EXPECT_TRUE(ExtsRV32I.at("i") == (RISCVExtensionInfo{"i", 2, 0}));
+  EXPECT_EQ(InfoRV32I.getXLen(), 32U);
+  EXPECT_EQ(InfoRV32I.getFLen(), 0U);
+
+  auto MaybeRV32E = RISCVISAInfo::parseArchString("rv32e", true);
+  ASSERT_THAT_EXPECTED(MaybeRV32E, Succeeded());
+  RISCVISAInfo &InfoRV32E = **MaybeRV32E;
+  RISCVISAInfo::OrderedExtensionMap ExtsRV32E = InfoRV32E.getExtensions();
+  EXPECT_EQ(ExtsRV32E.size(), 1UL);
+  EXPECT_TRUE(ExtsRV32E.at("e") == (RISCVExtensionInfo{"e", 1, 9}));
+  EXPECT_EQ(InfoRV32E.getXLen(), 32U);
+  EXPECT_EQ(InfoRV32E.getFLen(), 0U);
+
+  auto MaybeRV32G = RISCVISAInfo::parseArchString("rv32g", true);
+  ASSERT_THAT_EXPECTED(MaybeRV32G, Succeeded());
+  RISCVISAInfo &InfoRV32G = **MaybeRV32G;
+  RISCVISAInfo::OrderedExtensionMap ExtsRV32G = InfoRV32G.getExtensions();
+  EXPECT_EQ(ExtsRV32G.size(), 5UL);
+  EXPECT_TRUE(ExtsRV32G.at("i") == (RISCVExtensionInfo{"i", 2, 0}));
+  EXPECT_TRUE(ExtsRV32G.at("m") == (RISCVExtensionInfo{"m", 2, 0}));
+  EXPECT_TRUE(ExtsRV32G.at("a") == (RISCVExtensionInfo{"a", 2, 0}));
+  EXPECT_TRUE(ExtsRV32G.at("f") == (RISCVExtensionInfo{"f", 2, 0}));
+  EXPECT_TRUE(ExtsRV32G.at("d") == (RISCVExtensionInfo{"d", 2, 0}));
+  EXPECT_EQ(InfoRV32G.getXLen(), 32U);
+  EXPECT_EQ(InfoRV32G.getFLen(), 64U);
+
+  auto MaybeRV64I = RISCVISAInfo::parseArchString("rv64i", true);
+  ASSERT_THAT_EXPECTED(MaybeRV64I, Succeeded());
+  RISCVISAInfo &InfoRV64I = **MaybeRV64I;
+  RISCVISAInfo::OrderedExtensionMap ExtsRV64I = InfoRV64I.getExtensions();
+  EXPECT_EQ(ExtsRV64I.size(), 1UL);
+  EXPECT_TRUE(ExtsRV64I.at("i") == (RISCVExtensionInfo{"i", 2, 0}));
+  EXPECT_EQ(InfoRV64I.getXLen(), 64U);
+  EXPECT_EQ(InfoRV64I.getFLen(), 0U);
+
+  auto MaybeRV64G = RISCVISAInfo::parseArchString("rv64g", true);
+  ASSERT_THAT_EXPECTED(MaybeRV64G, Succeeded());
+  RISCVISAInfo &InfoRV64G = **MaybeRV64G;
+  RISCVISAInfo::OrderedExtensionMap ExtsRV64G = InfoRV64G.getExtensions();
+  EXPECT_EQ(ExtsRV64G.size(), 5UL);
+  EXPECT_TRUE(ExtsRV64G.at("i") == (RISCVExtensionInfo{"i", 2, 0}));
+  EXPECT_TRUE(ExtsRV64G.at("m") == (RISCVExtensionInfo{"m", 2, 0}));
+  EXPECT_TRUE(ExtsRV64G.at("a") == (RISCVExtensionInfo{"a", 2, 0}));
+  EXPECT_TRUE(ExtsRV64G.at("f") == (RISCVExtensionInfo{"f", 2, 0}));
+  EXPECT_TRUE(ExtsRV64G.at("d") == (RISCVExtensionInfo{"d", 2, 0}));
+  EXPECT_EQ(InfoRV64G.getXLen(), 64U);
+  EXPECT_EQ(InfoRV64G.getFLen(), 64U);
+}
+
+TEST(ParseArchString, RequiresCanonicalOrderForExtensions) {
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv64idf", true).takeError()),
+      "standard user-level extension not given in canonical order 'f'");
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv32iam", true).takeError()),
+      "standard user-level extension not given in canonical order 'm'");
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv32i_zfinx_a", true).takeError()),
+      "invalid extension prefix 'a'");
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv64i_svnapot_zicsr", true)
+                   .takeError()),
+      "standard user-level extension not given in canonical order 'zicsr'");
+  EXPECT_THAT_EXPECTED(
+      RISCVISAInfo::parseArchString("rv64imafdc_zicsr_svnapot", true),
+      Succeeded());
+}
+
+TEST(ParseArchString, RejectsUnrecognizedExtensionNamesByDefault) {
+  EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64ib", true).takeError()),
+            "unsupported standard user-level extension 'b'");
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv32i_zmadeup", true).takeError()),
+      "unsupported standard user-level extension 'zmadeup'");
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv64g_smadeup", true).takeError()),
+      "unsupported standard supervisor-level extension 'smadeup'");
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv64g_sxmadeup", true).takeError()),
+      "unsupported non-standard supervisor-level extension 'sxmadeup'");
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv64g_xmadeup", true).takeError()),
+      "unsupported non-standard user-level extension 'xmadeup'");
+}
+
+TEST(ParseArchString, IgnoresUnrecognizedExtensionNamesWithIgnoreUnknown) {
+  for (StringRef Input : {"rv32ib"}) {
+    auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true, false, true);
+    ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
+    RISCVISAInfo &Info = **MaybeISAInfo;
+    RISCVISAInfo::OrderedExtensionMap Exts = Info.getExtensions();
+    EXPECT_EQ(Exts.size(), 1UL);
+    EXPECT_TRUE(Exts.at("i") == (RISCVExtensionInfo{"i", 2, 0}));
+  }
+  // FIXME: These unrecognized extensions should be ignored just as in the
+  // case above. The below captures the current (incorrect) behaviour.
+  for (StringRef Input :
+       {"rv32i_zmadeup", "rv64i_smadeup", "rv32i_sxmadeup", "rv64i_xmadeup"}) {
+    auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true, false, true);
+    EXPECT_THAT_EXPECTED(MaybeISAInfo, Failed());
+  }
+}
+
+TEST(ParseArchString, AcceptsVersionInLongOrShortForm) {
+  for (StringRef Input : {"rv64i2", "rv64i2p0"}) {
+    auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
+    ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
+    RISCVISAInfo::OrderedExtensionMap Exts = (*MaybeISAInfo)->getExtensions();
+    EXPECT_TRUE(Exts.at("i") == (RISCVExtensionInfo{"i", 2, 0}));
+  }
+  for (StringRef Input : {"rv32i_zfinx1", "rv32i_zfinx1p0"}) {
+    auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
+    ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
+    RISCVISAInfo::OrderedExtensionMap Exts = (*MaybeISAInfo)->getExtensions();
+    EXPECT_TRUE(Exts.at("zfinx") == (RISCVExtensionInfo{"zfinx", 1, 0}));
+  }
+}
+
+TEST(ParseArchString, RejectsUnrecognizedExtensionVersionsByDefault) {
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv64i1p0", true).takeError()),
+      "unsupported version number 1.0 for extension 'i'");
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv64i9p9", true).takeError()),
+      "unsupported version number 9.9 for extension 'i'");
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv32im0p1", true).takeError()),
+      "unsupported version number 0.1 for extension 'm'");
+  EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv32izifencei10p10", true)
+                         .takeError()),
+            "unsupported version number 10.10 for extension 'zifencei'");
+}
+
+TEST(ParseArchString, RejectsUnrecognisedBaseISAVersionEvenWithIgnoreUnknown) {
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv64i1p0", true, false, true)
+                   .takeError()),
+      "unsupported version number 1.0 for extension 'i'");
+}
+
+TEST(ParseArchString,
+     IgnoresExtensionsWithUnrecognizedVersionsWithIgnoreUnknown) {
+  for (StringRef Input : {"rv32im1p1", "rv64i_svnapot10p9", "rv32i_zicsr0p5"}) {
+    auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true, false, true);
+    ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
+    RISCVISAInfo::OrderedExtensionMap Exts = (*MaybeISAInfo)->getExtensions();
+    EXPECT_EQ(Exts.size(), 1UL);
+    EXPECT_TRUE(Exts.at("i") == (RISCVExtensionInfo{"i", 2, 0}));
+  }
+}
+
+TEST(ParseArchString, AcceptsUnderscoreSplittingExtensions) {
+  for (StringRef Input : {"rv32imafdczifencei", "rv32i_m_a_f_d_c_zifencei"}) {
+    auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
+    ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
+    RISCVISAInfo::OrderedExtensionMap Exts = (*MaybeISAInfo)->getExtensions();
+    EXPECT_EQ(Exts.size(), 7UL);
+    EXPECT_EQ(Exts.at("i").ExtName, "i");
+    EXPECT_EQ(Exts.at("m").ExtName, "m");
+    EXPECT_EQ(Exts.at("a").ExtName, "a");
+    EXPECT_EQ(Exts.at("f").ExtName, "f");
+    EXPECT_EQ(Exts.at("d").ExtName, "d");
+    EXPECT_EQ(Exts.at("c").ExtName, "c");
+    EXPECT_EQ(Exts.at("zifencei").ExtName, "zifencei");
+  }
+}
+
+TEST(ParseArchString, RejectsDoubleOrTrailingUnderscore) {
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv64i__m", true).takeError()),
+      "invalid standard user-level extension '_'");
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv32ezicsr_", true).takeError()),
+      "extension name missing after separator '_'");
+
+  // FIXME: Trailing underscores after single letter extensions are accepted,
+  // which is inconsistent.
+  ASSERT_THAT_EXPECTED(RISCVISAInfo::parseArchString("rv32i_", true),
+                       Succeeded());
+  ASSERT_THAT_EXPECTED(RISCVISAInfo::parseArchString("rv64im_", true),
+                       Succeeded());
+}
+
+TEST(ParseArchString, RejectsDuplicateExtensionNames) {
+  EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64ii", true).takeError()),
+            "invalid standard user-level extension 'i'");
+  EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv32ee", true).takeError()),
+            "invalid standard user-level extension 'e'");
+  EXPECT_EQ(
+      toString(RISCVISAInfo::parseArchString("rv64imm", true).takeError()),
+      "standard user-level extension not given in canonical order 'm'");
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv32i_zicsr_zicsr", true).takeError()),
+      "duplicated standard user-level extension 'zicsr'");
+}
+
+TEST(ParseArchString,
+     RejectsExperimentalExtensionsIfNotEnableExperimentalExtension) {
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv64izihintntl", false).takeError()),
+      "requires '-menable-experimental-extensions' for experimental extension "
+      "'zihintntl'");
+}
+
+TEST(ParseArchString,
+     AcceptsExperimentalExtensionsIfEnableExperimentalExtension) {
+  // Note: If zihintntl becomes none-experimental, this test will need
+  // updating (and unfortunately, it will still pass). The failure of
+  // RejectsExperimentalExtensionsIfNotEnableExperimentalExtension will
+  // hopefully serve as a reminder to update.
+  auto MaybeISAInfo =
+      RISCVISAInfo::parseArchString("rv64izihintntl", true, false);
+  ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
+  RISCVISAInfo::OrderedExtensionMap Exts = (*MaybeISAInfo)->getExtensions();
+  EXPECT_EQ(Exts.size(), 2UL);
+  EXPECT_EQ(Exts.at("zihintntl").ExtName, "zihintntl");
+  auto MaybeISAInfo2 = RISCVISAInfo::parseArchString("rv64izihintntl0p2", true);
+  ASSERT_THAT_EXPECTED(MaybeISAInfo2, Succeeded());
+  RISCVISAInfo::OrderedExtensionMap Exts2 = (*MaybeISAInfo2)->getExtensions();
+  EXPECT_EQ(Exts2.size(), 2UL);
+  EXPECT_EQ(Exts2.at("zihintntl").ExtName, "zihintntl");
+}
+
+TEST(ParseArchString,
+     RequiresExplicitVersionNumberForExperimentalExtensionByDefault) {
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv64izihintntl", true).takeError()),
+      "experimental extension requires explicit version number `zihintntl`");
+}
+
+TEST(ParseArchString,
+     AcceptsUnrecognizedVersionIfNotExperimentalExtensionVersionCheck) {
+  auto MaybeISAInfo =
+      RISCVISAInfo::parseArchString("rv64izihintntl9p9", true, false);
+  ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
+  RISCVISAInfo::OrderedExtensionMap Exts = (*MaybeISAInfo)->getExtensions();
+  EXPECT_EQ(Exts.size(), 2UL);
+  EXPECT_TRUE(Exts.at("zihintntl") == (RISCVExtensionInfo{"zihintntl", 9, 9}));
+}
+
+TEST(ParseArchString, RejectsUnrecognizedVersionForExperimentalExtension) {
+  EXPECT_EQ(
+      toString(
+          RISCVISAInfo::parseArchString("rv64izihintntl9p9", true).takeError()),
+      "unsupported version number 9.9 for experimental extension 'zihintntl' "
+      "(this compiler supports 0.2)");
+}
+
+TEST(ParseArchString, AcceptsExtensionVersionForG) {
+  // FIXME: As there is no versioning scheme for G, arguably an error should
+  // be produced.
+  auto MaybeISAInfo = RISCVISAInfo::parseArchString("rv64g9p9", true, false);
+  ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
+  RISCVISAInfo::OrderedExtensionMap Exts = (*MaybeISAInfo)->getExtensions();
+  EXPECT_EQ(Exts.size(), 5UL);
+  EXPECT_TRUE(Exts.at("i") == (RISCVExtensionInfo{"i", 2, 0}));
+}
+
+TEST(ParseArchString, AddsImpliedExtensions) {
+  // Does not attempt to exhaustively test all implications.
+  auto MaybeRV64ID = RISCVISAInfo::parseArchString("rv64id", true);
+  ASSERT_THAT_EXPECTED(MaybeRV64ID, Succeeded());
+  RISCVISAInfo::OrderedExtensionMap ExtsRV64ID =
+      (*MaybeRV64ID)->getExtensions();
+  EXPECT_EQ(ExtsRV64ID.size(), 3UL);
+  EXPECT_EQ(ExtsRV64ID.at("i").ExtName, "i");
+  EXPECT_EQ(ExtsRV64ID.at("f").ExtName, "f");
+  EXPECT_EQ(ExtsRV64ID.at("d").ExtName, "d");
+
+  auto MaybeRV32IZKN = RISCVISAInfo::parseArchString("rv64izkn", true);
+  ASSERT_THAT_EXPECTED(MaybeRV32IZKN, Succeeded());
+  RISCVISAInfo::OrderedExtensionMap ExtsRV32IZKN =
+      (*MaybeRV32IZKN)->getExtensions();
+  EXPECT_EQ(ExtsRV32IZKN.size(), 8UL);
+  EXPECT_EQ(ExtsRV32IZKN.at("i").ExtName, "i");
+  EXPECT_EQ(ExtsRV32IZKN.at("zbkb").ExtName, "zbkb");
+  EXPECT_EQ(ExtsRV32IZKN.at("zbkc").ExtName, "zbkc");
+  EXPECT_EQ(ExtsRV32IZKN.at("zbkx").ExtName, "zbkx");
+  EXPECT_EQ(ExtsRV32IZKN.at("zkne").ExtName, "zkne");
+  EXPECT_EQ(ExtsRV32IZKN.at("zknd").ExtName, "zknd");
+  EXPECT_EQ(ExtsRV32IZKN.at("zknh").ExtName, "zknh");
+  EXPECT_EQ(ExtsRV32IZKN.at("zkn").ExtName, "zkn");
+}
+
+TEST(ParseArchString, RejectsConflictingExtensions) {
+  for (StringRef Input : {"rv32ifzfinx", "rv64gzdinx"}) {
+    EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
+              "'f' and 'zfinx' extensions are incompatible");
+  }
+}
+
+TEST(ToFeatureVector, IIsDroppedAndExperimentalExtensionsArePrefixed) {
+  auto MaybeISAInfo1 =
+      RISCVISAInfo::parseArchString("rv64im_zihintntl", true, false);
+  ASSERT_THAT_EXPECTED(MaybeISAInfo1, Succeeded());
+  EXPECT_THAT((*MaybeISAInfo1)->toFeatureVector(),
+              ElementsAre("+m", "+experimental-zihintntl"));
+
+  auto MaybeISAInfo2 = RISCVISAInfo::parseArchString(
+      "rv32e_zihintntl_xventanacondops", true, false);
+  ASSERT_THAT_EXPECTED(MaybeISAInfo2, Succeeded());
+  EXPECT_THAT((*MaybeISAInfo2)->toFeatureVector(),
+              ElementsAre("+e", "+experimental-zihintntl", "+xventanacondops"));
+}


        


More information about the llvm-commits mailing list