zixuan-wu updated this revision to Diff 396148.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D115921/new/

https://reviews.llvm.org/D115921

Files:
  clang/lib/Basic/Targets/RISCV.cpp
  clang/lib/Driver/ToolChains/Arch/RISCV.cpp
  clang/test/Driver/riscv-arch-version.c
  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
  llvm/test/CodeGen/RISCV/attributes-version.ll
  llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test

Index: llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test
===================================================================
--- llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test
+++ 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_x1p0_m2p0" arch feature. "x1p0" is an
+## The object file has the "rv32i2p0_y1p0_m2p0" arch feature. "y1p0" 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 @@
     Content: 3385C502
   - Name:    .riscv.attributes
     Type:    SHT_RISCV_ATTRIBUTES
-## The content is the encoding of the arch feature "rv32i2p0_x1p0_m2p0"
-    Content: 412300000072697363760001190000000572763332693270305F783170305F6D32703000
+## The content is the encoding of the arch feature "rv32i2p0_y1p0_m2p0"
+    Content: 412300000072697363760001190000000572763332693270305F793170305F6D32703000
Index: llvm/test/CodeGen/RISCV/attributes-version.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/RISCV/attributes-version.ll
@@ -0,0 +1,81 @@
+; Generate ELF attributes from llc.
+
+; RUN: llc -mtriple=riscv32 -mattr=+m %s -o - | FileCheck --check-prefix=RV32M %s
+; RUN: llc -mtriple=riscv32 -mattr=+a %s -o - | FileCheck --check-prefix=RV32A %s
+; RUN: llc -mtriple=riscv32 -mattr=+f %s -o - | FileCheck --check-prefix=RV32F %s
+; RUN: llc -mtriple=riscv32 -mattr=+d %s -o - | FileCheck --check-prefix=RV32D %s
+; RUN: llc -mtriple=riscv32 -mattr=+c %s -o - | FileCheck --check-prefix=RV32C %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfhmin %s -o - | FileCheck --check-prefix=RV32ZFHMIN %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfh %s -o - | FileCheck --check-prefix=RV32ZFH %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zba %s -o - | FileCheck --check-prefix=RV32ZBA %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbb %s -o - | FileCheck --check-prefix=RV32ZBB %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbc %s -o - | FileCheck --check-prefix=RV32ZBC %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbe %s -o - | FileCheck --check-prefix=RV32ZBE %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbf %s -o - | FileCheck --check-prefix=RV32ZBF %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbm %s -o - | FileCheck --check-prefix=RV32ZBM %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp %s -o - | FileCheck --check-prefix=RV32ZBP %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbr %s -o - | FileCheck --check-prefix=RV32ZBR %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbs %s -o - | FileCheck --check-prefix=RV32ZBS %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbt %s -o - | FileCheck --check-prefix=RV32ZBT %s
+
+
+; RV32M: .attribute 5, "rv32i2p0_m2p0"
+; RV32A: .attribute 5, "rv32i2p0_a2p0"
+; RV32F: .attribute 5, "rv32i2p0_f2p0"
+; RV32D: .attribute 5, "rv32i2p0_f2p0_d2p0"
+; RV32C: .attribute 5, "rv32i2p0_c2p0"
+; RV32V: .attribute 5, "rv32i2p0_v0p10_zvlsseg0p10"
+; RV32ZFHMIN: .attribute 5, "rv32i2p0_f2p0_zfhmin0p1"
+; RV32ZFH: .attribute 5, "rv32i2p0_f2p0_zfh0p1_zfhmin0p1"
+; RV32ZBA: .attribute 5, "rv32i2p0_zba1p0"
+; RV32ZBB: .attribute 5, "rv32i2p0_zbb1p0"
+; RV32ZBC: .attribute 5, "rv32i2p0_zbc1p0"
+; RV32ZBE: .attribute 5, "rv32i2p0_zbe0p93"
+; RV32ZBF: .attribute 5, "rv32i2p0_zbf0p93"
+; RV32ZBM: .attribute 5, "rv32i2p0_zbm0p93"
+; RV32ZBP: .attribute 5, "rv32i2p0_zbp0p93"
+; RV32ZBR: .attribute 5, "rv32i2p0_zbr0p93"
+; RV32ZBS: .attribute 5, "rv32i2p0_zbs1p0"
+; RV32ZBT: .attribute 5, "rv32i2p0_zbt0p93"
+
+
+; RUN: llc -mtriple=riscv32 -mattr=+m0p7 < %s 2>&1 | FileCheck --check-prefix=RV32M0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+a0p7 < %s 2>&1 | FileCheck --check-prefix=RV32A0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+f0p7 < %s 2>&1 | FileCheck --check-prefix=RV32F0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+d0p7 < %s 2>&1 | FileCheck --check-prefix=RV32D0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+c0p7 < %s 2>&1 | FileCheck --check-prefix=RV32C0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfhmin0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZFHMIN0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfh0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZFH0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zba0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBA0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbb0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBB0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbc0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBC0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbe0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBE0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbf0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBF0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbm0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBM0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbp0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBP0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbr0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBR0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbs0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBS0P7 %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbt0p7 < %s 2>&1 | FileCheck --check-prefix=RV32ZBT0P7 %s
+
+; RV32M0P7: '+m0p7' is not a recognized feature for this target
+; RV32A0P7: '+a0p7' is not a recognized feature for this target
+; RV32F0P7: '+f0p7' is not a recognized feature for this target
+; RV32D0P7: '+d0p7' is not a recognized feature for this target
+; RV32C0P7: '+c0p7' is not a recognized feature for this target
+; RV32ZFHMIN0P7: '+experimental-zfhmin0p7' is not a recognized feature for this target
+; RV32ZFH0P7: '+experimental-zfh0p7' is not a recognized feature for this target
+; RV32ZBA0P7: '+experimental-zba0p7' is not a recognized feature for this target
+; RV32ZBB0P7: '+experimental-zbb0p7' is not a recognized feature for this target
+; RV32ZBC0P7: '+experimental-zbc0p7' is not a recognized feature for this target
+; RV32ZBE0P7: '+experimental-zbe0p7' is not a recognized feature for this target
+; RV32ZBF0P7: '+experimental-zbf0p7' is not a recognized feature for this target
+; RV32ZBM0P7: '+experimental-zbm0p7' is not a recognized feature for this target
+; RV32ZBP0P7: '+experimental-zbp0p7' is not a recognized feature for this target
+; RV32ZBR0P7: '+experimental-zbr0p7' is not a recognized feature for this target
+; RV32ZBS0P7: '+experimental-zbs0p7' is not a recognized feature for this target
+; RV32ZBT0P7: '+experimental-zbt0p7' is not a recognized feature for this target
+
+define i32 @addi(i32 %a) {
+  %1 = add i32 %a, 1
+  ret i32 %1
+}
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,27 +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 HasStdExtZfhmin = false;
-  bool HasStdExtZfh = false;
+  RISCVExtensionVersion StdExtM;
+  RISCVExtensionVersion StdExtA;
+  RISCVExtensionVersion StdExtF;
+  RISCVExtensionVersion StdExtD;
+  RISCVExtensionVersion StdExtC;
+  RISCVExtensionVersion StdExtZba;
+  RISCVExtensionVersion StdExtZbb;
+  RISCVExtensionVersion StdExtZbc;
+  RISCVExtensionVersion StdExtZbe;
+  RISCVExtensionVersion StdExtZbf;
+  RISCVExtensionVersion StdExtZbm;
+  RISCVExtensionVersion StdExtZbp;
+  RISCVExtensionVersion StdExtZbr;
+  RISCVExtensionVersion StdExtZbs;
+  RISCVExtensionVersion StdExtZbt;
+  RISCVExtensionVersion StdExtV;
+  RISCVExtensionVersion StdExtZvlsseg;
+  RISCVExtensionVersion StdExtZvamo;
+  RISCVExtensionVersion StdExtZfhmin;
+  RISCVExtensionVersion StdExtZfh;
+  RISCVExtensionVersion StdExtE;
   bool HasRV64 = false;
