Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISCV] Support __builtin_cpu_is #116231

Merged
merged 22 commits into from
Nov 22, 2024

Conversation

wangpc-pp
Copy link
Contributor

We have defined __riscv_cpu_model variable in #101449. It contains
mvendorid, marchid and mimpid fields which are read via system
call sys_riscv_hwprobe.

We can support __builtin_cpu_is via comparing values in compiler's
CPU definitions and __riscv_cpu_model.

This depends on #116202.

Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1

[skip ci]
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen labels Nov 14, 2024
@wangpc-pp wangpc-pp requested review from topperc and preames November 14, 2024 14:02
@llvmbot
Copy link
Member

llvmbot commented Nov 14, 2024

@llvm/pr-subscribers-backend-risc-v

Author: Pengcheng Wang (wangpc-pp)

Changes

We have defined __riscv_cpu_model variable in #101449. It contains
mvendorid, marchid and mimpid fields which are read via system
call sys_riscv_hwprobe.

We can support __builtin_cpu_is via comparing values in compiler's
CPU definitions and __riscv_cpu_model.

This depends on #116202.


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

7 Files Affected:

  • (modified) clang/lib/Basic/Targets/RISCV.cpp (+8)
  • (modified) clang/lib/Basic/Targets/RISCV.h (+2)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+54)
  • (modified) clang/lib/CodeGen/CodeGenFunction.h (+2)
  • (modified) clang/test/CodeGen/builtin-cpu-is.c (+110-1)
  • (modified) llvm/include/llvm/TargetParser/RISCVTargetParser.h (+4)
  • (modified) llvm/lib/TargetParser/RISCVTargetParser.cpp (+26)
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index eaaba7642bd7b2..15e489a6a1288f 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -508,3 +508,11 @@ bool RISCVTargetInfo::validateGlobalRegisterVariable(
   }
   return false;
 }
+
+bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {
+  llvm::Triple Triple = getTriple();
+  assert(Triple.isOSLinux() &&
+         "__builtin_cpu_is() is only supported for Linux.");
+
+  return llvm::RISCV::hasValidCPUModel(CPUName);
+}
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 3b418585ab4a39..3544ea64cb5e77 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -128,8 +128,10 @@ class RISCVTargetInfo : public TargetInfo {
   }
 
   bool supportsCpuSupports() const override { return getTriple().isOSLinux(); }
+  bool supportsCpuIs() const override { return getTriple().isOSLinux(); }
   bool supportsCpuInit() const override { return getTriple().isOSLinux(); }
   bool validateCpuSupports(StringRef Feature) const override;
+  bool validateCpuIs(StringRef CPUName) const override;
   bool isValidFeatureName(StringRef Name) const override;
 
   bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9e0c0bff0125c0..82e21d105fcc0e 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -67,6 +67,7 @@
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/TargetParser/AArch64TargetParser.h"
 #include "llvm/TargetParser/RISCVISAInfo.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 #include "llvm/TargetParser/X86TargetParser.h"
 #include <optional>
 #include <sstream>
