zixuan-wu created this revision.
zixuan-wu added reviewers: asb, craig.topper, kito-cheng, luismarques, apazos, 
jrtc27, Jim, akuegel, jhenderson, MaskRay, sjarus.
Herald added subscribers: VincentWu, luke957, achieveartificialintelligence, 
vkmr, frasercrmck, evandro, sameer.abuasal, s.egerton, benna, psnobl, jocewei, 
PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, niosHD, 
sabuasal, simoncook, johnrusso, rbar, hiraditya.
zixuan-wu requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

Split from https://reviews.llvm.org/D115921 since testcase change is too large 
to review.

This is part of D115921 <https://reviews.llvm.org/D115921>, and will not be 
committed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115923

Files:
  clang/include/clang/Basic/BuiltinsRISCV.def
  clang/lib/Basic/Targets/RISCV.cpp
  clang/lib/Driver/ToolChains/Arch/RISCV.cpp
  clang/utils/TableGen/RISCVVEmitter.cpp
  llvm/include/llvm/Support/RISCVISAInfo.h
  llvm/lib/Object/ELFObjectFile.cpp
  llvm/lib/Support/RISCVISAInfo.cpp
  llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
  llvm/lib/Target/RISCV/RISCV.td
  llvm/lib/Target/RISCV/RISCVSubtarget.h

Index: llvm/lib/Target/RISCV/RISCVSubtarget.h
===================================================================
--- llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -24,6 +24,7 @@
 #include "llvm/CodeGen/SelectionDAGTargetInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/Support/RISCVISAInfo.h"
 #include "llvm/Target/TargetMachine.h"
 
 #define GET_SUBTARGETINFO_HEADER
@@ -34,28 +35,28 @@
 
 class RISCVSubtarget : public RISCVGenSubtargetInfo {
   virtual void anchor();
-  bool HasStdExtM = false;
-  bool HasStdExtA = false;
-  bool HasStdExtF = false;
-  bool HasStdExtD = false;
-  bool HasStdExtC = false;
-  bool HasStdExtZba = false;
-  bool HasStdExtZbb = false;
-  bool HasStdExtZbc = false;
-  bool HasStdExtZbe = false;
-  bool HasStdExtZbf = false;
-  bool HasStdExtZbm = false;
-  bool HasStdExtZbp = false;
-  bool HasStdExtZbr = false;
-  bool HasStdExtZbs = false;
-  bool HasStdExtZbt = false;
-  bool HasStdExtV = false;
-  bool HasStdExtZvlsseg = false;
-  bool HasStdExtZvamo = false;
-  bool HasStdExtZfhmin = false;
-  bool HasStdExtZfh = false;
+  RISCVExtensionVersion StdExtM = {0, 0};
+  RISCVExtensionVersion StdExtA = {0, 0};
+  RISCVExtensionVersion StdExtF = {0, 0};
+  RISCVExtensionVersion StdExtD = {0, 0};
+  RISCVExtensionVersion StdExtC = {0, 0};
+  RISCVExtensionVersion StdExtZba = {0, 0};
+  RISCVExtensionVersion StdExtZbb = {0, 0};
+  RISCVExtensionVersion StdExtZbc = {0, 0};
+  RISCVExtensionVersion StdExtZbe = {0, 0};
+  RISCVExtensionVersion StdExtZbf = {0, 0};
+  RISCVExtensionVersion StdExtZbm = {0, 0};
+  RISCVExtensionVersion StdExtZbp = {0, 0};
+  RISCVExtensionVersion StdExtZbr = {0, 0};
+  RISCVExtensionVersion StdExtZbs = {0, 0};
+  RISCVExtensionVersion StdExtZbt = {0, 0};
+  RISCVExtensionVersion StdExtV = {0, 0};
+  RISCVExtensionVersion StdExtZvlsseg = {0, 0};
+  RISCVExtensionVersion StdExtZvamo = {0, 0};
+  RISCVExtensionVersion StdExtZfhmin = {0, 0};
+  RISCVExtensionVersion StdExtZfh = {0, 0};
+  RISCVExtensionVersion StdExtE = {0, 0};
   bool HasRV64 = false;
-  bool IsRV32E = false;
   bool EnableLinkerRelax = false;
   bool EnableRVCHintInstrs = true;
   bool EnableSaveRestore = false;
@@ -101,28 +102,34 @@
     return &TSInfo;
   }
   bool enableMachineScheduler() const override { return true; }