-  bool IsRV32E = false;
   bool EnableLinkerRelax = false;
   bool EnableRVCHintInstrs = true;
   bool EnableSaveRestore = false;
@@ -100,27 +102,27 @@
     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 hasStdExtZfhmin() const { return HasStdExtZfhmin; }
-  bool hasStdExtZfh() const { return HasStdExtZfh; }
+  bool hasStdExtM() const { return StdExtM; }
+  bool hasStdExtA() const { return StdExtA; }
+  bool hasStdExtF() const { return StdExtF; }
+  bool hasStdExtD() const { return StdExtD; }
+  bool hasStdExtC() const { return StdExtC; }
+  bool hasStdExtZba() const { return StdExtZba; }
+  bool hasStdExtZbb() const { return StdExtZbb; }
+  bool hasStdExtZbc() const { return StdExtZbc; }
+  bool hasStdExtZbe() const { return StdExtZbe; }
+  bool hasStdExtZbf() const { return StdExtZbf; }
+  bool hasStdExtZbm() const { return StdExtZbm; }
+  bool hasStdExtZbp() const { return StdExtZbp; }
+  bool hasStdExtZbr() const { return StdExtZbr; }
+  bool hasStdExtZbs() const { return StdExtZbs; }
+  bool hasStdExtZbt() const { return StdExtZbt; }
+  bool hasStdExtV() const { return StdExtV; }
+  bool hasStdExtZvlsseg() const { return StdExtZvlsseg; }
+  bool hasStdExtZfhmin() const { return StdExtZfhmin; }
+  bool hasStdExtZfh() const { return StdExtZfh; }
   bool is64Bit() const { return HasRV64; }