@@ -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))));
+
+  return Result;
+}
+
 Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
                                              const CallExpr *E,
                                              ReturnValueSlot ReturnValue) {
@@ -22513,6 +22565,8 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     return EmitRISCVCpuSupports(E);
   if (BuiltinID == Builtin::BI__builtin_cpu_init)
     return EmitRISCVCpuInit();
+  if (BuiltinID == Builtin::BI__builtin_cpu_is)
+    return EmitRISCVCpuIs(E);
 
   SmallVector<Value *, 4> Ops;
   llvm::Type *ResultType = ConvertType(E->getType());
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index fcc1013d7361ec..5c4d76c2267a77 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4730,6 +4730,8 @@ class CodeGenFunction : public CodeGenTypeCache {
   llvm::Value *EmitRISCVCpuSupports(const CallExpr *E);
   llvm::Value *EmitRISCVCpuSupports(ArrayRef<StringRef> FeaturesStrs);
   llvm::Value *EmitRISCVCpuInit();
+  llvm::Value *EmitRISCVCpuIs(const CallExpr *E);
+  llvm::Value *EmitRISCVCpuIs(StringRef CPUStr);
 
   void AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst,
                                       const CallExpr *E);
diff --git a/clang/test/CodeGen/builtin-cpu-is.c b/clang/test/CodeGen/builtin-cpu-is.c
index dab6d2f9d11aec..e4a2071cf46795 100644
--- a/clang/test/CodeGen/builtin-cpu-is.c
+++ b/clang/test/CodeGen/builtin-cpu-is.c
@@ -1,11 +1,26 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm < %s| FileCheck %s
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-X86
+// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
 
+#ifdef __x86_64__
 // Test that we have the structure definition, the gep offsets, the name of the
 // global, the bit grab, and the icmp correct.
 extern void a(const char *);
 
 // CHECK: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
 
+// CHECK-X86-LABEL: define dso_local void @intel(
+// CHECK-X86-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr @__cpu_model, align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void intel(void) {
   if (__builtin_cpu_is("intel"))
     a("intel");
@@ -14,6 +29,18 @@ void intel(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
 
+// CHECK-X86-LABEL: define dso_local void @amd(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr @__cpu_model, align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 2
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.1)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void amd(void) {
   if (__builtin_cpu_is("amd"))
     a("amd");
@@ -22,6 +49,18 @@ void amd(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 2
 }
 
+// CHECK-X86-LABEL: define dso_local void @atom(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 1), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.2)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void atom(void) {
   if (__builtin_cpu_is("atom"))
     a("atom");
@@ -30,6 +69,18 @@ void atom(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
 
+// CHECK-X86-LABEL: define dso_local void @amdfam10h(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 1), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.3)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void amdfam10h(void) {
   if (__builtin_cpu_is("amdfam10h"))
     a("amdfam10h");
@@ -38,6 +89,18 @@ void amdfam10h(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 4
 }
 
+// CHECK-X86-LABEL: define dso_local void @barcelona(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.4)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void barcelona(void) {
   if (__builtin_cpu_is("barcelona"))
     a("barcelona");
@@ -46,6 +109,18 @@ void barcelona(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 4
 }
 
+// CHECK-X86-LABEL: define dso_local void @nehalem(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.5)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void nehalem(void) {
   if (__builtin_cpu_is("nehalem"))
     a("nehalem");
@@ -53,3 +128,37 @@ void nehalem(void) {
   // CHECK: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2)
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
+#endif
+
+#ifdef __riscv
+// CHECK-RV64-LABEL: define dso_local signext i32 @test_riscv(
+// CHECK-RV64-SAME: i32 noundef signext [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT:  [[ENTRY:.*:]]
+// CHECK-RV64-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK-RV64-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-RV64-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = load i32, ptr @__riscv_cpu_model, align 4
+// CHECK-RV64-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1567
+// CHECK-RV64-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 1), align 8
+// CHECK-RV64-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[TMP2]], -9223372036854710272
+// CHECK-RV64-NEXT:    [[TMP4:%.*]] = and i1 [[TMP1]], [[TMP3]]
+// CHECK-RV64-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 2), align 8
+// CHECK-RV64-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 273
+// CHECK-RV64-NEXT:    [[TMP7:%.*]] = and i1 [[TMP4]], [[TMP6]]
+// CHECK-RV64-NEXT:    br i1 [[TMP7]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-RV64:       [[IF_THEN]]:
+// CHECK-RV64-NEXT:    store i32 3, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    br label %[[RETURN:.*]]
+// CHECK-RV64:       [[IF_END]]:
+// CHECK-RV64-NEXT:    store i32 0, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    br label %[[RETURN]]
+// CHECK-RV64:       [[RETURN]]:
+// CHECK-RV64-NEXT:    [[TMP8:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    ret i32 [[TMP8]]
+//
+int test_riscv(int a) {
+  if (__builtin_cpu_is("veyron-v1"))
+    return 3;
+  return 0;
+}
+#endif
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index c75778952e0f51..23a30425e95616 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -45,6 +45,10 @@ void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
 void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
 bool hasFastScalarUnalignedAccess(StringRef CPU);
 bool hasFastVectorUnalignedAccess(StringRef CPU);
+bool hasValidCPUModel(StringRef CPU);
+uint32_t getVendorID(StringRef CPU);
+uint64_t getArchID(StringRef CPU);
+uint64_t getImplID(StringRef CPU);
 
 } // namespace RISCV
 
diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp
index 62fbd3458112e2..d62e1ba25cd94d 100644
--- a/llvm/lib/TargetParser/RISCVTargetParser.cpp
+++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp
@@ -71,6 +71,32 @@ bool hasFastVectorUnalignedAccess(StringRef CPU) {
   return Info && Info->FastVectorUnalignedAccess;
 }
 
+bool hasValidCPUModel(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  return Info && Info->MVendorID && Info->MArchID && Info->MImpID;
+}
+
+uint32_t getVendorID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MVendorID;
+}
+
+uint64_t getArchID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MArchID;
+}
+
+uint64_t getImplID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MImpID;
+}
+
 bool parseCPU(StringRef CPU, bool IsRV64) {
   const CPUInfo *Info = getCPUInfoByName(CPU);
 

@llvmbot
Copy link
Member

llvmbot commented Nov 14, 2024

@llvm/pr-subscribers-clang-codegen

Author: Pengcheng Wang (wangpc-pp)

Changes

We have defined __riscv_cpu_model variable in #101449. It contains
mvendorid, marchid and mimpid fields which are read via system
call sys_riscv_hwprobe.

We can support __builtin_cpu_is via comparing values in compiler's
CPU definitions and __riscv_cpu_model.

This depends on #116202.


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

7 Files Affected:

  • (modified) clang/lib/Basic/Targets/RISCV.cpp (+8)
  • (modified) clang/lib/Basic/Targets/RISCV.h (+2)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+54)
  • (modified) clang/lib/CodeGen/CodeGenFunction.h (+2)
  • (modified) clang/test/CodeGen/builtin-cpu-is.c (+110-1)
  • (modified) llvm/include/llvm/TargetParser/RISCVTargetParser.h (+4)
  • (modified) llvm/lib/TargetParser/RISCVTargetParser.cpp (+26)
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index eaaba7642bd7b2..15e489a6a1288f 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -508,3 +508,11 @@ bool RISCVTargetInfo::validateGlobalRegisterVariable(
   }
   return false;
 }