-  bool hasStdExtM() const { return HasStdExtM; }
-  bool hasStdExtA() const { return HasStdExtA; }
-  bool hasStdExtF() const { return HasStdExtF; }
-  bool hasStdExtD() const { return HasStdExtD; }
-  bool hasStdExtC() const { return HasStdExtC; }
-  bool hasStdExtZba() const { return HasStdExtZba; }
-  bool hasStdExtZbb() const { return HasStdExtZbb; }
-  bool hasStdExtZbc() const { return HasStdExtZbc; }
-  bool hasStdExtZbe() const { return HasStdExtZbe; }
-  bool hasStdExtZbf() const { return HasStdExtZbf; }
-  bool hasStdExtZbm() const { return HasStdExtZbm; }
-  bool hasStdExtZbp() const { return HasStdExtZbp; }
-  bool hasStdExtZbr() const { return HasStdExtZbr; }
-  bool hasStdExtZbs() const { return HasStdExtZbs; }
-  bool hasStdExtZbt() const { return HasStdExtZbt; }
-  bool hasStdExtV() const { return HasStdExtV; }
-  bool hasStdExtZvlsseg() const { return HasStdExtZvlsseg; }
-  bool hasStdExtZvamo() const { return HasStdExtZvamo; }
-  bool hasStdExtZfhmin() const { return HasStdExtZfhmin; }
-  bool hasStdExtZfh() const { return HasStdExtZfh; }
+  bool hasStdExtM() const { return StdExtM != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtA() const { return StdExtA != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtF() const { return StdExtF != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtD() const { return StdExtD != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtC() const { return StdExtC != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZba() const { return StdExtZba != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbb() const { return StdExtZbb != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbc() const { return StdExtZbc != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbe() const { return StdExtZbe != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbf() const { return StdExtZbf != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbm() const { return StdExtZbm != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbp() const { return StdExtZbp != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbr() const { return StdExtZbr != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbs() const { return StdExtZbs != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbt() const { return StdExtZbt != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtV() const { return StdExtV != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZvlsseg() const {
+    return StdExtZvlsseg != RISCVExtensionVersion{0, 0};
+  }
+  bool hasStdExtZvamo() const {
+    return StdExtZvamo != RISCVExtensionVersion{0, 0};
+  }
+  bool hasStdExtZfhmin() const {
+    return StdExtZfhmin != RISCVExtensionVersion{0, 0};
+  }
+  bool hasStdExtZfh() const { return StdExtZfh != RISCVExtensionVersion{0, 0}; }
   bool is64Bit() const { return HasRV64; }
-  bool isRV32E() const { return IsRV32E; }
+  bool isRV32E() const { return StdExtE != RISCVExtensionVersion{0, 0}; }
   bool enableLinkerRelax() const { return EnableLinkerRelax; }
   bool enableRVCHintInstrs() const { return EnableRVCHintInstrs; }
   bool enableSaveRestore() const { return EnableSaveRestore; }
@@ -135,11 +142,21 @@
   }
 
   // Vector codegen related methods.
-  bool hasVInstructions() const { return HasStdExtV; }
-  bool hasVInstructionsI64() const { return HasStdExtV; }
-  bool hasVInstructionsF16() const { return HasStdExtV && hasStdExtZfh(); }
-  bool hasVInstructionsF32() const { return HasStdExtV && hasStdExtF(); }
-  bool hasVInstructionsF64() const { return HasStdExtV && hasStdExtD(); }
+  bool hasVInstructions() const {
+    return StdExtV != RISCVExtensionVersion{0, 0};
+  }
+  bool hasVInstructionsI64() const {
+    return StdExtV != RISCVExtensionVersion{0, 0};
+  }
+  bool hasVInstructionsF16() const {
+    return StdExtV != RISCVExtensionVersion{0, 0} && hasStdExtZfh();
+  }
+  bool hasVInstructionsF32() const {
+    return StdExtV != RISCVExtensionVersion{0, 0} && hasStdExtF();
+  }
+  bool hasVInstructionsF64() const {
+    return StdExtV != RISCVExtensionVersion{0, 0} && hasStdExtD();
+  }
   // F16 and F64 both require F32.
   bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
   unsigned getMaxInterleaveFactor() const {
Index: llvm/lib/Target/RISCV/RISCV.td
===================================================================
--- llvm/lib/Target/RISCV/RISCV.td
+++ llvm/lib/Target/RISCV/RISCV.td
@@ -13,28 +13,28 @@
 //===----------------------------------------------------------------------===//
 
 def FeatureStdExtM
-    : SubtargetFeature<"m", "HasStdExtM", "true",
+    : SubtargetFeature<"m2p0", "StdExtM", "RISCVExtensionVersion{2, 0}",
                        "'M' (Integer Multiplication and Division)">;
 def HasStdExtM : Predicate<"Subtarget->hasStdExtM()">,
                            AssemblerPredicate<(all_of FeatureStdExtM),
                            "'M' (Integer Multiplication and Division)">;
 
 def FeatureStdExtA
-    : SubtargetFeature<"a", "HasStdExtA", "true",
+    : SubtargetFeature<"a2p0", "StdExtA", "RISCVExtensionVersion{2, 0}",
                        "'A' (Atomic Instructions)">;
 def HasStdExtA : Predicate<"Subtarget->hasStdExtA()">,
                            AssemblerPredicate<(all_of FeatureStdExtA),
                            "'A' (Atomic Instructions)">;
 
 def FeatureStdExtF
-    : SubtargetFeature<"f", "HasStdExtF", "true",
+    : SubtargetFeature<"f2p0", "StdExtF", "RISCVExtensionVersion{2, 0}",
                        "'F' (Single-Precision Floating-Point)">;
 def HasStdExtF : Predicate<"Subtarget->hasStdExtF()">,
                            AssemblerPredicate<(all_of FeatureStdExtF),
                            "'F' (Single-Precision Floating-Point)">;
 
 def FeatureStdExtD
-    : SubtargetFeature<"d", "HasStdExtD", "true",
+    : SubtargetFeature<"d2p0", "StdExtD", "RISCVExtensionVersion{2, 0}",
                        "'D' (Double-Precision Floating-Point)",
                        [FeatureStdExtF]>;
 def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">,
@@ -42,7 +42,7 @@
                            "'D' (Double-Precision Floating-Point)">;
 
 def FeatureStdExtZfhmin
-    : SubtargetFeature<"experimental-zfhmin", "HasStdExtZfhmin", "true",
+    : SubtargetFeature<"experimental-zfhmin0p1", "StdExtZfhmin", "RISCVExtensionVersion{0, 1}",
                        "'Zfhmin' (Half-Precision Floating-Point Minimal)",
                        [FeatureStdExtF]>;
 def HasStdExtZfhmin : Predicate<"Subtarget->hasStdExtZfhmin()">,
@@ -50,7 +50,7 @@
                              "'Zfhmin' (Half-Precision Floating-Point Minimal)">;
 
 def FeatureStdExtZfh
-    : SubtargetFeature<"experimental-zfh", "HasStdExtZfh", "true",
+    : SubtargetFeature<"experimental-zfh0p1", "StdExtZfh", "RISCVExtensionVersion{0, 1}",
                        "'Zfh' (Half-Precision Floating-Point)",
                        [FeatureStdExtZfhmin, FeatureStdExtF]>;
 def HasStdExtZfh : Predicate<"Subtarget->hasStdExtZfh()">,
@@ -58,14 +58,14 @@
                              "'Zfh' (Half-Precision Floating-Point)">;
 
 def FeatureStdExtC
-    : SubtargetFeature<"c", "HasStdExtC", "true",
+    : SubtargetFeature<"c2p0", "StdExtC", "RISCVExtensionVersion{2, 0}",
                        "'C' (Compressed Instructions)">;
 def HasStdExtC : Predicate<"Subtarget->hasStdExtC()">,
                            AssemblerPredicate<(all_of FeatureStdExtC),
                            "'C' (Compressed Instructions)">;
 
 def FeatureStdExtZba
-    : SubtargetFeature<"experimental-zba", "HasStdExtZba", "true",
+    : SubtargetFeature<"experimental-zba1p0", "StdExtZba", "RISCVExtensionVersion{1, 0}",
                        "'Zba' (Address calculation 'B' Instructions)">;
 def HasStdExtZba : Predicate<"Subtarget->hasStdExtZba()">,
                              AssemblerPredicate<(all_of FeatureStdExtZba),
@@ -73,63 +73,63 @@
 def NotHasStdExtZba : Predicate<"!Subtarget->hasStdExtZba()">;
 
 def FeatureStdExtZbb
-    : SubtargetFeature<"experimental-zbb", "HasStdExtZbb", "true",
+    : SubtargetFeature<"experimental-zbb1p0", "StdExtZbb", "RISCVExtensionVersion{1, 0}",
                        "'Zbb' (Base 'B' Instructions)">;
 def HasStdExtZbb : Predicate<"Subtarget->hasStdExtZbb()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbb),
                              "'Zbb' (Base 'B' Instructions)">;
 
 def FeatureStdExtZbc
-    : SubtargetFeature<"experimental-zbc", "HasStdExtZbc", "true",
+    : SubtargetFeature<"experimental-zbc1p0", "StdExtZbc", "RISCVExtensionVersion{1, 0}",
                        "'Zbc' (Carry-Less 'B' Instructions)">;
 def HasStdExtZbc : Predicate<"Subtarget->hasStdExtZbc()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbc),
                              "'Zbc' (Carry-Less 'B' Instructions)">;
 
 def FeatureStdExtZbe
-    : SubtargetFeature<"experimental-zbe", "HasStdExtZbe", "true",
+    : SubtargetFeature<"experimental-zbe0p93", "StdExtZbe", "RISCVExtensionVersion{0, 93}",
                        "'Zbe' (Extract-Deposit 'B' Instructions)">;
 def HasStdExtZbe : Predicate<"Subtarget->hasStdExtZbe()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbe),
                              "'Zbe' (Extract-Deposit 'B' Instructions)">;
 
 def FeatureStdExtZbf
-    : SubtargetFeature<"experimental-zbf", "HasStdExtZbf", "true",
+    : SubtargetFeature<"experimental-zbf0p93", "StdExtZbf", "RISCVExtensionVersion{0, 93}",
                        "'Zbf' (Bit-Field 'B' Instructions)">;
 def HasStdExtZbf : Predicate<"Subtarget->hasStdExtZbf()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbf),
                              "'Zbf' (Bit-Field 'B' Instructions)">;
 
 def FeatureStdExtZbm
-    : SubtargetFeature<"experimental-zbm", "HasStdExtZbm", "true",
+    : SubtargetFeature<"experimental-zbm0p93", "StdExtZbm", "RISCVExtensionVersion{0, 93}",
                        "'Zbm' (Matrix 'B' Instructions)">;
 def HasStdExtZbm : Predicate<"Subtarget->hasStdExtZbm()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbm),
                              "'Zbm' (Matrix 'B' Instructions)">;
 
 def FeatureStdExtZbp
-    : SubtargetFeature<"experimental-zbp", "HasStdExtZbp", "true",
+    : SubtargetFeature<"experimental-zbp0p93", "StdExtZbp", "RISCVExtensionVersion{0, 93}",
                        "'Zbp' (Permutation 'B' Instructions)">;
 def HasStdExtZbp : Predicate<"Subtarget->hasStdExtZbp()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbp),
                              "'Zbp' (Permutation 'B' Instructions)">;
 
 def FeatureStdExtZbr
-    : SubtargetFeature<"experimental-zbr", "HasStdExtZbr", "true",
+    : SubtargetFeature<"experimental-zbr0p93", "StdExtZbr", "RISCVExtensionVersion{0, 93}",
                        "'Zbr' (Polynomial Reduction 'B' Instructions)">;
 def HasStdExtZbr : Predicate<"Subtarget->hasStdExtZbr()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbr),
                              "'Zbr' (Polynomial Reduction 'B' Instructions)">;
 
 def FeatureStdExtZbs
-    : SubtargetFeature<"experimental-zbs", "HasStdExtZbs", "true",
+    : SubtargetFeature<"experimental-zbs1p0", "StdExtZbs", "RISCVExtensionVersion{1, 0}",
                        "'Zbs' (Single-Bit 'B' Instructions)">;
 def HasStdExtZbs : Predicate<"Subtarget->hasStdExtZbs()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbs),
                              "'Zbs' (Single-Bit 'B' Instructions)">;
 
 def FeatureStdExtZbt
-    : SubtargetFeature<"experimental-zbt", "HasStdExtZbt", "true",
+    : SubtargetFeature<"experimental-zbt0p93", "StdExtZbt", "RISCVExtensionVersion{0, 93}",
                        "'Zbt' (Ternary 'B' Instructions)">;
 def HasStdExtZbt : Predicate<"Subtarget->hasStdExtZbt()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbt),
@@ -151,7 +151,7 @@
                                       "RVC Hint Instructions">;
 
 def FeatureStdExtV
-    : SubtargetFeature<"experimental-v", "HasStdExtV", "true",
+    : SubtargetFeature<"experimental-v0p10", "StdExtV", "RISCVExtensionVersion{0, 10}",
                        "'V' (Vector Instructions)">;
 def HasStdExtV : Predicate<"Subtarget->hasStdExtV()">,
                            AssemblerPredicate<(all_of FeatureStdExtV),
@@ -161,7 +161,7 @@
 def HasVInstructionsAnyF : Predicate<"Subtarget->hasVInstructionsAnyF()">;
 
 def FeatureStdExtZvlsseg
-    : SubtargetFeature<"experimental-zvlsseg", "HasStdExtZvlsseg", "true",
+    : SubtargetFeature<"experimental-zvlsseg0p10", "StdExtZvlsseg", "RISCVExtensionVersion{0, 10}",
                        "'Zvlsseg' (Vector segment load/store instructions)",
                        [FeatureStdExtV]>;
 def HasStdExtZvlsseg : Predicate<"Subtarget->hasStdExtZvlsseg()">,
@@ -169,7 +169,7 @@
                                  "'Zvlsseg' (Vector segment load/store instructions)">;
 
 def FeatureStdExtZvamo
-    : SubtargetFeature<"experimental-zvamo", "HasStdExtZvamo", "true",
+    : SubtargetFeature<"experimental-zvamo0p10", "StdExtZvamo", "RISCVExtensionVersion{0, 10}",
                        "'Zvamo' (Vector AMO Operations)",
                        [FeatureStdExtV]>;
 def HasStdExtZvamo : Predicate<"Subtarget->hasStdExtZvamo()">,
@@ -189,7 +189,7 @@
 def RV64           : HwMode<"+64bit">;
 
 def FeatureRV32E
-    : SubtargetFeature<"e", "IsRV32E", "true",
+    : SubtargetFeature<"e1p9", "StdExtE", "RISCVExtensionVersion{1, 9}",
                        "Implements RV32E (provides 16 rather than 32 GPRs)">;
 def IsRV32E : Predicate<"Subtarget->isRV32E()">,
                         AssemblerPredicate<(all_of FeatureRV32E)>;
Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
===================================================================
--- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1990,7 +1990,7 @@
       return Error(Parser.getTok().getLoc(),
                    "unexpected token, expected end of statement");
 
-    setFeatureBits(RISCV::FeatureStdExtC, "c");
+    setFeatureBits(RISCV::FeatureStdExtC, "c2p0");
     return false;
   }
 
@@ -2002,7 +2002,7 @@
       return Error(Parser.getTok().getLoc(),
                    "unexpected token, expected end of statement");
 
-    clearFeatureBits(RISCV::FeatureStdExtC, "c");
+    clearFeatureBits(RISCV::FeatureStdExtC, "c2p0");
     return false;
   }
 
@@ -2154,7 +2154,7 @@
     auto &ISAInfo = *ParseResult;
 
     for (auto Feature : RISCVFeatureKV)
-      if (ISAInfo->hasExtension(Feature.Key))
+      if (ISAInfo->hasExtensionWithVersion(Feature.Key))
         setFeatureBits(Feature.Value, Feature.Key);
 
     if (ISAInfo->getXLen() == 32)
Index: llvm/lib/Support/RISCVISAInfo.cpp
===================================================================
--- llvm/lib/Support/RISCVISAInfo.cpp
+++ llvm/lib/Support/RISCVISAInfo.cpp
@@ -22,11 +22,6 @@
 using namespace llvm;
 
 namespace {
-/// Represents the major and version number components of a RISC-V extension
-struct RISCVExtensionVersion {
-  unsigned Major;
-  unsigned Minor;
-};
 
 struct RISCVSupportedExtension {
   const char *Name;
@@ -68,6 +63,11 @@
     {"zfh", RISCVExtensionVersion{0, 1}},
 };
 
+static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
+                                 unsigned &Minor, unsigned &ConsumeLength,
+                                 bool EnableExperimentalExtension,
+                                 bool ExperimentalExtensionVersionCheck);
+
 static bool stripExperimentalPrefix(StringRef &Ext) {
   return Ext.consume_front("experimental-");
 }
@@ -121,8 +121,8 @@
                                 unsigned MinorVersion) {
   RISCVExtensionInfo Ext;
   Ext.ExtName = ExtName.str();
-  Ext.MajorVersion = MajorVersion;
-  Ext.MinorVersion = MinorVersion;
+  Ext.Version.Major = MajorVersion;
+  Ext.Version.Minor = MinorVersion;
   Exts[ExtName.str()] = Ext;
 }
 
@@ -160,12 +160,23 @@
 }
 
 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
-  bool IsExperimental = stripExperimentalPrefix(Ext);
+  stripExperimentalPrefix(Ext);
 
-  if (IsExperimental)
-    return llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
-  else
-    return llvm::any_of(SupportedExtensions, FindByName(Ext));
+  auto Pos = findFirstNonVersionCharacter(Ext) + 1;
+  StringRef Name(Ext.substr(0, Pos));
+  StringRef Vers(Ext.substr(Pos));
+
+  unsigned Major, Minor, ConsumeLength;
+  if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
+                                   true, false)) {
+    consumeError(std::move(E));
+    return false;
+  }
+
+  if (!isSupportedExtension(Name, Major, Minor))
+    return false;
+
+  return true;
 }
 
 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
@@ -192,6 +203,18 @@
   return Exts.count(Ext.str()) != 0;
 }
 
+bool RISCVISAInfo::hasExtensionWithVersion(StringRef Ext) const {
+  stripExperimentalPrefix(Ext);
+
+  auto Pos = findFirstNonVersionCharacter(Ext) + 1;
+  StringRef Name(Ext.substr(0, Pos));
+
+  if (!isSupportedExtension(Name))
+    return false;
+
+  return Exts.count(Name.str()) != 0;
+}
+
 // Get the rank for single-letter extension, lower value meaning higher
 // priority.
 static int singleLetterExtensionRank(char Ext) {
@@ -274,26 +297,35 @@
   return LHS < RHS;
 }
 
-void RISCVISAInfo::toFeatures(
-    std::vector<StringRef> &Features,
-    std::function<StringRef(const Twine &)> StrAlloc) const {
+static std::string addVersionSuffix(Twine ExtName, unsigned Major, unsigned Minor) {
+ return (ExtName + Twine(Major) + "p" + Twine(Minor)).str();
+}
+
+void RISCVISAInfo::toFeatures(std::vector<std::string> &Features) const {
+
   for (auto &Ext : Exts) {
     StringRef ExtName = Ext.first;
+    auto Extension = Ext.second;
+    unsigned Major = Ext.second.Version.Major;
+    unsigned Minor = Ext.second.Version.Minor;
 
     if (ExtName == "i")
       continue;
 
     if (ExtName == "zvlsseg") {
-      Features.push_back("+experimental-v");
-      Features.push_back("+experimental-zvlsseg");
+      Features.push_back(addVersionSuffix("experimental-v", Major, Minor));
+      Features.push_back(
+          addVersionSuffix("experimental-zvlsseg", Major, Minor));
     } else if (ExtName == "zvamo") {
-      Features.push_back("+experimental-v");
-      Features.push_back("+experimental-zvlsseg");
-      Features.push_back("+experimental-zvamo");
+      Features.push_back(addVersionSuffix("experimental-v", Major, Minor));
+      Features.push_back(
+          addVersionSuffix("experimental-zvlsseg", Major, Minor));
+      Features.push_back(addVersionSuffix("experimental-zvamo", Major, Minor));
     } else if (isExperimentalExtension(ExtName)) {
-      Features.push_back(StrAlloc("+experimental-" + ExtName));
+      Features.push_back(
+          addVersionSuffix("experimental-" + ExtName, Major, Minor));
     } else {
-      Features.push_back(StrAlloc("+" + ExtName));
+      Features.push_back(addVersionSuffix(ExtName, Major, Minor));
     }
   }
 }
@@ -419,11 +451,15 @@
     bool Add = ExtName[0] == '+';
     ExtName = ExtName.drop_front(1); // Drop '+' or '-'
     Experimental = stripExperimentalPrefix(ExtName);
+    auto Pos = findFirstNonVersionCharacter(ExtName) + 1;
+    StringRef Name(ExtName.substr(0, Pos));
+    StringRef Vers(ExtName.substr(Pos));
+
     auto ExtensionInfos = Experimental
                               ? makeArrayRef(SupportedExperimentalExtensions)
                               : makeArrayRef(SupportedExtensions);
     auto ExtensionInfoIterator =
-        llvm::find_if(ExtensionInfos, FindByName(ExtName));
+        llvm::find_if(ExtensionInfos, FindByName(Name));
 
     // Not all features is related to ISA extension, like `relax` or
     // `save-restore`, skip those feature.
@@ -431,10 +467,10 @@
       continue;
 
     if (Add)
-      ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
+      ISAInfo->addExtension(Name, ExtensionInfoIterator->Version.Major,
                             ExtensionInfoIterator->Version.Minor);
     else
-      ISAInfo->Exts.erase(ExtName.str());
+      ISAInfo->Exts.erase(Name.str());
   }
 
   ISAInfo->updateImplication();
@@ -448,7 +484,8 @@
 
 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
-                              bool ExperimentalExtensionVersionCheck) {
+                              bool ExperimentalExtensionVersionCheck,
+                              bool IgnoreUnknownExtension) {
   // RISC-V ISA strings must be lowercase.
   if (llvm::any_of(Arch, isupper)) {
     return createStringError(errc::invalid_argument,
@@ -549,9 +586,10 @@
             "standard user-level extension not given in canonical order '%c'",
             C);
       }
-
-      return createStringError(errc::invalid_argument,
-                               "invalid standard user-level extension '%c'", C);
+      if (!IgnoreUnknownExtension)
+        return createStringError(errc::invalid_argument,
+                                 "invalid standard user-level extension '%c'",
+                                 C);
     }
 
     // Move to next char to prevent repeated letter.
@@ -563,18 +601,22 @@
       Next = std::string(std::next(I), E);
     if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor,
                                      ConsumeLength, EnableExperimentalExtension,
-                                     ExperimentalExtensionVersionCheck))
-      return std::move(E);
-
-    // The order is OK, then push it into features.
-    // TODO: Use version number when setting target features
-    // Currently LLVM supports only "mafdcbv".
-    StringRef SupportedStandardExtension = "mafdcbv";
-    if (SupportedStandardExtension.find(C) == StringRef::npos)
-      return createStringError(errc::invalid_argument,
-                               "unsupported standard user-level extension '%c'",
-                               C);
-    ISAInfo->addExtension(std::string(1, C), Major, Minor);
+                                     ExperimentalExtensionVersionCheck)) {
+      if (IgnoreUnknownExtension)
+        consumeError(std::move(E));
+      else
+        return std::move(E);
+    } else {
+      // The order is OK, then push it into features.
+      // TODO: Use version number when setting target features
+      // Currently LLVM supports only "mafdcbv".
+      StringRef SupportedStandardExtension = "mafdcbv";
+      if (SupportedStandardExtension.find(C) == StringRef::npos)
+        return createStringError(
+            errc::invalid_argument,
+            "unsupported standard user-level extension '%c'", C);
+      ISAInfo->addExtension(std::string(1, C), Major, Minor);
+    }
 
     // Consume full extension name and version, including any optional '_'
     // between this extension and the next
@@ -757,7 +799,7 @@
     StringRef ExtName = Ext.first;
     auto ExtInfo = Ext.second;
     Arch << LS << ExtName;
-    Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion;
+    Arch << ExtInfo.Version.Major << "p" << ExtInfo.Version.Minor;
   }
 
   return Arch.str();
Index: llvm/lib/Object/ELFObjectFile.cpp
===================================================================
--- llvm/lib/Object/ELFObjectFile.cpp
+++ llvm/lib/Object/ELFObjectFile.cpp
@@ -26,6 +26,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/RISCVAttributeParser.h"
 #include "llvm/Support/RISCVAttributes.h"
+#include "llvm/Support/RISCVISAInfo.h"
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
@@ -292,7 +293,7 @@
   unsigned PlatformFlags = getPlatformFlags();
 
   if (PlatformFlags & ELF::EF_RISCV_RVC) {
-    Features.AddFeature("c");
+    Features.AddFeature("c2p0");
   }
 
   // Add features according to the ELF attribute section.
@@ -306,38 +307,23 @@
 
   Optional<StringRef> Attr = Attributes.getAttributeString(RISCVAttrs::ARCH);
   if (Attr.hasValue()) {
-    // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)*
-    // Version string pattern is (major)p(minor). Major and minor are optional.
-    // For example, a version number could be 2p0, 2, or p92.
-    StringRef Arch = Attr.getValue();
-    if (Arch.consume_front("rv32"))
+    auto ParseResult =
+        llvm::RISCVISAInfo::parseArchString(Attr.getValue(), true, true, true);
+    if (!ParseResult)
+      return Features;
+
+    auto &ISAInfo = *ParseResult;
+
+    if (ISAInfo->getXLen() == 32)
       Features.AddFeature("64bit", false);
-    else if (Arch.consume_front("rv64"))
+    else if (ISAInfo->getXLen() == 64)
       Features.AddFeature("64bit");
 
-    while (!Arch.empty()) {
-      switch (Arch[0]) {
-      default:
-        break; // Ignore unexpected features.
-      case 'i':
-        Features.AddFeature("e", false);
-        break;
-      case 'd':
-        Features.AddFeature("f"); // D-ext will imply F-ext.
-        LLVM_FALLTHROUGH;
-      case 'e':
-      case 'm':
-      case 'a':
-      case 'f':
-      case 'c':
-        Features.AddFeature(Arch.take_front());
-        break;
-      }
-
-      // FIXME: Handle version numbers.
-      Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; });
-      Arch = Arch.drop_while([](char c) { return c == '_'; });
-    }
+    std::vector<std::string> ToFeatures;
+    ISAInfo->toFeatures(ToFeatures);
+
+    for (const auto &Feature : ToFeatures)
+      Features.AddFeature(Feature);
   }
 
   return Features;
