[llvm-branch-commits] [clang] [llvm] [RISCV] Support __builtin_cpu_is (PR #116231)

Sam Elliott via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Nov 14 06:42:15 PST 2024


================
@@ -22505,6 +22506,57 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID,
   return nullptr;
 }
 
+Value *CodeGenFunction::EmitRISCVCpuIs(const CallExpr *E) {
+  const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
+  StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
+  return EmitRISCVCpuIs(CPUStr);
+}
+
+Value *CodeGenFunction::EmitRISCVCpuIs(StringRef CPUStr) {
+  llvm::Type *Int32Ty = Builder.getInt32Ty();
+  llvm::Type *Int64Ty = Builder.getInt64Ty();
+  llvm::Type *MXLenType =
+      CGM.getTarget().getTriple().isArch32Bit() ? Int32Ty : Int64Ty;
+
+  llvm::Type *StructTy = llvm::StructType::get(Int32Ty, MXLenType, MXLenType);
+  llvm::Constant *RISCVCPUModel =
+      CGM.CreateRuntimeVariable(StructTy, "__riscv_cpu_model");
+  cast<llvm::GlobalValue>(RISCVCPUModel)->setDSOLocal(true);
+
+  auto loadRISCVCPUID = [&](unsigned Index, llvm::Type *ValueTy,
+                            CGBuilderTy &Builder, CodeGenModule &CGM) {
+    llvm::Value *GEPIndices[] = {Builder.getInt32(0),
+                                 llvm::ConstantInt::get(Int32Ty, Index)};
+    Value *Ptr = Builder.CreateInBoundsGEP(StructTy, RISCVCPUModel, GEPIndices);
+    Value *CPUID = Builder.CreateAlignedLoad(
+        ValueTy, Ptr,
+        CharUnits::fromQuantity(ValueTy->getScalarSizeInBits() / 8));
+    return CPUID;
+  };
+
+  // Compare mvendorid.
+  Value *VendorID = loadRISCVCPUID(0, Int32Ty, Builder, CGM);
+  Value *Result = Builder.CreateICmpEQ(
+      VendorID,
+      llvm::ConstantInt::get(Int32Ty, llvm::RISCV::getVendorID(CPUStr)));
+
+  // Compare marchid.
+  Value *ArchID = loadRISCVCPUID(1, MXLenType, Builder, CGM);
+  Result = Builder.CreateAnd(
+      Result, Builder.CreateICmpEQ(
+                  ArchID, llvm::ConstantInt::get(
+                              MXLenType, llvm::RISCV::getArchID(CPUStr))));
+
+  // Compare mimplid.
+  Value *ImplID = loadRISCVCPUID(2, MXLenType, Builder, CGM);
+  Result = Builder.CreateAnd(
+      Result, Builder.CreateICmpEQ(
+                  ImplID, llvm::ConstantInt::get(
+                              MXLenType, llvm::RISCV::getImplID(CPUStr))));
----------------
lenary wrote:

Currently we are using `getVendorID`, `getArchID` or `getImplID` returning 0 to mean we have no IDs in LLVM for that CPU. On the CPU Core's side, the CSRs will also report 0 if they are not implemented (though I'm not sure what e.g. Linux reports to userspace in this case).

When we have no IDs, what comparisons should we be doing?

Maybe we should only support `__builtin_cpu_is(...)` for CPUs where we have non-zero values for any of the three items? Otherwise either emit a compile-time error, or return `false` because we don't have a way to actually know if we're on the CPU being asked for?

I don't know the right answer here, but I think this implementation isn't handling these cases right.


https://github.com/llvm/llvm-project/pull/116231


More information about the llvm-branch-commits mailing list