llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Lucas Ribeiro (lucaslive974)

<details>
<summary>Changes</summary>

This PR implements x86 CPU feature detection builtins for ClangIR.

Adresses #<!-- -->167765


---

Patch is 217.22 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/212143.diff


6 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp (+162-12) 
- (added) clang/test/CIR/CodeGenBuiltins/X86/builtin-cpu-is-cputype.c (+440) 
- (added) clang/test/CIR/CodeGenBuiltins/X86/builtin-cpu-is-subtype.c (+792) 
- (added) clang/test/CIR/CodeGenBuiltins/X86/builtin-cpu-is-vendor.c (+71) 
- (added) clang/test/CIR/CodeGenBuiltins/X86/builtin-cpu-supports-all.c (+2193) 
- (added) clang/test/CIR/CodeGenBuiltins/X86/builtin-cpu-supports.c (+222) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 2369c654833cf..9f7307f3cb1e5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -26,6 +26,7 @@
 #include "clang/CIR/MissingFeatures.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/TargetParser/X86TargetParser.h"
 #include <string>
 
 using namespace clang;
@@ -908,21 +909,170 @@ static mlir::Value 
emitX86PackedByteShift(CIRGenBuilderTy &builder,
   return shuffleResult;
 }
 
-std::optional<mlir::Value>
-CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
-  if (builtinID == Builtin::BI__builtin_cpu_is) {
-    cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_is");
-    return mlir::Value{};
-  }
-  if (builtinID == Builtin::BI__builtin_cpu_supports) {
-    cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_supports");
-    return mlir::Value{};
+static mlir::Value emitX86CpuInit(CIRGenModule &module,
+                                  CIRGenBuilderTy &builder,
+                                  mlir::Location loc) {
+  cir::VoidType voidTy = builder.getVoidTy();
+  cir::FuncType fnTy = builder.getFuncType({}, voidTy);
+
+  cir::FuncOp fn = module.createRuntimeFunction(fnTy, "__cpu_indicator_init");
+  fn.setDsoLocal(true);
+  fn.setBuiltin(true);
+
+  return builder.createCallOp(loc, fn, mlir::ValueRange{}).getResult();
+}
+
+// Matching the struct layout from the compiler-rt/libgcc structure that is
+// filled in:
+// unsigned int __cpu_vendor;
+// unsigned int __cpu_type;
+// unsigned int __cpu_subtype;
+// unsigned int __cpu_features[1];
+static cir::GetGlobalOp getX86CpuModelGlobalRecord(CIRGenModule &module,
+                                                   CIRGenBuilderTy &builder,
+                                                   mlir::Location loc) {
+  auto u32iTy = builder.getUInt32Ty();
+  auto arrTy = cir::ArrayType::get(u32iTy, /**size=*/1);
+  cir::StructType sTy =
+      builder.getAnonRecordTy({u32iTy, u32iTy, u32iTy, arrTy});
+
+  cir::GlobalOp cpuModel;
+  if (auto it = module.symbolLookupCache.find("__cpu_model");
+      it == module.symbolLookupCache.end()) {
+    cpuModel = module.createGlobalOp(loc, "__cpu_model", sTy);
+    cpuModel.setDSOLocal(true);
+  } else
+    cpuModel = cast<cir::GlobalOp>(it->second);
+
+  return builder.createGetGlobal(cpuModel);
+}
+
+static mlir::Value emitX86CpuIs(CIRGenModule &module, CIRGenBuilderTy &builder,
+                                mlir::Location loc, llvm::StringRef cpuStr) {
+  // Calculate the index needed to access the correct field based on the
+  // range. ABI_VALUE matches with compiler-rt/libgcc values.
+  auto [index, abiValue, member] =
+      mlir::StringSwitch<std::tuple<unsigned, unsigned, llvm::StringRef>>(
+          cpuStr)
+#define X86_VENDOR(ENUM, STR, ABI_VALUE)                                       
\
+  .Case(STR, {0u, ABI_VALUE, "__cpu_vendor"})
+#define X86_CPU_TYPE(ENUM, STR, ABI_VALUE)                                     
\
+  .Case(STR, {1u, ABI_VALUE, "__cpu_type"})
+#define X86_CPU_SUBTYPE(ENUM, STR, ABI_VALUE)                                  
\
+  .Case(STR, {2u, ABI_VALUE, "__cpu_subtype"})
+#include "llvm/TargetParser/X86TargetParser.def"
+          .Default({0, 0, ""});
+  assert(abiValue != 0 && "Invalid CPUStr passed to CpuIs");
+
+  auto u32iTy = builder.getUInt32Ty();
+
+  cir::GetGlobalOp cpuModel = getX86CpuModelGlobalRecord(module, builder, loc);
+  cir::GetMemberOp cpuValue = builder.createGetMember(
+      loc, builder.getPointerTo(u32iTy), cpuModel, member, index);
+  mlir::Value value = builder.createAlignedLoad(loc, u32iTy, cpuValue,
+                                                CharUnits::fromQuantity(4));
+
+  return builder.createCompare(loc, cir::CmpOpKind::eq, value,
+                               /**rhs=*/builder.getUInt32(abiValue, loc));
+}
+
+// Matching the struct layout from the compiler-rt/libgcc structure that is
+// filled in:
+// unsigned int __features2[3];
+static cir::GetGlobalOp getX86CpuFeature2GlobalRecord(CIRGenModule &module,
+                                                      CIRGenBuilderTy &builder,
+                                                      mlir::Location loc) {
+  auto u32iTy = builder.getUInt32Ty();
+  auto arrTy = cir::ArrayType::get(u32iTy, /**size=*/3);
+
+  cir::GlobalOp cpuFeatures;
+  if (auto it = module.symbolLookupCache.find("__cpu_features2");
+      it == module.symbolLookupCache.end()) {
+    cpuFeatures = module.createGlobalOp(loc, "__cpu_features2", arrTy);
+    cpuFeatures.setDSOLocal(true);
+  } else
+    cpuFeatures = cast<cir::GlobalOp>(it->second);
+
+  return builder.createGetGlobal(cpuFeatures);
+}
+
+static mlir::Value emitX86CpuSupports(CIRGenModule &module,
+                                      CIRGenBuilderTy &builder,
+                                      mlir::Location loc,
+                                      llvm::StringRef featureStr) {
+  if (!module.getASTContext().getTargetInfo().validateCpuSupports(featureStr))
+    return builder.getFalse(loc);
+
+  std::array<uint32_t, 4> cpuSupportMask =
+      llvm::X86::getCpuSupportsMask(featureStr);
+
+  auto u32iTy = builder.getUInt32Ty();
+  auto arrTy = cir::ArrayType::get(u32iTy, 1);
+  auto aligmentUnit = CharUnits::fromQuantity(4);
+
+  mlir::Value result = builder.getTrue(loc);
+  if (cpuSupportMask[0] != 0) {
+    cir::GetGlobalOp cpuModel =
+        getX86CpuModelGlobalRecord(module, builder, loc);
+    cir::GetMemberOp cpuFeatureArr = builder.createGetMember(
+        loc, builder.getPointerTo(arrTy), cpuModel, "__cpu_feature", 3);
+
+    mlir::Value feature0Ptr =
+        builder.getArrayElement(loc, loc, cpuFeatureArr, u32iTy,
+                                /**idx=*/builder.getUInt32(0, loc),
+                                /**shouldDecay=*/false);
+    cir::LoadOp feature0 =
+        builder.createAlignedLoad(loc, u32iTy, feature0Ptr, aligmentUnit);
+
+    cir::ConstantOp mask = builder.getUInt32(cpuSupportMask[0], loc);
+    mlir::Value bitset = builder.createAnd(loc, feature0, mask);
+    mlir::Value cmp =
+        builder.createCompare(loc, cir::CmpOpKind::eq, bitset, mask);
+
+    result = builder.createAnd(loc, result, cmp);
   }
-  if (builtinID == Builtin::BI__builtin_cpu_init) {
-    cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_init");
-    return mlir::Value{};
+
+  cir::GetGlobalOp cpuFeature2Arr =
+      getX86CpuFeature2GlobalRecord(module, builder, loc);
+  for (unsigned idx : llvm::seq(1, 4)) {
+    const uint32_t featureMask = cpuSupportMask[idx];
+    if (!featureMask)
+      continue;
+
+    auto featurePtr =
+        builder.getArrayElement(loc, loc, cpuFeature2Arr, u32iTy,
+                                /**idx=*/builder.getUInt32(idx - 1, loc),
+                                /**shouldDecay=*/true);
+    mlir::Value feature =
+        builder.createAlignedLoad(loc, u32iTy, featurePtr, aligmentUnit);
+
+    cir::ConstantOp mask = builder.getUInt32(featureMask, loc);
+    mlir::Value bitset = builder.createAnd(loc, feature, mask);
+    mlir::Value cmp =
+        builder.createCompare(loc, cir::CmpOpKind::eq, bitset, mask);
+
+    result = builder.createAnd(loc, result, cmp);
   }
 
+  return result;
+}
+
+static llvm::StringRef getX86CpuString(const CallExpr *expr) {
+  const Expr *cpuExpr = expr->getArg(0)->IgnoreParenCasts();
+  return cast<clang::StringLiteral>(cpuExpr)->getString();
+}
+
+std::optional<mlir::Value>
+CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
+  if (builtinID == Builtin::BI__builtin_cpu_is)
+    return emitX86CpuIs(cgm, builder, getLoc(expr->getExprLoc()),
+                        getX86CpuString(expr));
+  if (builtinID == Builtin::BI__builtin_cpu_supports)
+    return emitX86CpuSupports(cgm, builder, getLoc(expr->getExprLoc()),
+                              getX86CpuString(expr));
+  if (builtinID == Builtin::BI__builtin_cpu_init)
+    return emitX86CpuInit(cgm, builder, getLoc(expr->getExprLoc()));
+
   // Handle MSVC intrinsics before argument evaluation to prevent double
   // evaluation.
   assert(!cir::MissingFeatures::msvcBuiltins());
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/builtin-cpu-is-cputype.c 
b/clang/test/CIR/CodeGenBuiltins/X86/builtin-cpu-is-cputype.c
new file mode 100644
index 0000000000000..2920120f0e521
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/X86/builtin-cpu-is-cputype.c
@@ -0,0 +1,440 @@
+// RUN: %clang_cc1 -x c -ffreestanding -triple x86_64-unknown-linux 
-Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+
+// RUN: %clang_cc1 -x c -ffreestanding -triple x86_64-unknown-linux 
-Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
+
+// RUN: %clang_cc1 -ffreestanding -triple=x86_64-pc-linux-gnu -emit-llvm -Wall 
-Werror %s -o - | FileCheck %s -check-prefix=OGCG
+
+// Test that __builtin_cpu_is emits the correct ABI value for every CPU type,
+// in llvm/include/llvm/TargetParser/X86TargetParser.def.
+extern void a(const char *);
+
+// CIR: !rec_anon_struct = !cir.struct<{!u32i, !u32i, !u32i, !cir.array<!u32i 
x 1>}>
+// CIR: cir.global "private" external dso_local @__cpu_model : !rec_anon_struct
+// LLVM: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
+// OGCG: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
+
+#define TEST_CPU_IS(NAME, STR)                                                 
\
+  void test_##NAME(void) {                                                     
\
+    if (__builtin_cpu_is(STR))                                                 
\
+      a(STR);                                                                  
\
+  }
+
+// CIR-LABEL: cir.func no_inline dso_local @test_bonnell(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<1> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_bonnell(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 1
+
+// OGCG-LABEL: define{{.*}} void @test_bonnell(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 1
+TEST_CPU_IS(bonnell, "bonnell")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_core2(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<2> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_core2(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 2
+
+// OGCG-LABEL: define{{.*}} void @test_core2(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 2
+TEST_CPU_IS(core2, "core2")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_corei7(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<3> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_corei7(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 3
+
+// OGCG-LABEL: define{{.*}} void @test_corei7(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 3
+TEST_CPU_IS(corei7, "corei7")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_amdfam10h(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<4> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_amdfam10h(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 4
+
+// OGCG-LABEL: define{{.*}} void @test_amdfam10h(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 4
+TEST_CPU_IS(amdfam10h, "amdfam10h")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_amdfam15h(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<5> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_amdfam15h(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 5
+
+// OGCG-LABEL: define{{.*}} void @test_amdfam15h(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 5
+TEST_CPU_IS(amdfam15h, "amdfam15h")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_silvermont(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<6> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_silvermont(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 6
+
+// OGCG-LABEL: define{{.*}} void @test_silvermont(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 6
+TEST_CPU_IS(silvermont, "silvermont")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_knl(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<7> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_knl(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 7
+
+// OGCG-LABEL: define{{.*}} void @test_knl(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 7
+TEST_CPU_IS(knl, "knl")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_btver1(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<8> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_btver1(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 8
+
+// OGCG-LABEL: define{{.*}} void @test_btver1(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 8
+TEST_CPU_IS(btver1, "btver1")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_btver2(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<9> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_btver2(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 9
+
+// OGCG-LABEL: define{{.*}} void @test_btver2(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 9
+TEST_CPU_IS(btver2, "btver2")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_amdfam17h(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<10> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_amdfam17h(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 10
+
+// OGCG-LABEL: define{{.*}} void @test_amdfam17h(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 10
+TEST_CPU_IS(amdfam17h, "amdfam17h")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_knm(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<11> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_knm(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 11
+
+// OGCG-LABEL: define{{.*}} void @test_knm(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 11
+TEST_CPU_IS(knm, "knm")
+
+// CIR-LABEL: cir.func no_inline dso_local @test_goldmont(
+// CIR: [[GLOBAL:%.]] = cir.get_global @__cpu_model : 
!cir.ptr<!rec_anon_struct>
+// CIR-NEXT: [[CPUTYPE:%.]] = cir.get_member [[GLOBAL]][1] {name = 
"__cpu_type"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i>
+// CIR-NEXT: [[VALUE:%.]] = cir.load align(4) [[CPUTYPE]] : !cir.ptr<!u32i>, 
!u32i
+// CIR-NEXT: [[MASK:%.]] = cir.const #cir.int<12> : !u32i
+// CIR-NEXT: {{.*}} = cir.cmp eq [[VALUE]], [[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_goldmont(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 12
+
+// OGCG-LABEL: define{{.*}} void @test_goldmont(
+// OGCG: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr 
@__cpu_model, i64 4)
+// OGCG: = icmp eq i32 [[LOAD]], 12
+TEST_CPU_IS(goldmon...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/212143
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to