Index: llvm/include/llvm/Support/RISCVISAInfo.h
===================================================================
--- llvm/include/llvm/Support/RISCVISAInfo.h
+++ llvm/include/llvm/Support/RISCVISAInfo.h
@@ -19,10 +19,29 @@
 #include <vector>
 
 namespace llvm {
+
+/// Represents the major and version number components of a RISC-V extension
+struct RISCVExtensionVersion {
+  unsigned Major;
+  unsigned Minor;
+
+  bool operator==(const RISCVExtensionVersion &Version) const {
+    return Major == Version.Major && Minor == Version.Minor;
+  }
+
+  bool operator!=(const RISCVExtensionVersion &Version) const {
+    return !operator==(Version);
+  }
+
+  bool operator<(const RISCVExtensionVersion &Version) const {
+    return (Major < Version.Major) ||
+           (Major == Version.Major && Minor < Version.Minor);
+  }
+};
+
 struct RISCVExtensionInfo {
   std::string ExtName;
-  unsigned MajorVersion;
-  unsigned MinorVersion;
+  RISCVExtensionVersion Version;
 };
 
 class RISCVISAInfo {
@@ -47,15 +66,15 @@
   /// Parse RISCV ISA info from arch string.
   static llvm::Expected<std::unique_ptr<RISCVISAInfo>>
   parseArchString(StringRef Arch, bool EnableExperimentalExtension,
-                  bool ExperimentalExtensionVersionCheck = true);
+                  bool ExperimentalExtensionVersionCheck = true,
+                  bool IgnoreUnknownExtension = false);
 
   /// Parse RISCV ISA info from feature vector.
   static llvm::Expected<std::unique_ptr<RISCVISAInfo>>
   parseFeatures(unsigned XLen, const std::vector<std::string> &Features);
 
   /// Convert RISCV ISA info to a feature vector.
-  void toFeatures(std::vector<StringRef> &Features,
-                  std::function<StringRef(const Twine &)> StrAlloc) const;
+  void toFeatures(std::vector<std::string> &Features) const;
 
   const OrderedExtensionMap &getExtensions() const { return Exts; };
 
@@ -63,6 +82,7 @@
   unsigned getFLen() const { return FLen; };
 
   bool hasExtension(StringRef Ext) const;
+  bool hasExtensionWithVersion(StringRef Ext) const;
   std::string toString() const;
 
   static bool isSupportedExtensionFeature(StringRef Ext);
Index: clang/utils/TableGen/RISCVVEmitter.cpp
===================================================================
--- clang/utils/TableGen/RISCVVEmitter.cpp
+++ clang/utils/TableGen/RISCVVEmitter.cpp
@@ -1021,7 +1021,7 @@
 
   OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
   OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
-        "ATTRS, \"experimental-v\")\n";
+        "ATTRS, \"experimental-v0p10\")\n";
   OS << "#endif\n";
   for (auto &Def : Defs) {
     auto P =
Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -41,8 +41,12 @@
     return false;
   }
 
-  (*ISAInfo)->toFeatures(
-      Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); });
+  std::vector<std::string> ToFeatures;
+  (*ISAInfo)->toFeatures(ToFeatures);
+
+  for (const auto &Feature : ToFeatures)
+    Features.push_back(Args.MakeArgString("+" + Feature));
+
   return true;
 }
 