-  bool isRV32E() const { return IsRV32E; }
+  bool isRV32E() const { return StdExtE; }
   bool enableLinkerRelax() const { return EnableLinkerRelax; }
   bool enableRVCHintInstrs() const { return EnableRVCHintInstrs; }
   bool enableSaveRestore() const { return EnableSaveRestore; }
@@ -133,11 +135,11 @@
   }
 
   // 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; }
+  bool hasVInstructionsI64() const { return StdExtV; }
+  bool hasVInstructionsF16() const { return StdExtV && hasStdExtZfh(); }
+  bool hasVInstructionsF32() const { return StdExtV && hasStdExtF(); }
+  bool hasVInstructionsF64() const { return StdExtV && 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<"m", "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<"a", "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<"f", "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<"d", "StdExtD", "RISCVExtensionVersion{2, 0}",
                        "'D' (Double-Precision Floating-Point)",
                        [FeatureStdExtF]>;
 def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">,
@@ -42,7 +42,8 @@
                            "'D' (Double-Precision Floating-Point)">;
 
 def FeatureStdExtZfhmin
-    : SubtargetFeature<"experimental-zfhmin", "HasStdExtZfhmin", "true",
+    : SubtargetFeature<"experimental-zfhmin", "StdExtZfhmin",
+                       "RISCVExtensionVersion{0, 1}",
                        "'Zfhmin' (Half-Precision Floating-Point Minimal)",
                        [FeatureStdExtF]>;
 def HasStdExtZfhmin : Predicate<"Subtarget->hasStdExtZfhmin()">,
@@ -50,7 +51,8 @@
                              "'Zfhmin' (Half-Precision Floating-Point Minimal)">;
 
 def FeatureStdExtZfh
-    : SubtargetFeature<"experimental-zfh", "HasStdExtZfh", "true",
+    : SubtargetFeature<"experimental-zfh", "StdExtZfh",
+                       "RISCVExtensionVersion{0, 1}",
                        "'Zfh' (Half-Precision Floating-Point)",
                        [FeatureStdExtZfhmin, FeatureStdExtF]>;
 def HasStdExtZfh : Predicate<"Subtarget->hasStdExtZfh()">,
@@ -58,14 +60,15 @@
                              "'Zfh' (Half-Precision Floating-Point)">;
 
 def FeatureStdExtC
-    : SubtargetFeature<"c", "HasStdExtC", "true",
+    : SubtargetFeature<"c", "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-zba", "StdExtZba",
+                       "RISCVExtensionVersion{1, 0}",
                        "'Zba' (Address calculation 'B' Instructions)">;
 def HasStdExtZba : Predicate<"Subtarget->hasStdExtZba()">,
                              AssemblerPredicate<(all_of FeatureStdExtZba),
@@ -73,63 +76,72 @@
 def NotHasStdExtZba : Predicate<"!Subtarget->hasStdExtZba()">;
 
 def FeatureStdExtZbb
-    : SubtargetFeature<"experimental-zbb", "HasStdExtZbb", "true",
+    : SubtargetFeature<"experimental-zbb", "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-zbc", "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-zbe", "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-zbf", "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-zbm", "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-zbp", "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-zbr", "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-zbs", "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-zbt", "StdExtZbt",
+                       "RISCVExtensionVersion{0, 93}",
                        "'Zbt' (Ternary 'B' Instructions)">;
 def HasStdExtZbt : Predicate<"Subtarget->hasStdExtZbt()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbt),
@@ -151,22 +163,26 @@
                                       "RVC Hint Instructions">;
 
 def FeatureStdExtV
-    : SubtargetFeature<"experimental-v", "HasStdExtV", "true",
+    : SubtargetFeature<"experimental-v", "StdExtV",
+                       "RISCVExtensionVersion{0, 10}",
                        "'V' (Vector Instructions)">;
-def HasStdExtV : Predicate<"Subtarget->hasStdExtV()">,
-                           AssemblerPredicate<(all_of FeatureStdExtV),
-                           "'V' (Vector Instructions)">;
+def HasStdExtV
+    : Predicate<"Subtarget->hasStdExtV()">,
+                 AssemblerPredicate<(all_of FeatureStdExtV),
+                 "'V' (Vector Instructions)">;
 
 def HasVInstructions    : Predicate<"Subtarget->hasVInstructions()">;
 def HasVInstructionsAnyF : Predicate<"Subtarget->hasVInstructionsAnyF()">;
 
 def FeatureStdExtZvlsseg
-    : SubtargetFeature<"experimental-zvlsseg", "HasStdExtZvlsseg", "true",
+    : SubtargetFeature<"experimental-zvlsseg", "StdExtZvlsseg",
+                       "RISCVExtensionVersion{0, 10}",
                        "'Zvlsseg' (Vector segment load/store instructions)",
                        [FeatureStdExtV]>;
-def HasStdExtZvlsseg : Predicate<"Subtarget->hasStdExtZvlsseg()">,
-                                 AssemblerPredicate<(all_of FeatureStdExtZvlsseg),
-                                 "'Zvlsseg' (Vector segment load/store instructions)">;
+def HasStdExtZvlsseg
+    : Predicate<"Subtarget->hasStdExtZvlsseg()">,
+                 AssemblerPredicate<(all_of FeatureStdExtZvlsseg),
+                 "'Zvlsseg' (Vector segment load/store instructions)">;
 
 def Feature64Bit
     : SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">;
@@ -181,7 +197,7 @@
 def RV64           : HwMode<"+64bit">;
 
 def FeatureRV32E
-    : SubtargetFeature<"e", "IsRV32E", "true",
+    : SubtargetFeature<"e", "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
@@ -2153,9 +2153,10 @@
     }
     auto &ISAInfo = *ParseResult;
 
