[clang] f21b9cc - [CIR] Implement __builtin_cpu_supports, _init, and _is (#212900)

via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 29 21:15:46 PDT 2026


Author: Erich Keane
Date: 2026-07-29T21:15:42-07:00
New Revision: f21b9cc9c6386cc1f4b057d8af6a3fdf617cddf9

URL: https://github.com/llvm/llvm-project/commit/f21b9cc9c6386cc1f4b057d8af6a3fdf617cddf9
DIFF: https://github.com/llvm/llvm-project/commit/f21b9cc9c6386cc1f4b057d8af6a3fdf617cddf9.diff

LOG: [CIR] Implement __builtin_cpu_supports, _init, and _is (#212900)

These are pretty trivial checks to a builtin variable, so this
implements it for x86, as this shows up in self-build. The tests are
pulled from classic-codegen and shows that we do the reasonable thing
for each of them.

Added: 
    clang/test/CIR/CodeGen/builtin-cpu-is-cputype.c
    clang/test/CIR/CodeGen/builtin-cpu-is-subtype.c
    clang/test/CIR/CodeGen/builtin-cpu-is-vendor.c
    clang/test/CIR/CodeGen/builtin-cpu-supports.c

Modified: 
    clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
    clang/lib/CIR/CodeGen/CIRGenFunction.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 2369c654833cf..9c98f4bc55daa 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,20 +909,177 @@ static mlir::Value emitX86PackedByteShift(CIRGenBuilderTy &builder,
   return shuffleResult;
 }
 
+mlir::Value CIRGenFunction::emitX86CpuIs(const CallExpr *expr) {
+  const Expr *cpuExpr = expr->getArg(0)->IgnoreParenCasts();
+  StringRef cpuStr = cast<clang::StringLiteral>(cpuExpr)->getString();
+  return emitX86CpuIs(getLoc(expr->getExprLoc()), cpuStr);
+}
+
+cir::GetGlobalOp CIRGenFunction::createGetCpuModel(mlir::Location loc) {
+  mlir::Type u32 = builder.getUInt32Ty();
+  auto cpuModel =
+      mlir::dyn_cast_or_null<cir::GlobalOp>(cgm.getGlobalValue("__cpu_model"));
+
+  if (!cpuModel) {
+    // 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];
+    mlir::Type tys[] = {u32, u32, u32, cir::ArrayType::get(u32, 1)};
+    mlir::Type modelTy = builder.getAnonRecordTy(tys, /*incomplete=*/false);
+    cpuModel =
+        cgm.createGlobalOp(loc, "__cpu_model", modelTy, /*isConstant=*/false);
+    cpuModel.setDsoLocal(true);
+  }
+
+  return cir::GetGlobalOp::create(builder, loc,
+                                  builder.getPointerTo(cpuModel.getSymType()),
+                                  cpuModel.getSymName());
+}
+
+cir::GetGlobalOp CIRGenFunction::createGetCpuFeatures2(mlir::Location loc) {
+  mlir::Type u32 = builder.getUInt32Ty();
+  auto cpuFeatures2 = mlir::dyn_cast_or_null<cir::GlobalOp>(
+      cgm.getGlobalValue("__cpu_features2"));
+
+  if (!cpuFeatures2) {
+    // This is just an array of 3 uint32s.
+    mlir::Type arrTy = cir::ArrayType::get(u32, 3);
+    cpuFeatures2 =
+        cgm.createGlobalOp(loc, "__cpu_features2", arrTy, /*isConstant=*/false);
+    cpuFeatures2.setDsoLocal(true);
+  }
+
+  return cir::GetGlobalOp::create(
+      builder, loc, builder.getPointerTo(cpuFeatures2.getSymType()),
+      cpuFeatures2.getSymName());
+}
+
+mlir::Value CIRGenFunction::emitX86CpuIs(mlir::Location loc, StringRef cpuStr) {
+  mlir::Type u32 = builder.getUInt32Ty();
+  // Calculate the index needed to access the correct field based on the
+  // range. ABI_VALUE matches with compiler-rt/libgcc values.
+  auto [fieldName, index, value] =
+      llvm::StringSwitch<std::tuple<llvm::StringLiteral, unsigned, unsigned>>(
+          cpuStr)
+#define X86_VENDOR(ENUM, STRING, ABI_VALUE)                                    \
+  .Case(STRING, {"__cpu_vendor", 0u, ABI_VALUE})
+#define X86_CPU_TYPE(ENUM, STR, ABI_VALUE)                                     \
+  .Case(STR, {"__cpu_type", 1u, ABI_VALUE})
+#define X86_CPU_SUBTYPE(ENUM, STR, ABI_VALUE)                                  \
+  .Case(STR, {"__cpu_subtype", 2u, ABI_VALUE})
+#include "llvm/TargetParser/X86TargetParser.def"
+          .Default({"", 0, 0});
+  assert(value != 0 && "Invalid CPUStr passed to CpuIs");
+
+  cir::GetGlobalOp getCpuModel = createGetCpuModel(loc);
+
+  // Note: the StringSwitch above ONLY has the ability to get the first 3
+  // fields, so we don't have to worry about it being the array field.  So we
+  // can continue assuming everything is an int.
+  cir::GetMemberOp cpuValuePtr = builder.createGetMember(
+      loc, builder.getPointerTo(u32), getCpuModel, fieldName, index);
+  cir::LoadOp getVal = builder.createAlignedLoad(loc, u32, cpuValuePtr,
+                                                 CharUnits::fromQuantity(4));
+
+  return cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, getVal,
+                            builder.getUInt32(value, loc));
+}
+
+mlir::Value CIRGenFunction::emitX86CpuSupports(const CallExpr *expr) {
+  const Expr *featureExpr = expr->getArg(0)->IgnoreParenCasts();
+  StringRef featureStr = cast<StringLiteral>(featureExpr)->getString();
+  if (!getContext().getTargetInfo().validateCpuSupports(featureStr))
+    return builder.getFalse(getLoc(expr->getExprLoc()));
+  return emitX86CpuSupports(getLoc(expr->getExprLoc()), featureStr);
+}
+
+mlir::Value
+CIRGenFunction::emitX86CpuSupports(mlir::Location loc,
+                                   ArrayRef<StringRef> featureStrs) {
+  return emitX86CpuSupports(loc, llvm::X86::getCpuSupportsMask(featureStrs));
+}
+
+mlir::Value
+CIRGenFunction::emitX86CpuSupports(mlir::Location loc,
+                                   std::array<uint32_t, 4> featureMask) {
+  mlir::Type u32 = builder.getUInt32Ty();
+  mlir::Value result;
+
+  auto addCondition = [&](unsigned maskVal, mlir::Value features) {
+    cir::ConstantOp mask = builder.getUInt32(maskVal, loc);
+    mlir::Value bitset = builder.createAnd(loc, features, mask);
+    mlir::Value cmp =
+        cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, bitset, mask);
+
+    if (result)
+      result = builder.createAnd(loc, result, cmp);
+    else
+      result = cmp;
+  };
+
+  // only check the '__cpu_features[0]' if we have a non-zero value.  A zero
+  // here means to JUST check __cpu_features2.
+  if (featureMask[0] != 0) {
+    cir::GetGlobalOp getCpuModel = createGetCpuModel(loc);
+    mlir::Type u32 = builder.getUInt32Ty();
+    auto arrTy = cir::ArrayType::get(u32, 1);
+
+    // Pick out the __cpu_features field, the 4th field in the struct.
+    cir::GetMemberOp cpuFeatArrPtr = builder.createGetMember(
+        loc, builder.getPointerTo(arrTy), getCpuModel, "__cpu_features", 3);
+
+    mlir::Value cpuFeatVal = builder.getArrayElement(
+        loc, loc, cpuFeatArrPtr, arrTy,
+        /*index=*/builder.getUInt32(0, loc), /*shouldDecay=*/true);
+    cir::LoadOp features = builder.createAlignedLoad(
+        loc, u32, cpuFeatVal, CharUnits::fromQuantity(4));
+
+    addCondition(featureMask[0], features);
+  }
+
+  // the 0th index is looked up in the __cpu_model field, the rest come from an
+  // array.
+  cir::GetGlobalOp getCpuFeatures2; // = createGetCpuFeatures2(loc);
+  for (int i = 1; i != 4; ++i) {
+    const uint32_t val = featureMask[i];
+    if (!val)
+      continue;
+    if (!getCpuFeatures2)
+      getCpuFeatures2 = createGetCpuFeatures2(loc);
+    mlir::Value getArrayElt = builder.getArrayElement(
+        loc, loc, getCpuFeatures2,
+        cast<cir::PointerType>(getCpuFeatures2.getType()).getPointee(),
+        builder.getUInt32(/*index=*/i - 1, loc),
+        /*shouldDecay=*/true);
+    cir::LoadOp features = builder.createAlignedLoad(
+        loc, u32, getArrayElt, CharUnits::fromQuantity(4));
+
+    addCondition(val, features);
+  }
+
+  return result;
+}
+
+mlir::Value CIRGenFunction::emitX86CpuInit(mlir::Location loc) {
+  cir::FuncOp initFunc =
+      cgm.createRuntimeFunction(builder.getVoidFnTy(), "__cpu_indicator_init");
+  initFunc.setDsoLocal(true);
+  assert(!cir::MissingFeatures::setDLLStorageClass());
+
+  return builder.createCallOp(loc, initFunc, {}).getResult();
+}
+
 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{};