Index: clang/lib/Basic/Targets/RISCV.cpp
===================================================================
--- clang/lib/Basic/Targets/RISCV.cpp
+++ clang/lib/Basic/Targets/RISCV.cpp
@@ -150,7 +150,7 @@
     auto ExtName = Extension.first;
     auto ExtInfo = Extension.second;
     unsigned Version =
-        (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000);
+        (ExtInfo.Version.Major * 1000000) + (ExtInfo.Version.Minor * 1000);
 
     Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
   }
@@ -223,8 +223,9 @@
   if (Result.hasValue())
     return Result.getValue();
 
-  if (ISAInfo->isSupportedExtensionFeature(Feature))
-    return ISAInfo->hasExtension(Feature);
+  if (ISAInfo->isSupportedExtensionFeature(Feature)) {
+    return ISAInfo->hasExtensionWithVersion(Feature);
+  }
 
   return false;
 }
Index: clang/include/clang/Basic/BuiltinsRISCV.def
===================================================================
--- clang/include/clang/Basic/BuiltinsRISCV.def
+++ clang/include/clang/Basic/BuiltinsRISCV.def
@@ -16,46 +16,46 @@
 #endif
 
 // Zbb extension
-TARGET_BUILTIN(__builtin_riscv_orc_b_32, "ZiZi", "nc", "experimental-zbb")
-TARGET_BUILTIN(__builtin_riscv_orc_b_64, "WiWi", "nc", "experimental-zbb,64bit")
+TARGET_BUILTIN(__builtin_riscv_orc_b_32, "ZiZi", "nc", "experimental-zbb1p0")
+TARGET_BUILTIN(__builtin_riscv_orc_b_64, "WiWi", "nc", "experimental-zbb1p0,64bit")
 
 // Zbc extension