-    for (auto Feature : RISCVFeatureKV)
-      if (ISAInfo->hasExtension(Feature.Key))
+    for (auto Feature : RISCVFeatureKV) {
+      if (ISAInfo->hasExtensionWithVersion(Feature.Key))
         setFeatureBits(Feature.Value, Feature.Key);
+    }
 
     if (ISAInfo->getXLen() == 32)
       clearFeatureBits(RISCV::Feature64Bit, "64bit");
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;
@@ -50,6 +45,7 @@
 
 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
     {"v", RISCVExtensionVersion{0, 10}},
+    //{"v", RISCVExtensionVersion{0, 7}},
     {"zba", RISCVExtensionVersion{1, 0}},
     {"zbb", RISCVExtensionVersion{1, 0}},
     {"zbc", RISCVExtensionVersion{1, 0}},
@@ -62,11 +58,17 @@
     {"zbt", RISCVExtensionVersion{0, 93}},
 
     {"zvlsseg", RISCVExtensionVersion{0, 10}},
+    //{"zvlsseg", RISCVExtensionVersion{0, 7}},
 
     {"zfhmin", RISCVExtensionVersion{0, 1}},
     {"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-");
 }
@@ -120,8 +122,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;
 }
 
@@ -149,22 +151,47 @@
   return StringRef();
 }
 
