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