-TARGET_BUILTIN(__builtin_riscv_clmul, "LiLiLi", "nc", "experimental-zbc")
-TARGET_BUILTIN(__builtin_riscv_clmulh, "LiLiLi", "nc", "experimental-zbc")
-TARGET_BUILTIN(__builtin_riscv_clmulr, "LiLiLi", "nc", "experimental-zbc")
+TARGET_BUILTIN(__builtin_riscv_clmul, "LiLiLi", "nc", "experimental-zbc1p0")
+TARGET_BUILTIN(__builtin_riscv_clmulh, "LiLiLi", "nc", "experimental-zbc1p0")
+TARGET_BUILTIN(__builtin_riscv_clmulr, "LiLiLi", "nc", "experimental-zbc1p0")
 
 // Zbe extension
-TARGET_BUILTIN(__builtin_riscv_bcompress_32, "ZiZiZi", "nc", "experimental-zbe")
+TARGET_BUILTIN(__builtin_riscv_bcompress_32, "ZiZiZi", "nc", "experimental-zbe0p93")
 TARGET_BUILTIN(__builtin_riscv_bcompress_64, "WiWiWi", "nc",
-               "experimental-zbe,64bit")
+               "experimental-zbe0p93,64bit")
 TARGET_BUILTIN(__builtin_riscv_bdecompress_32, "ZiZiZi", "nc",
-               "experimental-zbe")
+               "experimental-zbe0p93")
 TARGET_BUILTIN(__builtin_riscv_bdecompress_64, "WiWiWi", "nc",
-               "experimental-zbe,64bit")
+               "experimental-zbe0p93,64bit")
 
 // Zbp extension