-  }
-  if (builtinID == Builtin::BI__builtin_cpu_init) {
-    cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_init");
-    return mlir::Value{};
-  }
+  if (builtinID == Builtin::BI__builtin_cpu_is)
+    return emitX86CpuIs(expr);
+  if (builtinID == Builtin::BI__builtin_cpu_supports)
+    return emitX86CpuSupports(expr);
+  if (builtinID == Builtin::BI__builtin_cpu_init)
+    return emitX86CpuInit(getLoc(expr->getExprLoc()));
 
   // Handle MSVC intrinsics before argument evaluation to prevent double
   // evaluation.

diff  --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index eec20f595c5f2..ed53fc38f6930 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -2311,7 +2311,16 @@ class CIRGenFunction : public CIRGenTypeCache {
 
   std::optional<mlir::Value> emitRISCVBuiltinExpr(unsigned builtinID,
                                                   const CallExpr *expr);
-
+  cir::GetGlobalOp createGetCpuModel(mlir::Location loc);
+  cir::GetGlobalOp createGetCpuFeatures2(mlir::Location loc);
+  mlir::Value emitX86CpuIs(const CallExpr *expr);
+  mlir::Value emitX86CpuIs(mlir::Location loc, StringRef cpuStr);
+  mlir::Value emitX86CpuSupports(const CallExpr *expr);
+  mlir::Value emitX86CpuSupports(mlir::Location loc,
+                                 ArrayRef<StringRef> FeatureStrs);
+  mlir::Value emitX86CpuSupports(mlir::Location loc,
+                                 std::array<uint32_t, 4> FeatureMask);
+  mlir::Value emitX86CpuInit(mlir::Location loc);
   std::optional<mlir::Value> emitX86BuiltinExpr(unsigned builtinID,
                                                 const CallExpr *expr);
 

diff  --git a/clang/test/CIR/CodeGen/builtin-cpu-is-cputype.c b/clang/test/CIR/CodeGen/builtin-cpu-is-cputype.c
new file mode 100644
index 0000000000000..c020fc3b141bf
--- /dev/null
+++ b/clang/test/CIR/CodeGen/builtin-cpu-is-cputype.c
@@ -0,0 +1,331 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
+
+// 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: ![[MODEL_TY:.*]] = !cir.struct<{!u32i, !u32i, !u32i, !cir.array<!u32i x 1>}>
+// CIR: cir.global "private" external dso_local @__cpu_model : ![[MODEL_TY]]
+// LLVM: @__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{{.*}}@test_bonnell(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<1> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(bonnell, "bonnell")
+
+// CIR-LABEL: cir.func{{.*}}@test_core2(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<2> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(core2, "core2")
+
+// CIR-LABEL: cir.func{{.*}}@test_corei7(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<3> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(corei7, "corei7")
+
+// CIR-LABEL: cir.func{{.*}}@test_amdfam10h(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<4> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(amdfam10h, "amdfam10h")
+
+// CIR-LABEL: cir.func{{.*}}@test_amdfam15h(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<5> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(amdfam15h, "amdfam15h")
+
+// CIR-LABEL: cir.func{{.*}}@test_silvermont(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<6> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(silvermont, "silvermont")
+
+// CIR-LABEL: cir.func{{.*}}@test_knl(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<7> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(knl, "knl")
+
+// CIR-LABEL: cir.func{{.*}}@test_btver1(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<8> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(btver1, "btver1")
+
+// CIR-LABEL: cir.func{{.*}}@test_btver2(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<9> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(btver2, "btver2")
+
+// CIR-LABEL: cir.func{{.*}}@test_amdfam17h(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<10> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(amdfam17h, "amdfam17h")
+
+// CIR-LABEL: cir.func{{.*}}@test_knm(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<11> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(knm, "knm")
+
+// CIR-LABEL: cir.func{{.*}}@test_goldmont(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<12> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[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
+TEST_CPU_IS(goldmont, "goldmont")
+
+// CIR-LABEL: cir.func{{.*}}@test_goldmont_plus(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<13> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_goldmont_plus(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 13
+TEST_CPU_IS(goldmont_plus, "goldmont-plus")
+
+// CIR-LABEL: cir.func{{.*}}@test_tremont(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<14> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_tremont(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 14
+TEST_CPU_IS(tremont, "tremont")
+
+// CIR-LABEL: cir.func{{.*}}@test_amdfam19h(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<15> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_amdfam19h(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 15
+TEST_CPU_IS(amdfam19h, "amdfam19h")
+
+// CIR-LABEL: cir.func{{.*}}@test_zhaoxin_fam7h(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<16> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_zhaoxin_fam7h(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 16
+TEST_CPU_IS(zhaoxin_fam7h, "zhaoxin_fam7h")
+
+// CIR-LABEL: cir.func{{.*}}@test_sierraforest(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<17> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_sierraforest(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 17
+TEST_CPU_IS(sierraforest, "sierraforest")
+
+// CIR-LABEL: cir.func{{.*}}@test_grandridge(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<18> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_grandridge(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 18
+TEST_CPU_IS(grandridge, "grandridge")
+
+// CIR-LABEL: cir.func{{.*}}@test_clearwaterforest(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<19> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_clearwaterforest(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 19
+TEST_CPU_IS(clearwaterforest, "clearwaterforest")
+
+// CIR-LABEL: cir.func{{.*}}@test_amdfam1ah(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<20> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_amdfam1ah(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 20
+TEST_CPU_IS(amdfam1ah, "amdfam1ah")
+
+// CIR-LABEL: cir.func{{.*}}@test_hygonfam18h(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<21> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_hygonfam18h(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 21
+TEST_CPU_IS(hygonfam18h, "hygonfam18h")
+
+// Aliases
+
+// CIR-LABEL: cir.func{{.*}}@test_atom(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<1> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_atom(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 1
+TEST_CPU_IS(atom, "atom")
+
+// CIR-LABEL: cir.func{{.*}}@test_amdfam10(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<4> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_amdfam10(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 4
+TEST_CPU_IS(amdfam10, "amdfam10")
+
+// CIR-LABEL: cir.func{{.*}}@test_amdfam15(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<5> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_amdfam15(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 5
+TEST_CPU_IS(amdfam15, "amdfam15")
+
+// CIR-LABEL: cir.func{{.*}}@test_slm(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<6> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_slm(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 6
+TEST_CPU_IS(slm, "slm")
+
+// CIR-LABEL: cir.func{{.*}}@test_amdfam1a(
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_MEM_PTR:.*]] = cir.get_member %[[GET_MODEL]][1] {name = "__cpu_type"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_TYPE:.*]]  = cir.load {{.*}}%[[GET_MEM_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<20> : !u32i
+// CIR: cir.cmp eq %[[LOAD_TYPE]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_amdfam1a(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 4)
+// LLVM: = icmp eq i32 [[LOAD]], 20
+TEST_CPU_IS(amdfam1a, "amdfam1a")

diff  --git a/clang/test/CIR/CodeGen/builtin-cpu-is-subtype.c b/clang/test/CIR/CodeGen/builtin-cpu-is-subtype.c
new file mode 100644
index 0000000000000..65be1e9ebac68
--- /dev/null
+++ b/clang/test/CIR/CodeGen/builtin-cpu-is-subtype.c
@@ -0,0 +1,596 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
+
+
+// Test that __builtin_cpu_is emits the correct ABI value for every CPU
+// subtype, llvm/include/llvm/TargetParser/X86TargetParser.def.
+extern void a(const char *);
+
+// CIR: ![[MODEL_TY:.*]] = !cir.struct<{!u32i, !u32i, !u32i, !cir.array<!u32i x 1>}>
+// CIR: cir.global "private" external dso_local @__cpu_model : ![[MODEL_TY]]
+// LLVM: @__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{{.*}} @test_nehalem(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<1> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_nehalem(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 1
+TEST_CPU_IS(nehalem, "nehalem")
+
+// CIR-LABEL: cir.func{{.*}} @test_westmere(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<2> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_westmere(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 2
+TEST_CPU_IS(westmere, "westmere")
+
+// CIR-LABEL: cir.func{{.*}} @test_sandybridge(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<3> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_sandybridge(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 3
+TEST_CPU_IS(sandybridge, "sandybridge")
+
+// CIR-LABEL: cir.func{{.*}} @test_barcelona(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<4> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_barcelona(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 4
+TEST_CPU_IS(barcelona, "barcelona")
+
+// CIR-LABEL: cir.func{{.*}} @test_shanghai(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<5> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_shanghai(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 5
+TEST_CPU_IS(shanghai, "shanghai")
+
+// CIR-LABEL: cir.func{{.*}} @test_istanbul(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<6> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_istanbul(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 6
+TEST_CPU_IS(istanbul, "istanbul")
+
+// CIR-LABEL: cir.func{{.*}} @test_bdver1(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<7> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_bdver1(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 7
+TEST_CPU_IS(bdver1, "bdver1")
+
+// CIR-LABEL: cir.func{{.*}} @test_bdver2(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<8> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_bdver2(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 8
+TEST_CPU_IS(bdver2, "bdver2")
+
+// CIR-LABEL: cir.func{{.*}} @test_bdver3(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<9> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_bdver3(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 9
+TEST_CPU_IS(bdver3, "bdver3")
+
+// CIR-LABEL: cir.func{{.*}} @test_bdver4(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<10> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_bdver4(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 10
+TEST_CPU_IS(bdver4, "bdver4")
+
+// CIR-LABEL: cir.func{{.*}} @test_znver1(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<11> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_znver1(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 11
+TEST_CPU_IS(znver1, "znver1")
+
+// CIR-LABEL: cir.func{{.*}} @test_ivybridge(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<12> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_ivybridge(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 12
+TEST_CPU_IS(ivybridge, "ivybridge")
+
+// CIR-LABEL: cir.func{{.*}} @test_haswell(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<13> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_haswell(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 13
+TEST_CPU_IS(haswell, "haswell")
+
+// CIR-LABEL: cir.func{{.*}} @test_broadwell(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<14> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_broadwell(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 14
+TEST_CPU_IS(broadwell, "broadwell")
+
+// CIR-LABEL: cir.func{{.*}} @test_skylake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<15> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_skylake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 15
+TEST_CPU_IS(skylake, "skylake")
+
+// CIR-LABEL: cir.func{{.*}} @test_skylake_avx512(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<16> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_skylake_avx512(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 16
+TEST_CPU_IS(skylake_avx512, "skylake-avx512")
+
+// CIR-LABEL: cir.func{{.*}} @test_cannonlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<17> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_cannonlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 17
+TEST_CPU_IS(cannonlake, "cannonlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_icelake_client(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<18> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_icelake_client(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 18
+TEST_CPU_IS(icelake_client, "icelake-client")
+
+// CIR-LABEL: cir.func{{.*}} @test_icelake_server(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<19> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_icelake_server(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 19
+TEST_CPU_IS(icelake_server, "icelake-server")
+
+// CIR-LABEL: cir.func{{.*}} @test_znver2(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<20> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_znver2(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 20
+TEST_CPU_IS(znver2, "znver2")
+
+// CIR-LABEL: cir.func{{.*}} @test_cascadelake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<21> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_cascadelake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 21
+TEST_CPU_IS(cascadelake, "cascadelake")
+
+// CIR-LABEL: cir.func{{.*}} @test_tigerlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<22> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_tigerlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 22
+TEST_CPU_IS(tigerlake, "tigerlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_cooperlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<23> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_cooperlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 23
+TEST_CPU_IS(cooperlake, "cooperlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_sapphirerapids(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<24> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_sapphirerapids(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 24
+TEST_CPU_IS(sapphirerapids, "sapphirerapids")
+
+// CIR-LABEL: cir.func{{.*}} @test_alderlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<25> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_alderlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 25
+TEST_CPU_IS(alderlake, "alderlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_znver3(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<26> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_znver3(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 26
+TEST_CPU_IS(znver3, "znver3")
+
+// CIR-LABEL: cir.func{{.*}} @test_rocketlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<27> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_rocketlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 27
+TEST_CPU_IS(rocketlake, "rocketlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_zhaoxin_fam7h_lujiazui(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<28> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_zhaoxin_fam7h_lujiazui(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 28
+TEST_CPU_IS(zhaoxin_fam7h_lujiazui, "zhaoxin_fam7h_lujiazui")
+
+// CIR-LABEL: cir.func{{.*}} @test_znver4(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<29> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_znver4(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 29
+TEST_CPU_IS(znver4, "znver4")
+
+// CIR-LABEL: cir.func{{.*}} @test_graniterapids(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<30> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_graniterapids(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 30
+TEST_CPU_IS(graniterapids, "graniterapids")
+
+// CIR-LABEL: cir.func{{.*}} @test_graniterapids_d(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<31> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_graniterapids_d(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 31
+TEST_CPU_IS(graniterapids_d, "graniterapids-d")
+
+// CIR-LABEL: cir.func{{.*}} @test_arrowlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<32> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_arrowlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 32
+TEST_CPU_IS(arrowlake, "arrowlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_arrowlake_s(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<33> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_arrowlake_s(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 33
+TEST_CPU_IS(arrowlake_s, "arrowlake-s")
+
+// CIR-LABEL: cir.func{{.*}} @test_pantherlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<34> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_pantherlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 34
+TEST_CPU_IS(pantherlake, "pantherlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_znver5(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<36> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_znver5(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 36
+TEST_CPU_IS(znver5, "znver5")
+
+// CIR-LABEL: cir.func{{.*}} @test_diamondrapids(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<38> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_diamondrapids(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 38
+TEST_CPU_IS(diamondrapids, "diamondrapids")
+
+// CIR-LABEL: cir.func{{.*}} @test_novalake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<39> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_novalake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 39
+TEST_CPU_IS(novalake, "novalake")
+
+// CIR-LABEL: cir.func{{.*}} @test_znver6(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<40> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_znver6(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 40
+TEST_CPU_IS(znver6, "znver6")
+
+// CIR-LABEL: cir.func{{.*}} @test_c86_4g_m4(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<41> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_c86_4g_m4(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 41
+TEST_CPU_IS(c86_4g_m4, "c86-4g-m4")
+
+// CIR-LABEL: cir.func{{.*}} @test_c86_4g_m6(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<42> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_c86_4g_m6(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 42
+TEST_CPU_IS(c86_4g_m6, "c86-4g-m6")
+
+// CIR-LABEL: cir.func{{.*}} @test_c86_4g_m7(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<43> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_c86_4g_m7(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 43
+TEST_CPU_IS(c86_4g_m7, "c86-4g-m7")
+
+// CIR-LABEL: cir.func{{.*}} @test_c86_4g_m8(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<44> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_c86_4g_m8(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 44
+TEST_CPU_IS(c86_4g_m8, "c86-4g-m8")
+
+// Aliases
+
+// CIR-LABEL: cir.func{{.*}} @test_emeraldrapids(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<24> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_emeraldrapids(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 24
+TEST_CPU_IS(emeraldrapids, "emeraldrapids")
+
+// CIR-LABEL: cir.func{{.*}} @test_raptorlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<25> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_raptorlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 25
+TEST_CPU_IS(raptorlake, "raptorlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_meteorlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<25> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_meteorlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 25
+TEST_CPU_IS(meteorlake, "meteorlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_gracemont(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<25> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_gracemont(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 25
+TEST_CPU_IS(gracemont, "gracemont")
+
+// CIR-LABEL: cir.func{{.*}} @test_lunarlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<33> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_lunarlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 33
+TEST_CPU_IS(lunarlake, "lunarlake")
+
+// CIR-LABEL: cir.func{{.*}} @test_wildcatlake(
+// CIR:  %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR:  %[[GET_ST_PTR:.*]] = cir.get_member %[[GET_MODEL]][2] {name = "__cpu_subtype"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR:  %[[ST:.*]] = cir.load {{.*}}%[[GET_ST_PTR]] : !cir.ptr<!u32i>, !u32i
+// CIR:  %[[MASK:.*]] = cir.const #cir.int<34> : !u32i
+// CIR:  cir.cmp eq %[[ST]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_wildcatlake(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 8)
+// LLVM: = icmp eq i32 [[LOAD]], 34
+TEST_CPU_IS(wildcatlake, "wildcatlake")

diff  --git a/clang/test/CIR/CodeGen/builtin-cpu-is-vendor.c b/clang/test/CIR/CodeGen/builtin-cpu-is-vendor.c
new file mode 100644
index 0000000000000..b754f8dc6c1b1
--- /dev/null
+++ b/clang/test/CIR/CodeGen/builtin-cpu-is-vendor.c
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
+
+// Test that __builtin_cpu_is emits the correct ABI value and field offset for
+// every vendor (field offset 0) in llvm/include/llvm/TargetParser/
+// X86TargetParser.def.
+extern void a(const char *);
+
+// CIR: ![[MODEL_TY:.*]] = !cir.struct<{!u32i, !u32i, !u32i, !cir.array<!u32i x 1>}>
+// CIR: cir.global "private" external dso_local @__cpu_model : ![[MODEL_TY]]
+// LLVM: @__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 {{.*}}@test_intel()
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_VENDOR:.*]] = cir.get_member %[[GET_MODEL]][0] {name = "__cpu_vendor"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_VENDOR:.*]] = cir.load {{.*}}%[[GET_VENDOR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<1> : !u32i
+// CIR: cir.cmp eq %[[LOAD_VENDOR]], %[[MASK]] : !u32i
+
+// LLVM-LABEL: define{{.*}} void @test_intel(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr @__cpu_model
+// LLVM: = icmp eq i32 [[LOAD]], 1
+TEST_CPU_IS(intel, "intel")
+
+// CIR-LABEL: cir.func {{.*}}@test_amd()
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_VENDOR:.*]] = cir.get_member %[[GET_MODEL]][0] {name = "__cpu_vendor"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_VENDOR:.*]] = cir.load {{.*}}%[[GET_VENDOR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<2> : !u32i
+// CIR: cir.cmp eq %[[LOAD_VENDOR]], %[[MASK]] : !u32i
+//
+// LLVM-LABEL: define{{.*}} void @test_amd(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr @__cpu_model
+// LLVM: = icmp eq i32 [[LOAD]], 2
+TEST_CPU_IS(amd, "amd")
+
+// CIR-LABEL: cir.func {{.*}}@test_other()
+// CIR: %[[GET_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<![[MODEL_TY]]>
+// CIR: %[[GET_VENDOR:.*]] = cir.get_member %[[GET_MODEL]][0] {name = "__cpu_vendor"} : !cir.ptr<![[MODEL_TY]]> -> !cir.ptr<!u32i>
+// CIR: %[[LOAD_VENDOR:.*]] = cir.load {{.*}}%[[GET_VENDOR]] : !cir.ptr<!u32i>, !u32i
+// CIR: %[[MASK:.*]] = cir.const #cir.int<5> : !u32i
+// CIR: cir.cmp eq %[[LOAD_VENDOR]], %[[MASK]] : !u32i
+//
+// LLVM-LABEL: define{{.*}} void @test_other(
+// LLVM: [[LOAD:%[^ ]+]] = load i32, ptr @__cpu_model
+// LLVM: = icmp eq i32 [[LOAD]], 5
+TEST_CPU_IS(other, "other")

diff  --git a/clang/test/CIR/CodeGen/builtin-cpu-supports.c b/clang/test/CIR/CodeGen/builtin-cpu-supports.c
new file mode 100644
index 0000000000000..eecde11ce26f3
--- /dev/null
+++ b/clang/test/CIR/CodeGen/builtin-cpu-supports.c
@@ -0,0 +1,229 @@
+// This is a clone of a file of the same name, but only the x86 parts, since
+// that is all we support in CIR right now.
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM,LLVMCIR
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM,OGCG
+
+// 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 *);
+
+// CIR-LABEL: cir.func{{.*}} @main() -> !s32i
+// CIR-SAME: attributes {[[ATTRS:.*]]} {
+// CIR:      cir.call @__cpu_indicator_init() : () -> ()
+// CIR-NEXT: cir.scope {
+// CIR-NEXT:   %[[CPU_MODEL:.*]] = cir.get_global @__cpu_model : !cir.ptr<!rec_anon_struct>
+// CIR-NEXT:   %[[CPU_FEAT:.*]] = cir.get_member %[[CPU_MODEL]][3] {name = "__cpu_features"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!cir.array<!u32i x 1>>
+// CIR-NEXT:   %[[ZERO:.*]] = cir.const #cir.int<0> : !u32i
+// CIR-NEXT:   %[[FEAT0:.*]] = cir.get_element %[[CPU_FEAT]][%[[ZERO]] : !u32i] : !cir.ptr<!cir.array<!u32i x 1>> -> !cir.ptr<!u32i>
+// CIR-NEXT:   %[[LOAD_FEAT0:.*]] = cir.load {{.*}} %[[FEAT0]] : !cir.ptr<!u32i>, !u32i
+// CIR-NEXT:   %[[MASK:.*]] = cir.const #cir.int<256> : !u32i
+// CIR-NEXT:   %[[AND:.*]] = cir.and %[[LOAD_FEAT0]], %[[MASK]] : !u32i
+// CIR-NEXT:   %[[RES:.*]] = cir.cmp eq %[[AND]], %[[MASK]] : !u32i
+// CIR-NEXT:   cir.if %[[RES]] {
+// CIR-NEXT:     %[[STR:.*]] = cir.get_global 
+// CIR-NEXT:     %[[STR_DECAY:.*]] = cir.cast array_to_ptrdecay %[[STR]] : !cir.ptr<!cir.array<!s8i x 7>> -> !cir.ptr<!s8i>
+// CIR-NEXT:     cir.call @a(%[[STR_DECAY]]) : (!cir.ptr<!s8i> {llvm.noundef}) -> ()
+// CIR-NEXT:   }
+// CIR-NEXT: }
+// CIR-NEXT: cir.scope {
+// CIR-NEXT:   %[[CPU_FEAT2:.*]] = cir.get_global @__cpu_features2 : !cir.ptr<!cir.array<!u32i x 3>>
+// CIR-NEXT:   %[[ZERO:.*]] = cir.const #cir.int<0> : !u32i
+// CIR-NEXT:   %[[FEAT2_0:.*]] = cir.get_element %[[CPU_FEAT2]][%[[ZERO]] : !u32i] : !cir.ptr<!cir.array<!u32i x 3>> -> !cir.ptr<!u32i>
+// CIR-NEXT:   %[[LOAD_FEAT2_0:.*]] = cir.load {{.*}} %[[FEAT2_0]] : !cir.ptr<!u32i>, !u32i
+// CIR-NEXT:   %[[MASK:.*]] = cir.const #cir.int<1> : !u32i
+// CIR-NEXT:   %[[AND:.*]] = cir.and %[[LOAD_FEAT2_0]], %[[MASK]] : !u32i
+// CIR-NEXT:   %[[RES:.*]] = cir.cmp eq %[[AND]], %[[MASK]] : !u32i
+// CIR-NEXT:   cir.if %[[RES]] {
+// CIR-NEXT:     %[[STR:.*]] = cir.get_global 
+// CIR-NEXT:     %[[STR_DECAY:.*]] = cir.cast array_to_ptrdecay %[[STR]] : !cir.ptr<!cir.array<!s8i x 5>> -> !cir.ptr<!s8i>
+// CIR-NEXT:     cir.call @a(%[[STR_DECAY]]) : (!cir.ptr<!s8i> {llvm.noundef}) -> ()
+// CIR-NEXT:   }
+// CIR-NEXT: }
+
+// LLVM-LABEL: define dso_local i32 @main(
+// LLVM-SAME: ) #[[ATTR0:[0-9]+]] {
+// OGCG-NEXT:  entry:
+// LLVM-NEXT:    [[RETVAL:%.*]] = alloca i32
+// LLVM-NEXT:    store i32 0, ptr [[RETVAL]], align 4
+// LLVM-NEXT:    call void @__cpu_indicator_init()
+//
+// CIR leaves an extra branch/newline/label here.
+// LLVMCIR-NEXT:     br label %[[BRANCH:.*]]
+// LLVMCIR:          [[BRANCH]]:
+//
+// LLVM-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_model, i64 12), align 4
+// LLVM-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 256
+// LLVM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 256
+//
+// OGCG-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// OGCG-NEXT:    br i1 [[TMP3]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+// LLVMCIR-NEXT: br i1 [[TMP2]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+//
+// LLVM:       [[IF_THEN]]:
+// LLVM-NEXT:    call void @a(ptr noundef @.str)
+// CIR has a meaningless set of empty blocks here.
+// LLVM:         br label %[[IF_END]]
+// LLVM:       [[IF_END]]:
+// CIR has more meaningless empty blocks here.
+// LLVM:         [[TMP4:%.*]] = load i32, ptr @__cpu_features2, align 4
+// LLVM-NEXT:    [[TMP5:%.*]] = and i32 [[TMP4]], 1
+// LLVM-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 1
+//
+// OGCG-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
+// OGCG-NEXT:    br i1 [[TMP7]], label %[[IF_THEN1:.*]], label %[[IF_END1:.*]]
+// LLVMCIR-NEXT: br i1 [[TMP6]], label %[[IF_THEN1:.*]], label %[[IF_END1:.*]]
+
+//
+// LLVM:       [[IF_THEN1]]:
+// LLVM-NEXT:    call void @a(ptr noundef @.str.1)
+
+int main(void) {
+  __builtin_cpu_init();
+
+  if (__builtin_cpu_supports("sse4.2"))
+    a("sse4.2");
+
+
+  if (__builtin_cpu_supports("gfni"))
+    a("gfni");
+
+
+  return 0;
+}
+
+
+// CIR-LABEL: cir.func{{.*}} @baseline() -> !s32i
+// CIR-SAME: attributes {[[ATTRS]]} {
+// CIR-NEXT: %[[RETVAL:.*]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!s32i>
+// CIR-NEXT: %[[CPU_FEAT2:.*]] = cir.get_global @__cpu_features2 : !cir.ptr<!cir.array<!u32i x 3>>
+// CIR-NEXT: %[[ONE:.*]] = cir.const #cir.int<1> : !u32i
+// CIR-NEXT: %[[FEAT2_ELT:.*]] = cir.get_element %[[CPU_FEAT2]][%[[ONE]] : !u32i] : !cir.ptr<!cir.array<!u32i x 3>> -> !cir.ptr<!u32i>
+// CIR-NEXT: %[[FEAT2_ELT_LOAD:.*]] = cir.load {{.*}} %[[FEAT2_ELT]] : !cir.ptr<!u32i>, !u32i
+// CIR-NEXT: %[[MASK:.*]] = cir.const #cir.int<2147483648> : !u32i
+// CIR-NEXT: %[[AND:.*]] = cir.and %[[FEAT2_ELT_LOAD]], %[[MASK]] : !u32i
+// CIR-NEXT: %[[RES:.*]] = cir.cmp eq %[[AND]], %[[MASK]] : !u32i
+// CIR-NEXT: %[[CAST:.*]] = cir.cast bool_to_int %[[RES]] : !cir.bool -> !s32i
+// CIR-NEXT: cir.store %[[CAST]], %[[RETVAL]] : !s32i, !cir.ptr<!s32i>
+// CIR-NEXT: %[[LOAD_RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.return %[[LOAD_RET]] : !s32i
+
+// LLVM-LABEL: define dso_local i32 @baseline(
+// LLVM-SAME: ) #[[ATTR0]] {
+// OGCG-NEXT:  entry:
+// LLVMCIR-NEXT: [[RETVAL:%.*]] = alloca i32
+// LLVM-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_features2, i64 4), align 4
+// LLVM-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], -2147483648
+// LLVM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], -2147483648
+//
+// OGCG-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// OGCG-NEXT:    [[CONV:%.*]] = zext i1 [[TMP3]] to i32
+// OGCG-NEXT:    ret i32 [[CONV]]
+//
+// LLVMCIR-NEXT: [[EXT:%.*]] = zext i1 [[TMP2]] to i32
+// LLVMCIR-NEXT: store i32 [[EXT]], ptr [[RETVAL]]
+// LLVMCIR-NEXT: [[LOAD_RET:%.*]] = load i32, ptr [[RETVAL]]
+// LLVMCIR-NEXT: ret i32 [[LOAD_RET]]
+//
+int baseline() { return __builtin_cpu_supports("x86-64"); }
+
+// CIR-LABEL: cir.func{{.*}} @v2() -> !s32i
+// CIR-SAME: attributes {[[ATTRS]]} {
+// CIR-NEXT: %[[RETVAL:.*]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!s32i>
+// CIR-NEXT: %[[CPU_FEAT2:.*]] = cir.get_global @__cpu_features2 : !cir.ptr<!cir.array<!u32i x 3>>
+// CIR-NEXT: %[[TWO:.*]] = cir.const #cir.int<2> : !u32i
+// CIR-NEXT: %[[FEAT2_ELT:.*]] = cir.get_element %[[CPU_FEAT2]][%[[TWO]] : !u32i] : !cir.ptr<!cir.array<!u32i x 3>> -> !cir.ptr<!u32i>
+// CIR-NEXT: %[[FEAT2_ELT_LOAD:.*]] = cir.load {{.*}} %[[FEAT2_ELT]] : !cir.ptr<!u32i>, !u32i
+// CIR-NEXT: %[[MASK:.*]] = cir.const #cir.int<1> : !u32i
+// CIR-NEXT: %[[AND:.*]] = cir.and %[[FEAT2_ELT_LOAD]], %[[MASK]] : !u32i
+// CIR-NEXT: %[[RES:.*]] = cir.cmp eq %[[AND]], %[[MASK]] : !u32i
+// CIR-NEXT: %[[CAST:.*]] = cir.cast bool_to_int %[[RES]] : !cir.bool -> !s32i
+// CIR-NEXT: cir.store %[[CAST]], %[[RETVAL]] : !s32i, !cir.ptr<!s32i>
+// CIR-NEXT: %[[LOAD_RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.return %[[LOAD_RET]] : !s32i
+
+// LLVM-LABEL: define dso_local i32 @v2(
+// LLVM-SAME: ) #[[ATTR0]] {
+// OGCG-NEXT:  entry:
+// LLVMCIR-NEXT: [[RETVAL:%.*]] = alloca i32
+// LLVM-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_features2, i64 8), align 4
+// LLVM-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 1
+// LLVM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1
+//
+// OGCG-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// OGCG-NEXT:    [[CONV:%.*]] = zext i1 [[TMP3]] to i32
+// OGCG-NEXT:    ret i32 [[CONV]]
+//
+// LLVMCIR-NEXT: [[EXT:%.*]] = zext i1 [[TMP2]] to i32
+// LLVMCIR-NEXT: store i32 [[EXT]], ptr [[RETVAL]]
+// LLVMCIR-NEXT: [[LOAD_RET:%.*]] = load i32, ptr [[RETVAL]]
+// LLVMCIR-NEXT: ret i32 [[LOAD_RET]]
+//
+int v2() { return __builtin_cpu_supports("x86-64-v2"); }
+
+// CIR-LABEL: cir.func{{.*}} @v3() -> !s32i
+// CIR-SAME: attributes {[[ATTRS]]} {
+// CIR-NEXT: %[[RETVAL:.*]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!s32i>
+// CIR-NEXT: %[[CPU_FEAT2:.*]] = cir.get_global @__cpu_features2 : !cir.ptr<!cir.array<!u32i x 3>>
+// CIR-NEXT: %[[TWO:.*]] = cir.const #cir.int<2> : !u32i
+// CIR-NEXT: %[[FEAT2_ELT:.*]] = cir.get_element %[[CPU_FEAT2]][%[[TWO]] : !u32i] : !cir.ptr<!cir.array<!u32i x 3>> -> !cir.ptr<!u32i>
+// CIR-NEXT: %[[FEAT2_ELT_LOAD:.*]] = cir.load {{.*}} %[[FEAT2_ELT]] : !cir.ptr<!u32i>, !u32i
+// CIR-NEXT: %[[MASK:.*]] = cir.const #cir.int<2> : !u32i
+// CIR-NEXT: %[[AND:.*]] = cir.and %[[FEAT2_ELT_LOAD]], %[[MASK]] : !u32i
+// CIR-NEXT: %[[RES:.*]] = cir.cmp eq %[[AND]], %[[MASK]] : !u32i
+// CIR-NEXT: %[[CAST:.*]] = cir.cast bool_to_int %[[RES]] : !cir.bool -> !s32i
+// CIR-NEXT: cir.store %[[CAST]], %[[RETVAL]] : !s32i, !cir.ptr<!s32i>
+// CIR-NEXT: %[[LOAD_RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.return %[[LOAD_RET]] : !s32i
+
+// LLVM-LABEL: define dso_local i32 @v3(
+// LLVM-SAME: ) #[[ATTR0]] {
+// OGCG-NEXT:  entry:
+// LLVMCIR-NEXT: [[RETVAL:%.*]] = alloca i32
+// LLVM-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_features2, i64 8), align 4
+// LLVM-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 2
+// LLVM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 2
+//
+// OGCG-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// OGCG-NEXT:    [[CONV:%.*]] = zext i1 [[TMP3]] to i32
+// OGCG-NEXT:    ret i32 [[CONV]]
+//
+// LLVMCIR-NEXT: [[EXT:%.*]] = zext i1 [[TMP2]] to i32
+// LLVMCIR-NEXT: store i32 [[EXT]], ptr [[RETVAL]]
+// LLVMCIR-NEXT: [[LOAD_RET:%.*]] = load i32, ptr [[RETVAL]]
+// LLVMCIR-NEXT: ret i32 [[LOAD_RET]]
+//
+int v3() { return __builtin_cpu_supports("x86-64-v3"); }
+
+// CIR-LABEL: cir.func{{.*}} @v4() -> !s32i
+// CIR-SAME: attributes {[[ATTRS]]} {
+// CIR-NEXT: %[[RETVAL:.*]] = cir.alloca "__retval" {{.*}} : !cir.ptr<!s32i>
+// CIR-NEXT: %[[CPU_FEAT2:.*]] = cir.get_global @__cpu_features2 : !cir.ptr<!cir.array<!u32i x 3>>
+// CIR-NEXT: %[[TWO:.*]] = cir.const #cir.int<2> : !u32i
+// CIR-NEXT: %[[FEAT2_ELT:.*]] = cir.get_element %[[CPU_FEAT2]][%[[TWO]] : !u32i] : !cir.ptr<!cir.array<!u32i x 3>> -> !cir.ptr<!u32i>
+// CIR-NEXT: %[[FEAT2_ELT_LOAD:.*]] = cir.load {{.*}} %[[FEAT2_ELT]] : !cir.ptr<!u32i>, !u32i
+// CIR-NEXT: %[[MASK:.*]] = cir.const #cir.int<4> : !u32i
+// CIR-NEXT: %[[AND:.*]] = cir.and %[[FEAT2_ELT_LOAD]], %[[MASK]] : !u32i
+// CIR-NEXT: %[[RES:.*]] = cir.cmp eq %[[AND]], %[[MASK]] : !u32i
+// CIR-NEXT: %[[CAST:.*]] = cir.cast bool_to_int %[[RES]] : !cir.bool -> !s32i
+// CIR-NEXT: cir.store %[[CAST]], %[[RETVAL]] : !s32i, !cir.ptr<!s32i>
+// CIR-NEXT: %[[LOAD_RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.return %[[LOAD_RET]] : !s32i
+
+// LLVM-LABEL: define dso_local i32 @v4(
+// LLVM-SAME: ) #[[ATTR0]] {
+// OGCG-NEXT:  entry:
+// LLVMCIR-NEXT: [[RETVAL:%.*]] = alloca i32
+// LLVM-NEXT:    [[TMP0:%.*]] = load i32, ptr getelementptr inbounds nuw (i8, ptr @__cpu_features2, i64 8), align 4
+// LLVM-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 4
+// LLVM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 4
+//
+// OGCG-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// OGCG-NEXT:    [[CONV:%.*]] = zext i1 [[TMP3]] to i32
+// OGCG-NEXT:    ret i32 [[CONV]]
+//
+// LLVMCIR-NEXT: [[EXT:%.*]] = zext i1 [[TMP2]] to i32
+// LLVMCIR-NEXT: store i32 [[EXT]], ptr [[RETVAL]]
+// LLVMCIR-NEXT: [[LOAD_RET:%.*]] = load i32, ptr [[RETVAL]]
+// LLVMCIR-NEXT: ret i32 [[LOAD_RET]]
+int v4() { return __builtin_cpu_supports("x86-64-v4"); }


        


More information about the cfe-commits mailing list