[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