-TARGET_BUILTIN(__builtin_riscv_grev_32, "ZiZiZi", "nc", "experimental-zbp")
-TARGET_BUILTIN(__builtin_riscv_grev_64, "WiWiWi", "nc", "experimental-zbp,64bit")
-TARGET_BUILTIN(__builtin_riscv_gorc_32, "ZiZiZi", "nc", "experimental-zbp")
-TARGET_BUILTIN(__builtin_riscv_gorc_64, "WiWiWi", "nc", "experimental-zbp,64bit")
-TARGET_BUILTIN(__builtin_riscv_shfl_32, "ZiZiZi", "nc", "experimental-zbp")
-TARGET_BUILTIN(__builtin_riscv_shfl_64, "WiWiWi", "nc", "experimental-zbp,64bit")
-TARGET_BUILTIN(__builtin_riscv_unshfl_32, "ZiZiZi", "nc", "experimental-zbp")
-TARGET_BUILTIN(__builtin_riscv_unshfl_64, "WiWiWi", "nc", "experimental-zbp,64bit")
-TARGET_BUILTIN(__builtin_riscv_xperm_n, "LiLiLi", "nc", "experimental-zbp")
-TARGET_BUILTIN(__builtin_riscv_xperm_b, "LiLiLi", "nc", "experimental-zbp")
-TARGET_BUILTIN(__builtin_riscv_xperm_h, "LiLiLi", "nc", "experimental-zbp")
-TARGET_BUILTIN(__builtin_riscv_xperm_w, "WiWiWi", "nc", "experimental-zbp,64bit")
+TARGET_BUILTIN(__builtin_riscv_grev_32, "ZiZiZi", "nc", "experimental-zbp0p93")
+TARGET_BUILTIN(__builtin_riscv_grev_64, "WiWiWi", "nc", "experimental-zbp0p93,64bit")
+TARGET_BUILTIN(__builtin_riscv_gorc_32, "ZiZiZi", "nc", "experimental-zbp0p93")
+TARGET_BUILTIN(__builtin_riscv_gorc_64, "WiWiWi", "nc", "experimental-zbp0p93,64bit")
+TARGET_BUILTIN(__builtin_riscv_shfl_32, "ZiZiZi", "nc", "experimental-zbp0p93")
+TARGET_BUILTIN(__builtin_riscv_shfl_64, "WiWiWi", "nc", "experimental-zbp0p93,64bit")
+TARGET_BUILTIN(__builtin_riscv_unshfl_32, "ZiZiZi", "nc", "experimental-zbp0p93")
+TARGET_BUILTIN(__builtin_riscv_unshfl_64, "WiWiWi", "nc", "experimental-zbp0p93,64bit")
+TARGET_BUILTIN(__builtin_riscv_xperm_n, "LiLiLi", "nc", "experimental-zbp0p93")
+TARGET_BUILTIN(__builtin_riscv_xperm_b, "LiLiLi", "nc", "experimental-zbp0p93")
+TARGET_BUILTIN(__builtin_riscv_xperm_h, "LiLiLi", "nc", "experimental-zbp0p93")
+TARGET_BUILTIN(__builtin_riscv_xperm_w, "WiWiWi", "nc", "experimental-zbp0p93,64bit")
 
 // Zbr extension