+
+bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {
+  llvm::Triple Triple = getTriple();
+  assert(Triple.isOSLinux() &&
+         "__builtin_cpu_is() is only supported for Linux.");
+
+  return llvm::RISCV::hasValidCPUModel(CPUName);
+}
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 3b418585ab4a39..3544ea64cb5e77 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -128,8 +128,10 @@ class RISCVTargetInfo : public TargetInfo {
   }
 
   bool supportsCpuSupports() const override { return getTriple().isOSLinux(); }
+  bool supportsCpuIs() const override { return getTriple().isOSLinux(); }
   bool supportsCpuInit() const override { return getTriple().isOSLinux(); }
   bool validateCpuSupports(StringRef Feature) const override;
+  bool validateCpuIs(StringRef CPUName) const override;
   bool isValidFeatureName(StringRef Name) const override;
 
   bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9e0c0bff0125c0..82e21d105fcc0e 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -67,6 +67,7 @@
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/TargetParser/AArch64TargetParser.h"
 #include "llvm/TargetParser/RISCVISAInfo.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 #include "llvm/TargetParser/X86TargetParser.h"
 #include <optional>
 #include <sstream>
@@ -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))));
+
+  return Result;
+}
+
 Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
                                              const CallExpr *E,
                                              ReturnValueSlot ReturnValue) {
@@ -22513,6 +22565,8 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     return EmitRISCVCpuSupports(E);
   if (BuiltinID == Builtin::BI__builtin_cpu_init)
     return EmitRISCVCpuInit();
+  if (BuiltinID == Builtin::BI__builtin_cpu_is)
+    return EmitRISCVCpuIs(E);
 
   SmallVector<Value *, 4> Ops;
   llvm::Type *ResultType = ConvertType(E->getType());
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index fcc1013d7361ec..5c4d76c2267a77 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4730,6 +4730,8 @@ class CodeGenFunction : public CodeGenTypeCache {
   llvm::Value *EmitRISCVCpuSupports(const CallExpr *E);
   llvm::Value *EmitRISCVCpuSupports(ArrayRef<StringRef> FeaturesStrs);
   llvm::Value *EmitRISCVCpuInit();
+  llvm::Value *EmitRISCVCpuIs(const CallExpr *E);
+  llvm::Value *EmitRISCVCpuIs(StringRef CPUStr);
 
   void AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst,
                                       const CallExpr *E);
diff --git a/clang/test/CodeGen/builtin-cpu-is.c b/clang/test/CodeGen/builtin-cpu-is.c
index dab6d2f9d11aec..e4a2071cf46795 100644
--- a/clang/test/CodeGen/builtin-cpu-is.c
+++ b/clang/test/CodeGen/builtin-cpu-is.c
@@ -1,11 +1,26 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm < %s| FileCheck %s
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-X86
+// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
 
+#ifdef __x86_64__
 // Test that we have the structure definition, the gep offsets, the name of the
 // global, the bit grab, and the icmp correct.
 extern void a(const char *);
 
 // CHECK: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
 
+// CHECK-X86-LABEL: define dso_local void @intel(
+// CHECK-X86-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr @__cpu_model, align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void intel(void) {
   if (__builtin_cpu_is("intel"))
     a("intel");
@@ -14,6 +29,18 @@ void intel(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
 
+// CHECK-X86-LABEL: define dso_local void @amd(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr @__cpu_model, align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 2
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.1)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void amd(void) {
   if (__builtin_cpu_is("amd"))
     a("amd");
@@ -22,6 +49,18 @@ void amd(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 2
 }
 
+// CHECK-X86-LABEL: define dso_local void @atom(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 1), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.2)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void atom(void) {
   if (__builtin_cpu_is("atom"))
     a("atom");
@@ -30,6 +69,18 @@ void atom(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
 
+// CHECK-X86-LABEL: define dso_local void @amdfam10h(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 1), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.3)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void amdfam10h(void) {
   if (__builtin_cpu_is("amdfam10h"))
     a("amdfam10h");
@@ -38,6 +89,18 @@ void amdfam10h(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 4
 }
 
+// CHECK-X86-LABEL: define dso_local void @barcelona(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.4)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void barcelona(void) {
   if (__builtin_cpu_is("barcelona"))
     a("barcelona");
@@ -46,6 +109,18 @@ void barcelona(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 4
 }
 
+// CHECK-X86-LABEL: define dso_local void @nehalem(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.5)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void nehalem(void) {
   if (__builtin_cpu_is("nehalem"))
     a("nehalem");
@@ -53,3 +128,37 @@ void nehalem(void) {
   // CHECK: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2)
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
+#endif
+
+#ifdef __riscv
+// CHECK-RV64-LABEL: define dso_local signext i32 @test_riscv(
+// CHECK-RV64-SAME: i32 noundef signext [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT:  [[ENTRY:.*:]]
+// CHECK-RV64-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK-RV64-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-RV64-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = load i32, ptr @__riscv_cpu_model, align 4
+// CHECK-RV64-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1567
+// CHECK-RV64-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 1), align 8
+// CHECK-RV64-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[TMP2]], -9223372036854710272
+// CHECK-RV64-NEXT:    [[TMP4:%.*]] = and i1 [[TMP1]], [[TMP3]]
+// CHECK-RV64-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 2), align 8
+// CHECK-RV64-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 273
+// CHECK-RV64-NEXT:    [[TMP7:%.*]] = and i1 [[TMP4]], [[TMP6]]
+// CHECK-RV64-NEXT:    br i1 [[TMP7]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-RV64:       [[IF_THEN]]:
+// CHECK-RV64-NEXT:    store i32 3, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    br label %[[RETURN:.*]]
+// CHECK-RV64:       [[IF_END]]:
+// CHECK-RV64-NEXT:    store i32 0, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    br label %[[RETURN]]
+// CHECK-RV64:       [[RETURN]]:
+// CHECK-RV64-NEXT:    [[TMP8:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    ret i32 [[TMP8]]
+//
+int test_riscv(int a) {
+  if (__builtin_cpu_is("veyron-v1"))
+    return 3;
+  return 0;
+}
+#endif
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index c75778952e0f51..23a30425e95616 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -45,6 +45,10 @@ void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
 void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
 bool hasFastScalarUnalignedAccess(StringRef CPU);
 bool hasFastVectorUnalignedAccess(StringRef CPU);
+bool hasValidCPUModel(StringRef CPU);
+uint32_t getVendorID(StringRef CPU);
+uint64_t getArchID(StringRef CPU);
+uint64_t getImplID(StringRef CPU);
 
 } // namespace RISCV
 
diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp
index 62fbd3458112e2..d62e1ba25cd94d 100644
--- a/llvm/lib/TargetParser/RISCVTargetParser.cpp
+++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp
@@ -71,6 +71,32 @@ bool hasFastVectorUnalignedAccess(StringRef CPU) {
   return Info && Info->FastVectorUnalignedAccess;
 }
 
+bool hasValidCPUModel(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  return Info && Info->MVendorID && Info->MArchID && Info->MImpID;
+}
+
+uint32_t getVendorID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MVendorID;
+}
+
+uint64_t getArchID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MArchID;
+}
+
+uint64_t getImplID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MImpID;
+}
+
 bool parseCPU(StringRef CPU, bool IsRV64) {
   const CPUInfo *Info = getCPUInfoByName(CPU);
 

@llvmbot
Copy link
Member

llvmbot commented Nov 14, 2024

@llvm/pr-subscribers-clang

Author: Pengcheng Wang (wangpc-pp)

Changes

We have defined __riscv_cpu_model variable in #101449. It contains
mvendorid, marchid and mimpid fields which are read via system
call sys_riscv_hwprobe.

We can support __builtin_cpu_is via comparing values in compiler's
CPU definitions and __riscv_cpu_model.

This depends on #116202.


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

7 Files Affected:

  • (modified) clang/lib/Basic/Targets/RISCV.cpp (+8)
  • (modified) clang/lib/Basic/Targets/RISCV.h (+2)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+54)
  • (modified) clang/lib/CodeGen/CodeGenFunction.h (+2)
  • (modified) clang/test/CodeGen/builtin-cpu-is.c (+110-1)
  • (modified) llvm/include/llvm/TargetParser/RISCVTargetParser.h (+4)
  • (modified) llvm/lib/TargetParser/RISCVTargetParser.cpp (+26)
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index eaaba7642bd7b2..15e489a6a1288f 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -508,3 +508,11 @@ bool RISCVTargetInfo::validateGlobalRegisterVariable(
   }
   return false;
 }