-static Optional<RISCVExtensionVersion> isExperimentalExtension(StringRef Ext) {
-  auto ExtIterator =
-      llvm::find_if(SupportedExperimentalExtensions, FindByName(Ext));
-  if (ExtIterator == std::end(SupportedExperimentalExtensions))
-    return None;
+static std::vector<RISCVExtensionVersion>
+getExperimentalExtensionVersions(StringRef Ext) {
+  std::vector<RISCVExtensionVersion> Result;
 
-  return ExtIterator->Version;
+  for (auto &Extension : SupportedExperimentalExtensions) {
+    if (Extension.Name == Ext)
+      Result.push_back(Extension.Version);
+  }
+
+  return Result;
 }
 
-bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
-  bool IsExperimental = stripExperimentalPrefix(Ext);
+Optional<RISCVExtensionInfo>
+RISCVISAInfo::isSupportedExtensionFeature(StringRef 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 (Vers.empty()) {
+    auto Version = findDefaultVersion(Name);
+    if (!Version)
+      return None;
+
+    Major = Version->Major;
+    Minor = Version->Minor;
+
+  } else if (auto E = getExtensionVersion(Name, Vers, Major, Minor,
+                                          ConsumeLength, true, false)) {
+    // Not all features is related to ISA extension, like `relax` or
+    // `save-restore`, skip those feature.
+    consumeError(std::move(E));
+    return None;
+  }
+
+  if (!isSupportedExtension(Name, Major, Minor))
+    return None;
+
+  return RISCVExtensionInfo{Name.str(), {Major, Minor}};
 }
 
 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
@@ -191,6 +218,20 @@
   return Exts.count(Ext.str()) != 0;
 }
 
+bool RISCVISAInfo::hasExtensionWithVersion(StringRef Ext) const {
+  auto Info = isSupportedExtensionFeature(Ext);
+  if (!Info)
+    return false;
+
+  auto ExtInfoIt = Exts.find(Info->ExtName);
+
+  if (ExtInfoIt == Exts.end())
+    return false;
+
+  return ExtInfoIt->second.Version.Major == Info->Version.Major &&
+         ExtInfoIt->second.Version.Minor == Info->Version.Minor;
+}
+
 // Get the rank for single-letter extension, lower value meaning higher
 // priority.
 static int singleLetterExtensionRank(char Ext) {
@@ -273,22 +314,35 @@
   return LHS < RHS;
 }
 
-void RISCVISAInfo::toFeatures(
-    std::vector<StringRef> &Features,
-    std::function<StringRef(const Twine &)> StrAlloc) const {
+static std::string addVersionSuffix(StringRef Suffix, StringRef ExtName,
+                                    unsigned Major, unsigned Minor) {
+  if (auto DefaultVersion = findDefaultVersion(ExtName))
+    if (DefaultVersion->Major == Major && DefaultVersion->Minor == Minor)
+      return (Twine(Suffix) + ExtName).str();
+
+  return (Suffix + 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");
-    } else if (isExperimentalExtension(ExtName)) {
-      Features.push_back(StrAlloc("+experimental-" + ExtName));
+      Features.push_back(addVersionSuffix("experimental-", "v", Major, Minor));
+      Features.push_back(
+          addVersionSuffix("experimental-", "zvlsseg", Major, Minor));
+    } else if (!getExperimentalExtensionVersions(ExtName).empty()) {
+      Features.push_back(
+          addVersionSuffix("experimental-", ExtName, Major, Minor));
     } else {
-      Features.push_back(StrAlloc("+" + ExtName));
+      Features.push_back(addVersionSuffix("", ExtName, Major, Minor));
     }
   }
 }
@@ -346,7 +400,8 @@
   }
 
   // If experimental extension, require use of current version number number
-  if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
+  auto ExperimentalExtension = getExperimentalExtensionVersions(Ext);
+  if (!ExperimentalExtension.empty()) {
     if (!EnableExperimentalExtension) {
       std::string Error = "requires '-menable-experimental-extensions' for "
                           "experimental extension '" +
@@ -362,18 +417,27 @@
       return createStringError(errc::invalid_argument, Error);
     }
 
-    auto SupportedVers = *ExperimentalExtension;
-    if (ExperimentalExtensionVersionCheck &&
-        (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
-      std::string Error = "unsupported version number " + MajorStr.str();
-      if (!MinorStr.empty())
-        Error += "." + MinorStr.str();
-      Error += " for experimental extension '" + Ext.str() +
-               "'(this compiler supports " + utostr(SupportedVers.Major) + "." +
-               utostr(SupportedVers.Minor) + ")";
-      return createStringError(errc::invalid_argument, Error);
+    for (auto Version : ExperimentalExtension) {
+      if (Major == Version.Major && Minor == Version.Minor)
+        return Error::success();
     }
-    return Error::success();
+
+    if (!ExperimentalExtensionVersionCheck)
+      return Error::success();
+
+    std::string Error = "unsupported version number " + MajorStr.str();
+    if (!MinorStr.empty())
+      Error += "." + MinorStr.str();
+    Error += " for experimental extension '" + Ext.str() +
+             "'(this compiler supports ";
+
+    ListSeparator LS;
+    for (auto Version : ExperimentalExtension) {
+      Error += LS;
+      Error += (utostr(Version.Major) + "." + utostr(Version.Minor));
+    }
+    Error += ")";
+    return createStringError(errc::invalid_argument, Error);
   }
 
   // Exception rule for `g`, we don't have clear version scheme for that on
@@ -409,27 +473,19 @@
 
   for (auto &Feature : Features) {
     StringRef ExtName = Feature;
-    bool Experimental = false;
     assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
     bool Add = ExtName[0] == '+';
     ExtName = ExtName.drop_front(1); // Drop '+' or '-'
-    Experimental = stripExperimentalPrefix(ExtName);
-    auto ExtensionInfos = Experimental
-                              ? makeArrayRef(SupportedExperimentalExtensions)
-                              : makeArrayRef(SupportedExtensions);
-    auto ExtensionInfoIterator =
-        llvm::find_if(ExtensionInfos, FindByName(ExtName));
 
-    // Not all features is related to ISA extension, like `relax` or
-    // `save-restore`, skip those feature.
-    if (ExtensionInfoIterator == ExtensionInfos.end())
+    auto Info = isSupportedExtensionFeature(ExtName);
+    if (!Info)
       continue;
 
     if (Add)
-      ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
-                            ExtensionInfoIterator->Version.Minor);
+      ISAInfo->addExtension(Info->ExtName, Info->Version.Major,
+                            Info->Version.Minor);
     else
-      ISAInfo->Exts.erase(ExtName.str());
+      ISAInfo->Exts.erase(Info->ExtName);
   }
 
   ISAInfo->updateImplication();
@@ -443,7 +499,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,
@@ -544,9 +601,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.
@@ -558,18 +616,23 @@
       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)
+        ISAInfo->addExtension(std::string(1, C), Major, Minor);
+      else if (!IgnoreUnknownExtension)
+        return createStringError(
+            errc::invalid_argument,
+            "unsupported standard user-level extension '%c'", C);
+    }
 
     // Consume full extension name and version, including any optional '_'
     // between this extension and the next
@@ -724,10 +787,9 @@
   for (auto &Ext : Exts) {
     auto I = llvm::lower_bound(ImpliedExts, Ext.first);
     if (I != std::end(ImpliedExts) && I->Name == Ext.first) {
-      for (auto &ImpliedExt : I->Exts) {
-        auto Version = findDefaultVersion(ImpliedExt);
-        addExtension(ImpliedExt, Version->Major, Version->Minor);
-      }
+      for (auto &ImpliedExt : I->Exts)
+        addExtension(ImpliedExt, Ext.second.Version.Major,
+                     Ext.second.Version.Minor);
     }
   }
 }
@@ -752,7 +814,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>
@@ -309,35 +310,27 @@
     // 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 == '_'; });
+    if (PlatformFlags & ELF::EF_RISCV_RVC) {
+      Features.AddFeature("c", false);
     }
+
+    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,34 @@
 #include <vector>
 
 namespace llvm {
+
+/// Represents the major and version number components of a RISC-V extension
+struct RISCVExtensionVersion {
+  unsigned Major;
+  unsigned Minor;
+
+  RISCVExtensionVersion() : Major(0), Minor(0) {}
+  RISCVExtensionVersion(unsigned Maj, unsigned Min) : Major(Maj), Minor(Min) {}
+
+  bool operator==(const RISCVExtensionVersion &Version) const {
+    return Major == Version.Major && Minor == Version.Minor;
+  }
+
+  bool operator!=(const RISCVExtensionVersion &Version) const {
+    return !(*this == Version);
+  }
+
+  bool operator<(const RISCVExtensionVersion &Version) const {
+    return (Major < Version.Major) ||
+           (Major == Version.Major && Minor < Version.Minor);
+  }
+
+  operator bool() const { return Major != 0 || Minor != 0; }
+};
+
 struct RISCVExtensionInfo {
   std::string ExtName;
-  unsigned MajorVersion;
-  unsigned MinorVersion;
+  RISCVExtensionVersion Version;
 };
 
 class RISCVISAInfo {
@@ -47,15 +71,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,9 +87,11 @@
   unsigned getFLen() const { return FLen; };
 
   bool hasExtension(StringRef Ext) const;
+  bool hasExtensionWithVersion(StringRef Ext) const;
   std::string toString() const;
 
-  static bool isSupportedExtensionFeature(StringRef Ext);
+  static Optional<RISCVExtensionInfo>
+  isSupportedExtensionFeature(StringRef Ext);
   static bool isSupportedExtension(StringRef Ext);
   static bool isSupportedExtension(StringRef Ext, unsigned MajorVersion,
                                    unsigned MinorVersion);
Index: clang/test/Driver/riscv-arch-version.c
===================================================================
--- /dev/null
+++ clang/test/Driver/riscv-arch-version.c
@@ -0,0 +1,181 @@
+// RUN: %clang -target riscv32-unknown-elf -march=rv32e1p9  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-E1P9 %s
+// RV32-E1P9: "-target-feature" "+e"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32im2p0  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-M2P0 %s
+// RV32-M2P0: "-target-feature" "+m"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ia2p0  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-A2P0 %s
+// RV32-A2P0: "-target-feature" "+a"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32if2p0  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-F2P0 %s
+// RV32-F2P0: "-target-feature" "+f"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ifd2p0  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-D2P0 %s
+// RV32-D2P0: "-target-feature" "+f" "-target-feature" "+d"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ic2p0  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-C2P0 %s
+// RV32-C2P0: "-target-feature" "+c"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iv0p10 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-V0P10 %s
+// RV32-EXPERIMENTAL-V0P10: "-target-feature" "+experimental-v"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izba1p0 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBA1P0 %s
+// RV32-EXPERIMENTAL-ZBA1P0: "-target-feature" "+experimental-zba"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbb1p0 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBB1P0 %s
+// RV32-EXPERIMENTAL-ZBB1P0: "-target-feature" "+experimental-zbb"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbc1p0 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBC1P0 %s
+// RV32-EXPERIMENTAL-ZBC1P0: "-target-feature" "+experimental-zbc"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbe0p93 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBE0P93 %s
+// RV32-EXPERIMENTAL-ZBE0P93: "-target-feature" "+experimental-zbe"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbf0p93 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBF0P93 %s
+// RV32-EXPERIMENTAL-ZBF0P93: "-target-feature" "+experimental-zbf"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbm0p93 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBM0P93 %s
+// RV32-EXPERIMENTAL-ZBM0P93: "-target-feature" "+experimental-zbm"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbp0p93 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBP0P93 %s
+// RV32-EXPERIMENTAL-ZBP0P93: "-target-feature" "+experimental-zbp"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbr0p93 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBR0P93 %s
+// RV32-EXPERIMENTAL-ZBR0P93: "-target-feature" "+experimental-zbr"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbs1p0 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBS1P0 %s
+// RV32-EXPERIMENTAL-ZBS1P0: "-target-feature" "+experimental-zbs"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbt0p93 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBT0P93 %s
+// RV32-EXPERIMENTAL-ZBT0P93: "-target-feature" "+experimental-zbt"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg0p10 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVLSSEG0P10 %s
+// RV32-EXPERIMENTAL-ZVLSSEG0P10: "-target-feature" "+experimental-zvlsseg"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izfhmin0p1 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFHMIN0P1 %s
+// RV32-EXPERIMENTAL-ZFHMIN0P1: "-target-feature" "+experimental-zfhmin"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izfh0p1 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFH0P1 %s
+// RV32-EXPERIMENTAL-ZFH0P1: "-target-feature" "+experimental-zfh"
+
+// Error Check Blow.
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32e2p0  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-E2P0 %s
+// RV32-E2P0: error: invalid arch name 'rv32e2p0'
+// RV32-E2P0: unsupported version number 2.0 for extension 'e'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32im2p1  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-M2P1 %s
+// RV32-M2P1: error: invalid arch name 'rv32im2p1'
+// RV32-M2P1: unsupported version number 2.1 for extension 'm'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ia2p1  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-A2P1 %s
+// RV32-A2P1: error: invalid arch name 'rv32ia2p1'
+// RV32-A2P1: unsupported version number 2.1 for extension 'a'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32if2p1  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-F2P1 %s
+// RV32-F2P1: error: invalid arch name 'rv32if2p1'
+// RV32-F2P1: unsupported version number 2.1 for extension 'f'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32id2p1  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-D2P1 %s
+// RV32-D2P1: error: invalid arch name 'rv32id2p1'
+// RV32-D2P1: unsupported version number 2.1 for extension 'd'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ic2p1  -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-C2P1 %s
+// RV32-C2P1: error: invalid arch name 'rv32ic2p1'
+// RV32-C2P1: unsupported version number 2.1 for extension 'c'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iv0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-V0P7 %s
+// RV32-EXPERIMENTAL-V0P7: error: invalid arch name 'rv32iv0p7'
+// RV32-EXPERIMENTAL-V0P7: unsupported version number 0.7 for experimental extension 'v'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izba0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBA0P7 %s
+// RV32-EXPERIMENTAL-ZBA0P7: error: invalid arch name 'rv32izba0p7'
+// RV32-EXPERIMENTAL-ZBA0P7: unsupported version number 0.7 for experimental extension 'zba'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbb0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBB0P7 %s
+// RV32-EXPERIMENTAL-ZBB0P7: error: invalid arch name 'rv32izbb0p7'
+// RV32-EXPERIMENTAL-ZBB0P7: unsupported version number 0.7 for experimental extension 'zbb'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbc0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBC0P7 %s
+// RV32-EXPERIMENTAL-ZBC0P7: error: invalid arch name 'rv32izbc0p7'
+// RV32-EXPERIMENTAL-ZBC0P7: unsupported version number 0.7 for experimental extension 'zbc'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbe0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBE0P7 %s
+// RV32-EXPERIMENTAL-ZBE0P7: error: invalid arch name 'rv32izbe0p7'
+// RV32-EXPERIMENTAL-ZBE0P7: unsupported version number 0.7 for experimental extension 'zbe'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbf0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBF0P7 %s
+// RV32-EXPERIMENTAL-ZBF0P7: error: invalid arch name 'rv32izbf0p7'
+// RV32-EXPERIMENTAL-ZBF0P7: unsupported version number 0.7 for experimental extension 'zbf'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbm0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBM0P7 %s
+// RV32-EXPERIMENTAL-ZBM0P7: error: invalid arch name 'rv32izbm0p7'
+// RV32-EXPERIMENTAL-ZBM0P7: unsupported version number 0.7 for experimental extension 'zbm'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbp0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBP0P7 %s
+// RV32-EXPERIMENTAL-ZBP0P7: error: invalid arch name 'rv32izbp0p7'
+// RV32-EXPERIMENTAL-ZBP0P7: unsupported version number 0.7 for experimental extension 'zbp'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbr0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBR0P7 %s
+// RV32-EXPERIMENTAL-ZBR0P7: error: invalid arch name 'rv32izbr0p7'
+// RV32-EXPERIMENTAL-ZBR0P7: unsupported version number 0.7 for experimental extension 'zbr'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbs0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBS0P7 %s
+// RV32-EXPERIMENTAL-ZBS0P7: error: invalid arch name 'rv32izbs0p7'
+// RV32-EXPERIMENTAL-ZBS0P7: unsupported version number 0.7 for experimental extension 'zbs'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izbt0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBT0P7 %s
+// RV32-EXPERIMENTAL-ZBT0P7: error: invalid arch name 'rv32izbt0p7'
+// RV32-EXPERIMENTAL-ZBT0P7: unsupported version number 0.7 for experimental extension 'zbt'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg0p1 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVLSSEG0P1 %s
+// RV32-EXPERIMENTAL-ZVLSSEG0P1: error: invalid arch name 'rv32izvlsseg0p1'
+// RV32-EXPERIMENTAL-ZVLSSEG0P1: unsupported version number 0.1 for experimental extension 'zvlsseg'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izfhmin0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFHMIN0P7 %s
+// RV32-EXPERIMENTAL-ZFHMIN0P7: error: invalid arch name 'rv32izfhmin0p7'
+// RV32-EXPERIMENTAL-ZFHMIN0P7: unsupported version number 0.7 for experimental extension 'zfhmin'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32izfh0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFH0P7 %s
+// RV32-EXPERIMENTAL-ZFH0P7: error: invalid arch name 'rv32izfh0p7'
+// RV32-EXPERIMENTAL-ZFH0P7: unsupported version number 0.7 for experimental extension 'zfh'
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,10 +223,7 @@
   if (Result.hasValue())
     return Result.getValue();
 
-  if (ISAInfo->isSupportedExtensionFeature(Feature))
-    return ISAInfo->hasExtension(Feature);
-
-  return false;
+  return ISAInfo->hasExtensionWithVersion(Feature);
 }
 
 /// Perform initialization based on the user configured set of features.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to