-TARGET_BUILTIN(__builtin_riscv_crc32_b, "LiLi", "nc", "experimental-zbr")
-TARGET_BUILTIN(__builtin_riscv_crc32_h, "LiLi", "nc", "experimental-zbr")
-TARGET_BUILTIN(__builtin_riscv_crc32_w, "LiLi", "nc", "experimental-zbr")
-TARGET_BUILTIN(__builtin_riscv_crc32c_b, "LiLi", "nc", "experimental-zbr")
-TARGET_BUILTIN(__builtin_riscv_crc32c_h, "LiLi", "nc", "experimental-zbr")
-TARGET_BUILTIN(__builtin_riscv_crc32c_w, "LiLi", "nc", "experimental-zbr")
-TARGET_BUILTIN(__builtin_riscv_crc32_d, "LiLi", "nc", "experimental-zbr")
-TARGET_BUILTIN(__builtin_riscv_crc32c_d, "LiLi", "nc", "experimental-zbr")
+TARGET_BUILTIN(__builtin_riscv_crc32_b, "LiLi", "nc", "experimental-zbr0p93")
+TARGET_BUILTIN(__builtin_riscv_crc32_h, "LiLi", "nc", "experimental-zbr0p93")
+TARGET_BUILTIN(__builtin_riscv_crc32_w, "LiLi", "nc", "experimental-zbr0p93")
+TARGET_BUILTIN(__builtin_riscv_crc32c_b, "LiLi", "nc", "experimental-zbr0p93")
+TARGET_BUILTIN(__builtin_riscv_crc32c_h, "LiLi", "nc", "experimental-zbr0p93")
+TARGET_BUILTIN(__builtin_riscv_crc32c_w, "LiLi", "nc", "experimental-zbr0p93")
+TARGET_BUILTIN(__builtin_riscv_crc32_d, "LiLi", "nc", "experimental-zbr0p93")
+TARGET_BUILTIN(__builtin_riscv_crc32c_d, "LiLi", "nc", "experimental-zbr0p93")
 
 #undef BUILTIN
 #undef TARGET_BUILTIN
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D115923: [RISCV][Don't C... Zixuan Wu via Phabricator via cfe-commits

Reply via email to