+
+bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {
+  llvm::Triple Triple = getTriple();
+  assert(Triple.isOSLinux() &&
+         "__builtin_cpu_is() is only supported for Linux.");
+
+  return llvm::RISCV::hasValidCPUModel(CPUName);
+}
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 3b418585ab4a39..3544ea64cb5e77 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -128,8 +128,10 @@ class RISCVTargetInfo : public TargetInfo {
   }
 
   bool supportsCpuSupports() const override { return getTriple().isOSLinux(); }
+  bool supportsCpuIs() const override { return getTriple().isOSLinux(); }
   bool supportsCpuInit() const override { return getTriple().isOSLinux(); }
   bool validateCpuSupports(StringRef Feature) const override;
+  bool validateCpuIs(StringRef CPUName) const override;
   bool isValidFeatureName(StringRef Name) const override;
 
   bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9e0c0bff0125c0..82e21d105fcc0e 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -67,6 +67,7 @@
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/TargetParser/AArch64TargetParser.h"
 #include "llvm/TargetParser/RISCVISAInfo.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 #include "llvm/TargetParser/X86TargetParser.h"
 #include <optional>
 #include <sstream>
@@ -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))));
+
+  return Result;
+}
+
 Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
                                              const CallExpr *E,
                                              ReturnValueSlot ReturnValue) {
@@ -22513,6 +22565,8 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     return EmitRISCVCpuSupports(E);
   if (BuiltinID == Builtin::BI__builtin_cpu_init)
     return EmitRISCVCpuInit();
+  if (BuiltinID == Builtin::BI__builtin_cpu_is)
+    return EmitRISCVCpuIs(E);
 
   SmallVector<Value *, 4> Ops;
   llvm::Type *ResultType = ConvertType(E->getType());
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index fcc1013d7361ec..5c4d76c2267a77 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4730,6 +4730,8 @@ class CodeGenFunction : public CodeGenTypeCache {
   llvm::Value *EmitRISCVCpuSupports(const CallExpr *E);
   llvm::Value *EmitRISCVCpuSupports(ArrayRef<StringRef> FeaturesStrs);
   llvm::Value *EmitRISCVCpuInit();
+  llvm::Value *EmitRISCVCpuIs(const CallExpr *E);
+  llvm::Value *EmitRISCVCpuIs(StringRef CPUStr);
 
   void AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst,
                                       const CallExpr *E);
diff --git a/clang/test/CodeGen/builtin-cpu-is.c b/clang/test/CodeGen/builtin-cpu-is.c
index dab6d2f9d11aec..e4a2071cf46795 100644
--- a/clang/test/CodeGen/builtin-cpu-is.c
+++ b/clang/test/CodeGen/builtin-cpu-is.c
@@ -1,11 +1,26 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm < %s| FileCheck %s
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-X86
+// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-RV64
 
+#ifdef __x86_64__
 // Test that we have the structure definition, the gep offsets, the name of the
 // global, the bit grab, and the icmp correct.
 extern void a(const char *);
 
 // CHECK: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
 
+// CHECK-X86-LABEL: define dso_local void @intel(
+// CHECK-X86-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr @__cpu_model, align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void intel(void) {
   if (__builtin_cpu_is("intel"))
     a("intel");
@@ -14,6 +29,18 @@ void intel(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
 
+// CHECK-X86-LABEL: define dso_local void @amd(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr @__cpu_model, align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 2
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.1)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void amd(void) {
   if (__builtin_cpu_is("amd"))
     a("amd");
@@ -22,6 +49,18 @@ void amd(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 2
 }
 
+// CHECK-X86-LABEL: define dso_local void @atom(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 1), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.2)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void atom(void) {
   if (__builtin_cpu_is("atom"))
     a("atom");
@@ -30,6 +69,18 @@ void atom(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
 
+// CHECK-X86-LABEL: define dso_local void @amdfam10h(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 1), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.3)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void amdfam10h(void) {
   if (__builtin_cpu_is("amdfam10h"))
     a("amdfam10h");
@@ -38,6 +89,18 @@ void amdfam10h(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 4
 }
 
+// CHECK-X86-LABEL: define dso_local void @barcelona(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.4)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void barcelona(void) {
   if (__builtin_cpu_is("barcelona"))
     a("barcelona");
@@ -46,6 +109,18 @@ void barcelona(void) {
   // CHECK: = icmp eq i32 [[LOAD]], 4
 }
 
+// CHECK-X86-LABEL: define dso_local void @nehalem(
+// CHECK-X86-SAME: ) #[[ATTR0]] {
+// CHECK-X86-NEXT:  [[ENTRY:.*:]]
+// CHECK-X86-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2), align 4
+// CHECK-X86-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1
+// CHECK-X86-NEXT:    br i1 [[TMP1]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-X86:       [[IF_THEN]]:
+// CHECK-X86-NEXT:    call void @a(ptr noundef @.str.5)
+// CHECK-X86-NEXT:    br label %[[IF_END]]
+// CHECK-X86:       [[IF_END]]:
+// CHECK-X86-NEXT:    ret void
+//
 void nehalem(void) {
   if (__builtin_cpu_is("nehalem"))
     a("nehalem");
@@ -53,3 +128,37 @@ void nehalem(void) {
   // CHECK: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 2)
   // CHECK: = icmp eq i32 [[LOAD]], 1
 }
+#endif
+
+#ifdef __riscv
+// CHECK-RV64-LABEL: define dso_local signext i32 @test_riscv(
+// CHECK-RV64-SAME: i32 noundef signext [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT:  [[ENTRY:.*:]]
+// CHECK-RV64-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK-RV64-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-RV64-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = load i32, ptr @__riscv_cpu_model, align 4
+// CHECK-RV64-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 1567
+// CHECK-RV64-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 1), align 8
+// CHECK-RV64-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[TMP2]], -9223372036854710272
+// CHECK-RV64-NEXT:    [[TMP4:%.*]] = and i1 [[TMP1]], [[TMP3]]
+// CHECK-RV64-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, i64, i64 }, ptr @__riscv_cpu_model, i32 0, i32 2), align 8
+// CHECK-RV64-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 273
+// CHECK-RV64-NEXT:    [[TMP7:%.*]] = and i1 [[TMP4]], [[TMP6]]
+// CHECK-RV64-NEXT:    br i1 [[TMP7]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// CHECK-RV64:       [[IF_THEN]]:
+// CHECK-RV64-NEXT:    store i32 3, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    br label %[[RETURN:.*]]
+// CHECK-RV64:       [[IF_END]]:
+// CHECK-RV64-NEXT:    store i32 0, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    br label %[[RETURN]]
+// CHECK-RV64:       [[RETURN]]:
+// CHECK-RV64-NEXT:    [[TMP8:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    ret i32 [[TMP8]]
+//
+int test_riscv(int a) {
+  if (__builtin_cpu_is("veyron-v1"))
+    return 3;
+  return 0;
+}
+#endif
diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
index c75778952e0f51..23a30425e95616 100644
--- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h
+++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h
@@ -45,6 +45,10 @@ void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
 void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
 bool hasFastScalarUnalignedAccess(StringRef CPU);
 bool hasFastVectorUnalignedAccess(StringRef CPU);
+bool hasValidCPUModel(StringRef CPU);
+uint32_t getVendorID(StringRef CPU);
+uint64_t getArchID(StringRef CPU);
+uint64_t getImplID(StringRef CPU);
 
 } // namespace RISCV
 
diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp
index 62fbd3458112e2..d62e1ba25cd94d 100644
--- a/llvm/lib/TargetParser/RISCVTargetParser.cpp
+++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp
@@ -71,6 +71,32 @@ bool hasFastVectorUnalignedAccess(StringRef CPU) {
   return Info && Info->FastVectorUnalignedAccess;
 }
 
+bool hasValidCPUModel(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  return Info && Info->MVendorID && Info->MArchID && Info->MImpID;
+}
+
+uint32_t getVendorID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MVendorID;
+}
+
+uint64_t getArchID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MArchID;
+}
+
+uint64_t getImplID(StringRef CPU) {
+  const CPUInfo *Info = getCPUInfoByName(CPU);
+  if (!Info)
+    return false;
+  return Info->MImpID;
+}
+
 bool parseCPU(StringRef CPU, bool IsRV64) {
   const CPUInfo *Info = getCPUInfoByName(CPU);
 

Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1
Comment on lines 22537 to 22555
// 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))));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

@wangpc-pp wangpc-pp Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently this implementation just reports an error when there is no non-zero values in CPU definitions (done in validateCpuIs). This should match PPC/X86. PPC supports CPUs with valid Linux_SUPPORT_METHOD or AIX_SUPPORT_METHOD value; X86 supports a set of defined CPUs.

Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
clang/lib/CodeGen/CGBuiltin.cpp Outdated Show resolved Hide resolved
clang/lib/CodeGen/CGBuiltin.cpp Outdated Show resolved Hide resolved
clang/lib/CodeGen/CGBuiltin.cpp Outdated Show resolved Hide resolved
clang/lib/CodeGen/CGBuiltin.cpp Outdated Show resolved Hide resolved
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1

[skip ci]
Created using spr 1.3.6-beta.1
@wangpc-pp wangpc-pp changed the base branch from users/wangpc-pp/spr/main.riscv-support-__builtin_cpu_is to main November 22, 2024 12:04
@wangpc-pp wangpc-pp merged commit c11b6b1 into main Nov 22, 2024
6 of 11 checks passed
@wangpc-pp wangpc-pp deleted the users/wangpc-pp/spr/riscv-support-__builtin_cpu_is branch November 22, 2024 12:04
wangpc-pp added a commit that referenced this pull request Nov 22, 2024
We have defined `__riscv_cpu_model` variable in #101449. It contains
`mvendorid`, `marchid` and `mimpid` fields which are read via system
call `sys_riscv_hwprobe`.

We can support `__builtin_cpu_is` via comparing values in compiler's
CPU definitions and `__riscv_cpu_model`.

This depends on #116202.

Reviewers: lenary, BeMg, kito-cheng, preames, lukel97

Reviewed By: lenary

Pull Request: #116231
@fmayer
Copy link
Contributor

fmayer commented Nov 22, 2024

Fails buildbot: https://lab.llvm.org/buildbot/#/builders/24/builds/2791/steps/10/logs/stdio

-- Testing: 83950 of 83951 tests, 48 workers --
Testing:  0.. 10..
FAIL: Clang :: Preprocessor/has_builtin_cpuid.c (15996 of 83950)
******************** TEST 'Clang :: Preprocessor/has_builtin_cpuid.c' FAILED ********************
Exit Code: 1
Command Output (stderr):
--
RUN: at line 1: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple arm64-- -DARM -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
+ /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple arm64-- -DARM -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
RUN: at line 2: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple x86_64-- -DX86 -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
+ /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple x86_64-- -DX86 -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
RUN: at line 3: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple powerpc64-unknown-linux-gnu -DPPC    -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
+ /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple powerpc64-unknown-linux-gnu -DPPC -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
RUN: at line 5: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple riscv32-unknown-linux-gnu -DRISCV    -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
+ /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple riscv32-unknown-linux-gnu -DRISCV -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
error: 'expected-error' diagnostics seen but not expected: 
  File /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c Line 12: "ARM/RISCV shouldn't have __builtin_cpu_is"
1 error generated.
--

@wangpc-pp
Copy link
Contributor Author

Fails buildbot: https://lab.llvm.org/buildbot/#/builders/24/builds/2791/steps/10/logs/stdio

-- Testing: 83950 of 83951 tests, 48 workers --
Testing:  0.. 10..
FAIL: Clang :: Preprocessor/has_builtin_cpuid.c (15996 of 83950)
******************** TEST 'Clang :: Preprocessor/has_builtin_cpuid.c' FAILED ********************
Exit Code: 1
Command Output (stderr):
--
RUN: at line 1: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple arm64-- -DARM -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
+ /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple arm64-- -DARM -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
RUN: at line 2: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple x86_64-- -DX86 -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
+ /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple x86_64-- -DX86 -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
RUN: at line 3: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple powerpc64-unknown-linux-gnu -DPPC    -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
+ /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple powerpc64-unknown-linux-gnu -DPPC -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
RUN: at line 5: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple riscv32-unknown-linux-gnu -DRISCV    -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
+ /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/lib/clang/20/include -nostdsysteminc -fsyntax-only -triple riscv32-unknown-linux-gnu -DRISCV -verify /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c
error: 'expected-error' diagnostics seen but not expected: 
  File /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/clang/test/Preprocessor/has_builtin_cpuid.c Line 12: "ARM/RISCV shouldn't have __builtin_cpu_is"
1 error generated.
--

Thanks for reporting, it has been fixed now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants