Allow users to specify riscv cpu and get hardware features (#16902)

Allow users to specify riscv cpu and get hardware features. 
e.g.,
```
iree-compile \
  --iree-hal-target-backends=llvm-cpu \
  --iree-llvmcpu-target-triple=riscv64-pc-linux-gnu \
  --iree-llvmcpu-target-cpu=sifive-x280 \
  --iree-llvmcpu-target-abi=lp64d \
  --riscv-v-fixed-length-vector-lmul-max=8 \
  xxx.mlirbc -o xxx.vmfb
```

Signed-off-by: Alex Chiang <alex.chiang@sifive.com>
diff --git a/compiler/plugins/target/LLVMCPU/LLVMTargetOptions.cpp b/compiler/plugins/target/LLVMCPU/LLVMTargetOptions.cpp
index c1057d6..8fe6469 100644
--- a/compiler/plugins/target/LLVMCPU/LLVMTargetOptions.cpp
+++ b/compiler/plugins/target/LLVMCPU/LLVMTargetOptions.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/TargetParser/X86TargetParser.h"
@@ -67,20 +68,26 @@
     outCpuFeatures = targetCpuFeatures.getString();
   }
 
-  // If CPU is non-host and non-generic then we need to populate the
-  // corresponding features.
   if (outCpu.empty() || inCpu == "host" || inCpu == "generic" ||
       inCpu.starts_with("generic-")) {
     return true;
   }
-  if (triple.isX86()) {
-    llvm::SubtargetFeatures targetCpuFeatures(outCpuFeatures);
-    llvm::SmallVector<llvm::StringRef> cpuFeatureList;
-    llvm::X86::getFeaturesForCPU(outCpu, cpuFeatureList);
-    for (auto &feature : cpuFeatureList) {
+  // If CPU is non-host and non-generic then we need to populate the
+  // corresponding features.
+  llvm::SubtargetFeatures targetCpuFeatures(outCpuFeatures);
+  auto addCpuFeatures = [&](const auto &getFeaturesForCPU,
+                            auto &cpuFeatureList) {
+    getFeaturesForCPU(outCpu, cpuFeatureList, false);
+    for (const auto &feature : cpuFeatureList) {
       targetCpuFeatures.AddFeature(feature);
     }
-    outCpuFeatures = targetCpuFeatures.getString();
+  };
+  if (triple.isX86()) {
+    llvm::SmallVector<llvm::StringRef> cpuFeatureList;
+    addCpuFeatures(llvm::X86::getFeaturesForCPU, cpuFeatureList);
+  } else if (triple.isRISCV64()) {
+    llvm::SmallVector<std::string> cpuFeatureList;
+    addCpuFeatures(llvm::RISCV::getFeaturesForCPU, cpuFeatureList);
   } else {
     llvm::errs()
         << "error: Resolution of target CPU to target CPU features is not "
@@ -90,6 +97,7 @@
            "on this architecture, or implement that.\n";
     return false;
   }
+  outCpuFeatures = targetCpuFeatures.getString();
   return true;
 }