https://github.com/rturrado updated https://github.com/llvm/llvm-project/pull/173197
>From bab70fe98ebcbaa0d4a9ff13e46c22f5c7cd886c Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Fri, 19 Dec 2025 21:02:27 +0100 Subject: [PATCH 01/12] [CIR][X86] Add support for cpuid/cpuidex --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 27 +++++++ clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 12 +++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 70 +++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 50798be64551a..4998f307ee8e7 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5896,4 +5896,31 @@ def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> { }]; } +//===----------------------------------------------------------------------===// +// CpuIdOp +//===----------------------------------------------------------------------===// + +def CIR_CpuIdOp : CIR_Op<"cpuid"> { + let summary = "Get information about the CPU"; + let description = [{ + The `cir.cpuid` operation takes a base pointer to an array of 4 integers, a + function ID and a sub-function ID. The array of 4 integers is filled with + different information about the processor. + + Example: + + ```mlir + cir.cpuid %basePtr, %funcId, %subFuncId + : (!cir.ptr<!cir.array<4 x !s32i>>, !s32i, !s32i) + ``` + }]; + + let arguments = + (ins Arg<CIR_PtrToArray, "array address", [MemWrite]>:$basePtr, + CIR_SInt32:$funcId, CIR_SInt32:$subFuncId); + // TODO: remove once we can return an optional mlir::Value from + // emitX86BuiltinExpr + let results = (outs CIR_VectorType:$result); +} + #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 8bf3e63ad9179..00b50a3c74d6b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -25,6 +25,7 @@ #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/MissingFeatures.h" #include "llvm/ADT/Sequence.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/Support/ErrorHandling.h" #include <string> @@ -1949,7 +1950,16 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { return emitX86Select(builder, loc, ops[2], res, ops[1]); } case X86::BI__cpuid: - case X86::BI__cpuidex: + case X86::BI__cpuidex: { + mlir::Location loc = getLoc(expr->getExprLoc()); + mlir::Type i32Ty = builder.getSInt32Ty(); + mlir::Value subFuncId = builtinID == X86::BI__cpuidex + ? ops[2] + : builder.getConstInt(loc, sInt32Ty, 0); + cir::CpuIdOp::create(builder, loc, i32Ty, /*basePtr=*/ops[0], + /*funcId=*/ops[1], /*subFuncId=*/subFuncId); + return mlir::Value{}; + } case X86::BI__emul: case X86::BI__emulu: case X86::BI__mulh: diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 914233d8f6b8f..9d1e1e9fd2398 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -4282,6 +4282,76 @@ mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite( return mlir::failure(); } +mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( + cir::CpuIdOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type i32Ty = rewriter.getI32Type(); + mlir::Type i64Ty = rewriter.getI64Type(); + mlir::Type i32PtrTy = mlir::LLVM::LLVMPointerType::get(i32Ty.getContext(), 0); + + mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral( + rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty}); + + mlir::Value funcId = adaptor.getFuncId(); + mlir::Value subFuncId = adaptor.getSubFuncId(); + mlir::StringAttr opNameAttr = op->getAttrOfType<mlir::StringAttr>("name"); + if (!opNameAttr) + return mlir::failure(); + if (opNameAttr.getValue() == "cpuid") + subFuncId = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), i32Ty, 0); + std::vector operands{funcId, subFuncId}; + + StringRef asmString, constraints; + mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>(); + mlir::StringAttr tripleAttr = + moduleOp->getAttrOfType<mlir::StringAttr>("llvm.target_triple"); + if (!tripleAttr) + return mlir::failure(); + llvm::Triple triple(tripleAttr.getValue().str()); + if (triple.getArch() == llvm::Triple::x86) { + asmString = "cpuid"; + constraints = "={ax},={bx},={cx},={dx},{ax},{cx}"; + } else { + // x86-64 uses %rbx as the base register, so preserve it. + asmString = "xchgq %rbx, ${1:q}\n" + "cpuid\n" + "xchgq %rbx, ${1:q}"; + constraints = "={ax},=r,={cx},={dx},0,2"; + } + + mlir::Value inlineAsm = + mlir::LLVM::InlineAsmOp::create( + rewriter, op.getLoc(), cpuidRetTy, mlir::ValueRange(operands), + rewriter.getStringAttr(asmString), + rewriter.getStringAttr(constraints), + /*has_side_effects=*/mlir::UnitAttr{}, + /*is_align_stack=*/mlir::UnitAttr{}, + /*tail_call_kind=*/mlir::LLVM::TailCallKindAttr{}, + /*asm_dialect=*/mlir::LLVM::AsmDialectAttr{}, + /*operand_attrs=*/mlir::ArrayAttr{}) + .getResult(0); + + mlir::Value basePtr = adaptor.getBasePtr(); + + mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>()); + unsigned alignment = layout.getTypeABIAlignment(i32Ty); + for (unsigned i = 0; i < 4; i++) { + mlir::Value extracted = + mlir::LLVM::ExtractValueOp::create(rewriter, op.getLoc(), inlineAsm, i) + .getResult(); + mlir::Value index = mlir::LLVM::ConstantOp::create( + rewriter, op.getLoc(), i64Ty, rewriter.getI64IntegerAttr(i)); + llvm::SmallVector<mlir::Value, 1> gepIndices = {index}; + mlir::Value storePtr = mlir::LLVM::GEPOp::create( + rewriter, op.getLoc(), i32PtrTy, i32Ty, basePtr, + gepIndices, mlir::LLVM::GEPNoWrapFlags::none) + .getResult(); + mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr, + alignment); + } + return mlir::success(); +} + std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } >From 6979f456a475bfe92bbc7a286a51c56ffba26afd Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Thu, 25 Dec 2025 19:32:54 +0100 Subject: [PATCH 02/12] Address review comments from Lancern --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 18 ++++++++++----- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 1 - clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 22 +++++++++++++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 19 +++++----------- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4998f307ee8e7..3a4fe958e1804 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5903,9 +5903,16 @@ def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> { def CIR_CpuIdOp : CIR_Op<"cpuid"> { let summary = "Get information about the CPU"; let description = [{ - The `cir.cpuid` operation takes a base pointer to an array of 4 integers, a - function ID and a sub-function ID. The array of 4 integers is filled with - different information about the processor. + The `cir.cpuid` operation retrieves different types of CPU information and + stores it in an array of 4 integers. + + This operation takes 3 arguments: `basePtr`, a pointer to an array of 4 + integers; `funcID`, an integer determining what type of information to be + retrieved (for instance, basic information, processor information and + features, or cache/TLB information); and `subFuncId`, an integer that adds + more detail about what information is requested. + + As a result, the array of 4 integers is filled with the requested information. Example: @@ -5918,9 +5925,8 @@ def CIR_CpuIdOp : CIR_Op<"cpuid"> { let arguments = (ins Arg<CIR_PtrToArray, "array address", [MemWrite]>:$basePtr, CIR_SInt32:$funcId, CIR_SInt32:$subFuncId); - // TODO: remove once we can return an optional mlir::Value from - // emitX86BuiltinExpr - let results = (outs CIR_VectorType:$result); + + let hasVerifier = 1; } #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 00b50a3c74d6b..16d8b36853a93 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -25,7 +25,6 @@ #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/MissingFeatures.h" #include "llvm/ADT/Sequence.h" -#include "llvm/IR/InlineAsm.h" #include "llvm/Support/ErrorHandling.h" #include <string> diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 063896b00a5a5..6945176537c89 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -3565,6 +3565,28 @@ cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return success(); } +//===----------------------------------------------------------------------===// +// CpuIdOp +//===----------------------------------------------------------------------===// + +LogicalResult cir::CpuIdOp::verify() { + auto basePtrTy = mlir::dyn_cast<cir::PointerType>(getBasePtr().getType()); + if (!basePtrTy) + return mlir::failure(); + + auto arrayTy = mlir::dyn_cast<cir::ArrayType>(basePtrTy.getPointee()); + if (!arrayTy) + return mlir::failure(); + if (arrayTy.getSize() != 4) + return emitOpError() << "base pointer must point to an array of size 4"; + + auto intTy = mlir::dyn_cast<cir::IntType>(arrayTy.getElementType()); + if (!intTy || !intTy.isSigned() || intTy.getWidth() != 32) + return emitOpError() << "base pointer must point to an array of !s32i"; + + return mlir::success(); +} + //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 9d1e1e9fd2398..c647ceb2a4577 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -12,6 +12,7 @@ #include "LowerToLLVM.h" +#include <array> #include <deque> #include <optional> @@ -4294,21 +4295,11 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( mlir::Value funcId = adaptor.getFuncId(); mlir::Value subFuncId = adaptor.getSubFuncId(); - mlir::StringAttr opNameAttr = op->getAttrOfType<mlir::StringAttr>("name"); - if (!opNameAttr) - return mlir::failure(); - if (opNameAttr.getValue() == "cpuid") - subFuncId = mlir::LLVM::ConstantOp::create(rewriter, op.getLoc(), i32Ty, 0); - std::vector operands{funcId, subFuncId}; + std::array<mlir::Value, 2> operands{funcId, subFuncId}; StringRef asmString, constraints; - mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>(); - mlir::StringAttr tripleAttr = - moduleOp->getAttrOfType<mlir::StringAttr>("llvm.target_triple"); - if (!tripleAttr) - return mlir::failure(); - llvm::Triple triple(tripleAttr.getValue().str()); - if (triple.getArch() == llvm::Triple::x86) { + if (const llvm::Triple &triple = lowerMod->getTarget().getTriple(); + triple.getArch() == llvm::Triple::x86) { asmString = "cpuid"; constraints = "={ax},={bx},={cx},={dx},{ax},{cx}"; } else { @@ -4349,6 +4340,8 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr, alignment); } + + rewriter.eraseOp(op); return mlir::success(); } >From a9f1a2a7a68f7a49c83fb4c00fa67db64358f713 Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Wed, 7 Jan 2026 23:08:06 +0100 Subject: [PATCH 03/12] Fix cpuid/cpuidex builtin implementation These builtins do not return anything, so the first parameter is the first operand. --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 16d8b36853a93..77454552df64d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -1951,11 +1951,10 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { case X86::BI__cpuid: case X86::BI__cpuidex: { mlir::Location loc = getLoc(expr->getExprLoc()); - mlir::Type i32Ty = builder.getSInt32Ty(); mlir::Value subFuncId = builtinID == X86::BI__cpuidex ? ops[2] : builder.getConstInt(loc, sInt32Ty, 0); - cir::CpuIdOp::create(builder, loc, i32Ty, /*basePtr=*/ops[0], + cir::CpuIdOp::create(builder, loc, /*basePtr=*/ops[0], /*funcId=*/ops[1], /*subFuncId=*/subFuncId); return mlir::Value{}; } >From f30a508f6ad6e2130f326831a9a571b4dd96bb63 Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Wed, 7 Jan 2026 23:16:09 +0100 Subject: [PATCH 04/12] Change CIR_CpuIdOp to accept a pointer as first operand Arrays are usually decayed to pointers. By not restricting basePtr to be exactly a pointer to an array of 4 signed integers, we allow passing a pointer to signed integer. Extra verifications are already done at the verifier. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 8 +++++--- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 14 ++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 3a4fe958e1804..75b4870819d6d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5914,16 +5914,18 @@ def CIR_CpuIdOp : CIR_Op<"cpuid"> { As a result, the array of 4 integers is filled with the requested information. + Note that, since arrays usually decay to pointers, `basePtr` is expected to be + just a pointer to integer. Extra verifications are done at the verifier. + Example: ```mlir - cir.cpuid %basePtr, %funcId, %subFuncId - : (!cir.ptr<!cir.array<4 x !s32i>>, !s32i, !s32i) + cir.cpuid %basePtr, %funcId, %subFuncId : (!cir.ptr<!s32i>, !s32i, !s32i) ``` }]; let arguments = - (ins Arg<CIR_PtrToArray, "array address", [MemWrite]>:$basePtr, + (ins Arg<CIR_PointerType, "array address", [MemWrite]>:$basePtr, CIR_SInt32:$funcId, CIR_SInt32:$subFuncId); let hasVerifier = 1; diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 6945176537c89..ccc43bd27a6bb 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -3574,13 +3574,15 @@ LogicalResult cir::CpuIdOp::verify() { if (!basePtrTy) return mlir::failure(); - auto arrayTy = mlir::dyn_cast<cir::ArrayType>(basePtrTy.getPointee()); - if (!arrayTy) - return mlir::failure(); - if (arrayTy.getSize() != 4) - return emitOpError() << "base pointer must point to an array of size 4"; + mlir::Type type = basePtrTy.getPointee(); + + // basePtr points to an array of size at least 4 + auto arrayTy = mlir::dyn_cast<cir::ArrayType>(type); + if (arrayTy && (arrayTy.getSize() < 4)) + return emitOpError() << "base pointer must point to an array of size at least 4"; - auto intTy = mlir::dyn_cast<cir::IntType>(arrayTy.getElementType()); + // Array decay: basePtr points to !s32i + auto intTy = mlir::dyn_cast<cir::IntType>(type); if (!intTy || !intTy.isSigned() || intTy.getWidth() != 32) return emitOpError() << "base pointer must point to an array of !s32i"; >From 62f2420501ce9999bd68d56c90446f1dd72adc0e Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Wed, 7 Jan 2026 23:30:24 +0100 Subject: [PATCH 05/12] Add cpuid-builtins.c test --- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 3 +- .../CIR/CodeGenBuiltins/X86/cpuid-builtins.c | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index ccc43bd27a6bb..7a514a4f18cd7 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -3579,7 +3579,8 @@ LogicalResult cir::CpuIdOp::verify() { // basePtr points to an array of size at least 4 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(type); if (arrayTy && (arrayTy.getSize() < 4)) - return emitOpError() << "base pointer must point to an array of size at least 4"; + return emitOpError() + << "base pointer must point to an array of size at least 4"; // Array decay: basePtr points to !s32i auto intTy = mlir::dyn_cast<cir::IntType>(type); diff --git a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c new file mode 100644 index 0000000000000..5012fe2331baa --- /dev/null +++ b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir -Wall -Werror %s +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s + +#pragma intrinsic(__cpuid) + +void test__cpuid_with_array_decayed_to_pointer(int cpuInfo[4], int function_id) { + __cpuid(cpuInfo, function_id); +} +// CIR-LABEL: __cpuid_with_array_decayed_to_pointer +// CIR: %[[CPUINFO_PTR:.*]] = cir.alloca !cir.ptr<!s32i> +// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i +// CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[ZERO]]) : (!cir.ptr<!s32i>, !s32i, !s32i) + +void test__cpuid_with_array(int function_id) { + int cpuInfo[4]; + __cpuid(cpuInfo, function_id); +} +// CIR-LABEL: __cpuid_with_array +// CIR: %[[CPUINFO_PTR:.*]] = cir.alloca !cir.array<!s32i x 4> +// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i +// CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[ZERO]]) : (!cir.ptr<!s32i>, !s32i, !s32i) + +#pragma intrinsic(__cpuidex) + +void test__cpuidex(int cpuInfo[4], int function_id, int subfunction_id) { + __cpuidex(cpuInfo, function_id, subfunction_id); +} +// CIR-LABEL: __cpuidex +// CIR: %[[SUBFUNCTION_ID_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["subfunction_id" +// CIR: %[[SUBFUNCTION_ID:.*]] = cir.load {{.*}} %[[SUBFUNCTION_ID_PTR]] +// CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[SUBFUNCTION_ID]]) : (!cir.ptr<!s32i>, !s32i, !s32i) >From e9d570e948bf13aac494842cd6dded529ee732c1 Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Thu, 8 Jan 2026 19:48:26 +0100 Subject: [PATCH 06/12] Add LLVM and OGCG checks to cpuid-builtins.c test --- .../CIR/CodeGenBuiltins/X86/cpuid-builtins.c | 131 +++++++++++++++++- 1 file changed, 124 insertions(+), 7 deletions(-) diff --git a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c index 5012fe2331baa..cb2fdb8a8c7b8 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c @@ -1,31 +1,148 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir -Wall -Werror %s // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t-cir.ll -Wall -Werror %s +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s + +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -emit-llvm -o %t.ll -Wall -Werror %s +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + #pragma intrinsic(__cpuid) -void test__cpuid_with_array_decayed_to_pointer(int cpuInfo[4], int function_id) { - __cpuid(cpuInfo, function_id); +void test__cpuid_with_array_decayed_to_pointer(int cpuInfo[4], int functionId) { + __cpuid(cpuInfo, functionId); } // CIR-LABEL: __cpuid_with_array_decayed_to_pointer // CIR: %[[CPUINFO_PTR:.*]] = cir.alloca !cir.ptr<!s32i> // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i // CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[ZERO]]) : (!cir.ptr<!s32i>, !s32i, !s32i) -void test__cpuid_with_array(int function_id) { +// LLVM-LABEL: __cpuid_with_array_decayed_to_pointer +// LLVM-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca ptr +// LLVM-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 +// LLVM-DAG: [[CPU_INFO_PTR:%.*]] = load ptr, ptr [[STACK_PTR_TO_CPU_INFO_PTR]] +// LLVM-DAG: [[FUNCTION_ID:%.*]] = load i32, ptr [[STACK_PTR_TO_FUNCTION_ID]] +// LLVM-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) +// LLVM-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 +// LLVM-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 +// LLVM-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 +// LLVM-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 +// LLVM-DAG: [[ADDRPTR0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 +// LLVM-DAG: [[ADDRPTR1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 +// LLVM-DAG: [[ADDRPTR2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 +// LLVM-DAG: [[ADDRPTR3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 +// LLVM-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 +// LLVM-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 +// LLVM-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 +// LLVM-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 + +// OGCG-LABEL: __cpuid_with_array_decayed_to_pointer +// OGCG-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca ptr +// OGCG-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 +// OGCG-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 %{{.*}}, i32 0) +// OGCG-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 0 +// OGCG-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 1 +// OGCG-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 2 +// OGCG-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 3 +// OGCG-DAG: [[ADDRPTR0:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 0 +// OGCG-DAG: [[ADDRPTR1:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 1 +// OGCG-DAG: [[ADDRPTR2:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 2 +// OGCG-DAG: [[ADDRPTR3:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 3 +// OGCG-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 +// OGCG-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 +// OGCG-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 +// OGCG-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 + +void test__cpuid_with_array(int functionId) { int cpuInfo[4]; - __cpuid(cpuInfo, function_id); + __cpuid(cpuInfo, functionId); } // CIR-LABEL: __cpuid_with_array // CIR: %[[CPUINFO_PTR:.*]] = cir.alloca !cir.array<!s32i x 4> // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i // CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[ZERO]]) : (!cir.ptr<!s32i>, !s32i, !s32i) +// LLVM-LABEL: __cpuid_with_array +// LLVM-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca [4 x i32] +// LLVM-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 +// LLVM-DAG: [[CPU_INFO_PTR:%.*]] = getelementptr i32, ptr [[STACK_PTR_TO_CPU_INFO_PTR]] +// LLVM-DAG: [[FUNCTION_ID:%.*]] = load i32, ptr [[STACK_PTR_TO_FUNCTION_ID]] +// LLVM-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) +// LLVM-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 +// LLVM-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 +// LLVM-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 +// LLVM-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 +// LLVM-DAG: [[ADDRPTR0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 +// LLVM-DAG: [[ADDRPTR1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 +// LLVM-DAG: [[ADDRPTR2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 +// LLVM-DAG: [[ADDRPTR3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 +// LLVM-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 +// LLVM-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 +// LLVM-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 +// LLVM-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 + +// OGCG-LABEL: __cpuid_with_array +// OGCG-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca [4 x i32] +// OGCG-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 +// OGCG-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 %{{.*}}, i32 0) +// OGCG-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 0 +// OGCG-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 1 +// OGCG-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 2 +// OGCG-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 3 +// OGCG-DAG: [[ADDRPTR0:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 0 +// OGCG-DAG: [[ADDRPTR1:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 1 +// OGCG-DAG: [[ADDRPTR2:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 2 +// OGCG-DAG: [[ADDRPTR3:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 3 +// OGCG-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 +// OGCG-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 +// OGCG-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 +// OGCG-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 + #pragma intrinsic(__cpuidex) -void test__cpuidex(int cpuInfo[4], int function_id, int subfunction_id) { - __cpuidex(cpuInfo, function_id, subfunction_id); +void test__cpuidex(int cpuInfo[4], int functionId, int subfunctionId) { + __cpuidex(cpuInfo, functionId, subfunctionId); } // CIR-LABEL: __cpuidex -// CIR: %[[SUBFUNCTION_ID_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["subfunction_id" +// CIR: %[[SUBFUNCTION_ID_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["subfunctionId" // CIR: %[[SUBFUNCTION_ID:.*]] = cir.load {{.*}} %[[SUBFUNCTION_ID_PTR]] // CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[SUBFUNCTION_ID]]) : (!cir.ptr<!s32i>, !s32i, !s32i) + +// LLVM-LABEL: __cpuidex +// LLVM-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca ptr +// LLVM-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 +// LLVM-DAG: [[STACK_PTR_TO_SUBFUNCTION_ID:%.*]] = alloca i32 +// LLVM-DAG: [[CPU_INFO_PTR:%.*]] = load ptr, ptr [[STACK_PTR_TO_CPU_INFO_PTR]] +// LLVM-DAG: [[FUNCTION_ID:%.*]] = load i32, ptr [[STACK_PTR_TO_FUNCTION_ID]] +// LLVM-DAG: [[SUBFUNCTION_ID:%.*]] = load i32, ptr [[STACK_PTR_TO_SUBFUNCTION_ID]] +// LLVM-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 [[SUBFUNCTION_ID]]) +// LLVM-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 +// LLVM-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 +// LLVM-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 +// LLVM-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 +// LLVM-DAG: [[ADDRPTR0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 +// LLVM-DAG: [[ADDRPTR1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 +// LLVM-DAG: [[ADDRPTR2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 +// LLVM-DAG: [[ADDRPTR3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 +// LLVM-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 +// LLVM-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 +// LLVM-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 +// LLVM-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 + +// OGCG-LABEL: __cpuidex +// OGCG-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca ptr +// OGCG-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 +// OGCG-DAG: [[STACK_PTR_TO_SUBFUNCTION_ID:%.*]] = alloca i32 +// OGCG-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 %{{.*}}, i32 %{{.*}}) +// OGCG-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 0 +// OGCG-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 1 +// OGCG-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 2 +// OGCG-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 3 +// OGCG-DAG: [[ADDRPTR0:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 0 +// OGCG-DAG: [[ADDRPTR1:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 1 +// OGCG-DAG: [[ADDRPTR2:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 2 +// OGCG-DAG: [[ADDRPTR3:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 3 +// OGCG-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 +// OGCG-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 +// OGCG-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 +// OGCG-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 >From 4d467eee39e3d395a68748ab2d0956232945b63b Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Fri, 9 Jan 2026 19:26:44 +0100 Subject: [PATCH 07/12] Address comments from Andy Kaylor's review CIRDialect.cpp: remove CpuIdOp::verify(). CIROps.td: change type of cpu_info parameter to CIR_PtrToType<CIR_SInt32>. cpuid-builtins.c: remove alloca checks, change come LLVM-DAG and OGCG-DAG checks to LLVM and OGCG respectively, use variable names whenever possible. LowerToLLVM.cpp: do not use lowerMod to get the triple. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 19 +- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 25 -- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 13 +- .../CIR/CodeGenBuiltins/X86/cpuid-builtins.c | 232 +++++++++--------- 4 files changed, 131 insertions(+), 158 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 75b4870819d6d..5aee244866fc0 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5906,29 +5906,28 @@ def CIR_CpuIdOp : CIR_Op<"cpuid"> { The `cir.cpuid` operation retrieves different types of CPU information and stores it in an array of 4 integers. - This operation takes 3 arguments: `basePtr`, a pointer to an array of 4 - integers; `funcID`, an integer determining what type of information to be + This operation takes 3 arguments: `cpu_info`, a pointer to an array of 4 + integers; `function_id`, an integer determining what type of information to be retrieved (for instance, basic information, processor information and - features, or cache/TLB information); and `subFuncId`, an integer that adds + features, or cache/TLB information); and `sub_function_id`, an integer that adds more detail about what information is requested. As a result, the array of 4 integers is filled with the requested information. - Note that, since arrays usually decay to pointers, `basePtr` is expected to be - just a pointer to integer. Extra verifications are done at the verifier. - Example: ```mlir - cir.cpuid %basePtr, %funcId, %subFuncId : (!cir.ptr<!s32i>, !s32i, !s32i) + cir.cpuid %cpui_info, %function_id, %sub_function_id : (!cir.ptr<!s32i>, !s32i, !s32i) ``` }]; let arguments = - (ins Arg<CIR_PointerType, "array address", [MemWrite]>:$basePtr, - CIR_SInt32:$funcId, CIR_SInt32:$subFuncId); + (ins Arg<CIR_PtrToType<CIR_SInt32>, "array address", [MemWrite]>:$cpu_info, + CIR_SInt32:$function_id, CIR_SInt32:$sub_function_id); - let hasVerifier = 1; + let assemblyFormat = [{ + $cpu_info`,` $function_id`,` $sub_function_id `:` functional-type(operands, results) attr-dict + }]; } #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 7a514a4f18cd7..063896b00a5a5 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -3565,31 +3565,6 @@ cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) { return success(); } -//===----------------------------------------------------------------------===// -// CpuIdOp -//===----------------------------------------------------------------------===// - -LogicalResult cir::CpuIdOp::verify() { - auto basePtrTy = mlir::dyn_cast<cir::PointerType>(getBasePtr().getType()); - if (!basePtrTy) - return mlir::failure(); - - mlir::Type type = basePtrTy.getPointee(); - - // basePtr points to an array of size at least 4 - auto arrayTy = mlir::dyn_cast<cir::ArrayType>(type); - if (arrayTy && (arrayTy.getSize() < 4)) - return emitOpError() - << "base pointer must point to an array of size at least 4"; - - // Array decay: basePtr points to !s32i - auto intTy = mlir::dyn_cast<cir::IntType>(type); - if (!intTy || !intTy.isSigned() || intTy.getWidth() != 32) - return emitOpError() << "base pointer must point to an array of !s32i"; - - return mlir::success(); -} - //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index c647ceb2a4577..edfadeb7b1f0c 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -4293,13 +4293,16 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral( rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty}); - mlir::Value funcId = adaptor.getFuncId(); - mlir::Value subFuncId = adaptor.getSubFuncId(); + mlir::Value funcId = adaptor.getFunctionId(); + mlir::Value subFuncId = adaptor.getSubFunctionId(); std::array<mlir::Value, 2> operands{funcId, subFuncId}; StringRef asmString, constraints; - if (const llvm::Triple &triple = lowerMod->getTarget().getTriple(); - triple.getArch() == llvm::Triple::x86) { + mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>(); + llvm::Triple triple(mlir::cast<mlir::StringAttr>( + module->getAttr(cir::CIRDialect::getTripleAttrName())) + .getValue()); + if (triple.getArch() == llvm::Triple::x86) { asmString = "cpuid"; constraints = "={ax},={bx},={cx},={dx},{ax},{cx}"; } else { @@ -4322,7 +4325,7 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( /*operand_attrs=*/mlir::ArrayAttr{}) .getResult(0); - mlir::Value basePtr = adaptor.getBasePtr(); + mlir::Value basePtr = adaptor.getCpuInfo(); mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>()); unsigned alignment = layout.getTypeABIAlignment(i32Ty); diff --git a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c index cb2fdb8a8c7b8..94cc80566b4e7 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c @@ -9,140 +9,136 @@ #pragma intrinsic(__cpuid) -void test__cpuid_with_array_decayed_to_pointer(int cpuInfo[4], int functionId) { +void test__cpuid_with_cpu_info_as_pointer(int cpuInfo[4], int functionId) { __cpuid(cpuInfo, functionId); } -// CIR-LABEL: __cpuid_with_array_decayed_to_pointer -// CIR: %[[CPUINFO_PTR:.*]] = cir.alloca !cir.ptr<!s32i> -// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i -// CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[ZERO]]) : (!cir.ptr<!s32i>, !s32i, !s32i) +// CIR-LABEL: __cpuid_with_cpu_info_as_pointer +// CIR: [[CPU_INFO_PTR:%.*]] = cir.load align(8) +// CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) +// CIR: [[SUB_FUNCTION_ID:%.*]] = cir.const #cir.int<0> : !s32i +// CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () -// LLVM-LABEL: __cpuid_with_array_decayed_to_pointer -// LLVM-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca ptr -// LLVM-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 -// LLVM-DAG: [[CPU_INFO_PTR:%.*]] = load ptr, ptr [[STACK_PTR_TO_CPU_INFO_PTR]] -// LLVM-DAG: [[FUNCTION_ID:%.*]] = load i32, ptr [[STACK_PTR_TO_FUNCTION_ID]] -// LLVM-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) -// LLVM-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 -// LLVM-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 -// LLVM-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 -// LLVM-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 -// LLVM-DAG: [[ADDRPTR0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 -// LLVM-DAG: [[ADDRPTR1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 -// LLVM-DAG: [[ADDRPTR2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 -// LLVM-DAG: [[ADDRPTR3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 -// LLVM-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 -// LLVM-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 -// LLVM-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 -// LLVM-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 +// LLVM-LABEL: __cpuid_with_cpu_info_as_pointer +// LLVM: [[CPU_INFO_PTR:%.*]] = load ptr +// LLVM: [[FUNCTION_ID:%.*]] = load i32 +// LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) +// LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 +// LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 +// LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 +// LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 +// LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 +// LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 +// LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 +// LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 +// LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 +// LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 +// LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 +// LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 -// OGCG-LABEL: __cpuid_with_array_decayed_to_pointer -// OGCG-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca ptr -// OGCG-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 -// OGCG-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 %{{.*}}, i32 0) -// OGCG-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 0 -// OGCG-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 1 -// OGCG-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 2 -// OGCG-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 3 -// OGCG-DAG: [[ADDRPTR0:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 0 -// OGCG-DAG: [[ADDRPTR1:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 1 -// OGCG-DAG: [[ADDRPTR2:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 2 -// OGCG-DAG: [[ADDRPTR3:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 3 -// OGCG-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 -// OGCG-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 -// OGCG-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 -// OGCG-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 +// OGCG-LABEL: __cpuid_with_cpu_info_as_pointer +// OGCG: [[FUNCTION_ID:%.*]] = load i32 +// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) +// OGCG: [[CPU_INFO_PTR:%.*]] = load ptr +// OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 +// OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 +// OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 +// OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 +// OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 +// OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 +// OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 +// OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 +// OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 +// OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 +// OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 +// OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 -void test__cpuid_with_array(int functionId) { +void test__cpuid_with_cpu_info_as_array(int functionId) { int cpuInfo[4]; __cpuid(cpuInfo, functionId); } -// CIR-LABEL: __cpuid_with_array -// CIR: %[[CPUINFO_PTR:.*]] = cir.alloca !cir.array<!s32i x 4> -// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i -// CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[ZERO]]) : (!cir.ptr<!s32i>, !s32i, !s32i) +// CIR-LABEL: _cpuid_with_cpu_info_as_array +// CIR: [[CPU_INFO:%.*]] = cir.cast array_to_ptrdecay +// CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) +// CIR: [[SUB_FUNCTION_ID:%.*]] = cir.const #cir.int<0> : !s32i +// CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () -// LLVM-LABEL: __cpuid_with_array -// LLVM-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca [4 x i32] -// LLVM-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 -// LLVM-DAG: [[CPU_INFO_PTR:%.*]] = getelementptr i32, ptr [[STACK_PTR_TO_CPU_INFO_PTR]] -// LLVM-DAG: [[FUNCTION_ID:%.*]] = load i32, ptr [[STACK_PTR_TO_FUNCTION_ID]] -// LLVM-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) -// LLVM-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 -// LLVM-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 -// LLVM-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 -// LLVM-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 -// LLVM-DAG: [[ADDRPTR0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 -// LLVM-DAG: [[ADDRPTR1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 -// LLVM-DAG: [[ADDRPTR2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 -// LLVM-DAG: [[ADDRPTR3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 -// LLVM-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 -// LLVM-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 -// LLVM-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 -// LLVM-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 +// LLVM-LABEL: _cpuid_with_cpu_info_as_array +// LLVM: [[CPU_INFO_PTR:%.*]] = getelementptr i32, ptr +// LLVM: [[FUNCTION_ID:%.*]] = load i32 +// LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) +// LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 +// LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 +// LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 +// LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 +// LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 +// LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 +// LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 +// LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 +// LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 +// LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 +// LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 +// LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 -// OGCG-LABEL: __cpuid_with_array -// OGCG-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca [4 x i32] -// OGCG-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 -// OGCG-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 %{{.*}}, i32 0) -// OGCG-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 0 -// OGCG-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 1 -// OGCG-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 2 -// OGCG-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 3 -// OGCG-DAG: [[ADDRPTR0:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 0 -// OGCG-DAG: [[ADDRPTR1:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 1 -// OGCG-DAG: [[ADDRPTR2:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 2 -// OGCG-DAG: [[ADDRPTR3:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 3 -// OGCG-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 -// OGCG-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 -// OGCG-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 -// OGCG-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 +// OGCG-LABEL: _cpuid_with_cpu_info_as_array +// OGCG: [[FUNCTION_ID:%.*]] = load i32 +// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) +// OGCG: [[CPU_INFO_PTR:%.*]] = load ptr +// OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 +// OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 +// OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 +// OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 +// OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 +// OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 +// OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 +// OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 +// OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 +// OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 +// OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 +// OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 #pragma intrinsic(__cpuidex) -void test__cpuidex(int cpuInfo[4], int functionId, int subfunctionId) { - __cpuidex(cpuInfo, functionId, subfunctionId); +void test__cpuidex(int cpuInfo[4], int functionId, int subFunctionId) { + __cpuidex(cpuInfo, functionId, subFunctionId); } // CIR-LABEL: __cpuidex -// CIR: %[[SUBFUNCTION_ID_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["subfunctionId" -// CIR: %[[SUBFUNCTION_ID:.*]] = cir.load {{.*}} %[[SUBFUNCTION_ID_PTR]] -// CIR: {{.*}}cir.cpuid{{.*}}(%{{.*}}, %{{.*}}, %[[SUBFUNCTION_ID]]) : (!cir.ptr<!s32i>, !s32i, !s32i) +// CIR: [[CPU_INFO_PTR:%.*]] = cir.load align(8) +// CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) +// CIR: [[SUB_FUNCTION_ID:%.*]] = cir.load align(4) +// CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () // LLVM-LABEL: __cpuidex -// LLVM-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca ptr -// LLVM-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 -// LLVM-DAG: [[STACK_PTR_TO_SUBFUNCTION_ID:%.*]] = alloca i32 -// LLVM-DAG: [[CPU_INFO_PTR:%.*]] = load ptr, ptr [[STACK_PTR_TO_CPU_INFO_PTR]] -// LLVM-DAG: [[FUNCTION_ID:%.*]] = load i32, ptr [[STACK_PTR_TO_FUNCTION_ID]] -// LLVM-DAG: [[SUBFUNCTION_ID:%.*]] = load i32, ptr [[STACK_PTR_TO_SUBFUNCTION_ID]] -// LLVM-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 [[SUBFUNCTION_ID]]) -// LLVM-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 -// LLVM-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 -// LLVM-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 -// LLVM-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 -// LLVM-DAG: [[ADDRPTR0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 -// LLVM-DAG: [[ADDRPTR1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 -// LLVM-DAG: [[ADDRPTR2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 -// LLVM-DAG: [[ADDRPTR3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 -// LLVM-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 -// LLVM-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 -// LLVM-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 -// LLVM-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 +// LLVM: [[CPU_INFO_PTR:%.*]] = load ptr +// LLVM: [[FUNCTION_ID:%.*]] = load i32 +// LLVM: [[SUB_FUNCTION_ID:%.*]] = load i32 +// LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 [[SUB_FUNCTION_ID]]) +// LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 +// LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 +// LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 +// LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 +// LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 +// LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 +// LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 +// LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 +// LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 +// LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 +// LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 +// LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 // OGCG-LABEL: __cpuidex -// OGCG-DAG: [[STACK_PTR_TO_CPU_INFO_PTR:%.*]] = alloca ptr -// OGCG-DAG: [[STACK_PTR_TO_FUNCTION_ID:%.*]] = alloca i32 -// OGCG-DAG: [[STACK_PTR_TO_SUBFUNCTION_ID:%.*]] = alloca i32 -// OGCG-DAG: [[ASMRESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 %{{.*}}, i32 %{{.*}}) -// OGCG-DAG: [[RESULT0:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 0 -// OGCG-DAG: [[RESULT1:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 1 -// OGCG-DAG: [[RESULT2:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 2 -// OGCG-DAG: [[RESULT3:%.*]] = extractvalue { i32, i32, i32, i32 } %{{.*}}, 3 -// OGCG-DAG: [[ADDRPTR0:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 0 -// OGCG-DAG: [[ADDRPTR1:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 1 -// OGCG-DAG: [[ADDRPTR2:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 2 -// OGCG-DAG: [[ADDRPTR3:%.*]] = getelementptr inbounds i32, ptr %{{.*}}, i32 3 -// OGCG-DAG: store i32 [[RESULT0]], ptr [[ADDRPTR0]], align 4 -// OGCG-DAG: store i32 [[RESULT1]], ptr [[ADDRPTR1]], align 4 -// OGCG-DAG: store i32 [[RESULT2]], ptr [[ADDRPTR2]], align 4 -// OGCG-DAG: store i32 [[RESULT3]], ptr [[ADDRPTR3]], align 4 +// OGCG: [[FUNCTION_ID:%.*]] = load i32 +// OGCG: [[SUB_FUNCTION_ID:%.*]] = load i32 +// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 [[SUB_FUNCTION_ID]]) +// OGCG: [[CPU_INFO_PTR:%.*]] = load ptr +// OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 +// OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 +// OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 +// OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 +// OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 +// OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 +// OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 +// OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 +// OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 +// OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 +// OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 +// OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 >From e8f36296364713f928dc719dd5fcf75105636beb Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Fri, 9 Jan 2026 19:49:07 +0100 Subject: [PATCH 08/12] Fix hint names for builtin arguments --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 77454552df64d..eeecc9cdaa741 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -1954,8 +1954,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { mlir::Value subFuncId = builtinID == X86::BI__cpuidex ? ops[2] : builder.getConstInt(loc, sInt32Ty, 0); - cir::CpuIdOp::create(builder, loc, /*basePtr=*/ops[0], - /*funcId=*/ops[1], /*subFuncId=*/subFuncId); + cir::CpuIdOp::create(builder, loc, /*cpuInfo=*/ops[0], + /*functionId=*/ops[1], /*subFunctionId=*/subFuncId); return mlir::Value{}; } case X86::BI__emul: >From 1a7ff234f502ed221a57c96501925e58cd83c341 Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Fri, 9 Jan 2026 19:49:37 +0100 Subject: [PATCH 09/12] Fix tests --- clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c index 94cc80566b4e7..f466160258eef 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c @@ -37,7 +37,8 @@ void test__cpuid_with_cpu_info_as_pointer(int cpuInfo[4], int functionId) { // OGCG-LABEL: __cpuid_with_cpu_info_as_pointer // OGCG: [[FUNCTION_ID:%.*]] = load i32 -// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) +// OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 +// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 0) // OGCG: [[CPU_INFO_PTR:%.*]] = load ptr // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 @@ -81,8 +82,9 @@ void test__cpuid_with_cpu_info_as_array(int functionId) { // OGCG-LABEL: _cpuid_with_cpu_info_as_array // OGCG: [[FUNCTION_ID:%.*]] = load i32 -// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) -// OGCG: [[CPU_INFO_PTR:%.*]] = load ptr +// OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 +// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 0) +// OGCG: [[CPU_INFO_PTR:%.*]] = getelementptr inbounds [4 x i32], ptr // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 // OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 @@ -128,7 +130,9 @@ void test__cpuidex(int cpuInfo[4], int functionId, int subFunctionId) { // OGCG-LABEL: __cpuidex // OGCG: [[FUNCTION_ID:%.*]] = load i32 // OGCG: [[SUB_FUNCTION_ID:%.*]] = load i32 -// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 [[SUB_FUNCTION_ID]]) +// OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 +// OGCG: [[SUB_FUNCTION_ID_ARG:%.*]] = load i32 +// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 [[SUB_FUNCTION_ID_ARG]]) // OGCG: [[CPU_INFO_PTR:%.*]] = load ptr // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 >From fb8478e0fbb475951d8bf04ebd3c6ad2ef01ed42 Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Fri, 9 Jan 2026 20:04:52 +0100 Subject: [PATCH 10/12] Rename cpuid-builtins.c to ms-x86-intrinsics.c Add -ffreestanding flag. Move checks to inside each function. --- .../CIR/CodeGenBuiltins/X86/cpuid-builtins.c | 148 ----------------- .../CodeGenBuiltins/X86/ms-x86-intrinsics.c | 149 ++++++++++++++++++ 2 files changed, 149 insertions(+), 148 deletions(-) delete mode 100644 clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c create mode 100644 clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c diff --git a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c deleted file mode 100644 index f466160258eef..0000000000000 --- a/clang/test/CIR/CodeGenBuiltins/X86/cpuid-builtins.c +++ /dev/null @@ -1,148 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir -Wall -Werror %s -// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s - -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t-cir.ll -Wall -Werror %s -// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s - -// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -emit-llvm -o %t.ll -Wall -Werror %s -// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s - -#pragma intrinsic(__cpuid) - -void test__cpuid_with_cpu_info_as_pointer(int cpuInfo[4], int functionId) { - __cpuid(cpuInfo, functionId); -} -// CIR-LABEL: __cpuid_with_cpu_info_as_pointer -// CIR: [[CPU_INFO_PTR:%.*]] = cir.load align(8) -// CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) -// CIR: [[SUB_FUNCTION_ID:%.*]] = cir.const #cir.int<0> : !s32i -// CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () - -// LLVM-LABEL: __cpuid_with_cpu_info_as_pointer -// LLVM: [[CPU_INFO_PTR:%.*]] = load ptr -// LLVM: [[FUNCTION_ID:%.*]] = load i32 -// LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) -// LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 -// LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 -// LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 -// LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 -// LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 -// LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 -// LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 -// LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 -// LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 -// LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 -// LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 -// LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 - -// OGCG-LABEL: __cpuid_with_cpu_info_as_pointer -// OGCG: [[FUNCTION_ID:%.*]] = load i32 -// OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 -// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 0) -// OGCG: [[CPU_INFO_PTR:%.*]] = load ptr -// OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 -// OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 -// OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 -// OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 -// OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 -// OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 -// OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 -// OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 -// OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 -// OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 -// OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 -// OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 - -void test__cpuid_with_cpu_info_as_array(int functionId) { - int cpuInfo[4]; - __cpuid(cpuInfo, functionId); -} -// CIR-LABEL: _cpuid_with_cpu_info_as_array -// CIR: [[CPU_INFO:%.*]] = cir.cast array_to_ptrdecay -// CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) -// CIR: [[SUB_FUNCTION_ID:%.*]] = cir.const #cir.int<0> : !s32i -// CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () - -// LLVM-LABEL: _cpuid_with_cpu_info_as_array -// LLVM: [[CPU_INFO_PTR:%.*]] = getelementptr i32, ptr -// LLVM: [[FUNCTION_ID:%.*]] = load i32 -// LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) -// LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 -// LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 -// LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 -// LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 -// LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 -// LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 -// LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 -// LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 -// LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 -// LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 -// LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 -// LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 - -// OGCG-LABEL: _cpuid_with_cpu_info_as_array -// OGCG: [[FUNCTION_ID:%.*]] = load i32 -// OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 -// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 0) -// OGCG: [[CPU_INFO_PTR:%.*]] = getelementptr inbounds [4 x i32], ptr -// OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 -// OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 -// OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 -// OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 -// OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 -// OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 -// OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 -// OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 -// OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 -// OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 -// OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 -// OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 - -#pragma intrinsic(__cpuidex) - -void test__cpuidex(int cpuInfo[4], int functionId, int subFunctionId) { - __cpuidex(cpuInfo, functionId, subFunctionId); -} -// CIR-LABEL: __cpuidex -// CIR: [[CPU_INFO_PTR:%.*]] = cir.load align(8) -// CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) -// CIR: [[SUB_FUNCTION_ID:%.*]] = cir.load align(4) -// CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () - -// LLVM-LABEL: __cpuidex -// LLVM: [[CPU_INFO_PTR:%.*]] = load ptr -// LLVM: [[FUNCTION_ID:%.*]] = load i32 -// LLVM: [[SUB_FUNCTION_ID:%.*]] = load i32 -// LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 [[SUB_FUNCTION_ID]]) -// LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 -// LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 -// LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 -// LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 -// LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 -// LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 -// LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 -// LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 -// LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 -// LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 -// LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 -// LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 - -// OGCG-LABEL: __cpuidex -// OGCG: [[FUNCTION_ID:%.*]] = load i32 -// OGCG: [[SUB_FUNCTION_ID:%.*]] = load i32 -// OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 -// OGCG: [[SUB_FUNCTION_ID_ARG:%.*]] = load i32 -// OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 [[SUB_FUNCTION_ID_ARG]]) -// OGCG: [[CPU_INFO_PTR:%.*]] = load ptr -// OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 -// OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 -// OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 -// OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 -// OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 -// OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 -// OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 -// OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 -// OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 -// OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 -// OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 -// OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 diff --git a/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c b/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c new file mode 100644 index 0000000000000..d204a318aa821 --- /dev/null +++ b/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir -Wall -Werror %s +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s + +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t-cir.ll -Wall -Werror %s +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s + +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -fms-extensions -Wno-implicit-function-declaration -emit-llvm -o %t.ll -Wall -Werror %s +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + +#pragma intrinsic(__cpuid) +#pragma intrinsic(__cpuidex) + +void test__cpuid_with_cpu_info_as_pointer(int cpuInfo[4], int functionId) { + __cpuid(cpuInfo, functionId); + + // CIR-LABEL: __cpuid_with_cpu_info_as_pointer + // CIR: [[CPU_INFO_PTR:%.*]] = cir.load align(8) + // CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) + // CIR: [[SUB_FUNCTION_ID:%.*]] = cir.const #cir.int<0> : !s32i + // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () + + // LLVM-LABEL: __cpuid_with_cpu_info_as_pointer + // LLVM: [[CPU_INFO_PTR:%.*]] = load ptr + // LLVM: [[FUNCTION_ID:%.*]] = load i32 + // LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) + // LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 + // LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 + // LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 + // LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 + // LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + + // OGCG-LABEL: __cpuid_with_cpu_info_as_pointer + // OGCG: [[FUNCTION_ID:%.*]] = load i32 + // OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 + // OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 0) + // OGCG: [[CPU_INFO_PTR:%.*]] = load ptr + // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 + // OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 + // OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 + // OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 + // OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 +} + +void test__cpuid_with_cpu_info_as_array(int functionId) { + int cpuInfo[4]; + __cpuid(cpuInfo, functionId); + + // CIR-LABEL: _cpuid_with_cpu_info_as_array + // CIR: [[CPU_INFO:%.*]] = cir.cast array_to_ptrdecay + // CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) + // CIR: [[SUB_FUNCTION_ID:%.*]] = cir.const #cir.int<0> : !s32i + // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () + + // LLVM-LABEL: _cpuid_with_cpu_info_as_array + // LLVM: [[CPU_INFO_PTR:%.*]] = getelementptr i32, ptr + // LLVM: [[FUNCTION_ID:%.*]] = load i32 + // LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) + // LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 + // LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 + // LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 + // LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 + // LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + + // OGCG-LABEL: _cpuid_with_cpu_info_as_array + // OGCG: [[FUNCTION_ID:%.*]] = load i32 + // OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 + // OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 0) + // OGCG: [[CPU_INFO_PTR:%.*]] = getelementptr inbounds [4 x i32], ptr + // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 + // OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 + // OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 + // OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 + // OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 +} +void test__cpuidex(int cpuInfo[4], int functionId, int subFunctionId) { + __cpuidex(cpuInfo, functionId, subFunctionId); + + // CIR-LABEL: __cpuidex + // CIR: [[CPU_INFO_PTR:%.*]] = cir.load align(8) + // CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) + // CIR: [[SUB_FUNCTION_ID:%.*]] = cir.load align(4) + // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () + + // LLVM-LABEL: __cpuidex + // LLVM: [[CPU_INFO_PTR:%.*]] = load ptr + // LLVM: [[FUNCTION_ID:%.*]] = load i32 + // LLVM: [[SUB_FUNCTION_ID:%.*]] = load i32 + // LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 [[SUB_FUNCTION_ID]]) + // LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 + // LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 + // LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 + // LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 + // LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + + // OGCG-LABEL: __cpuidex + // OGCG: [[FUNCTION_ID:%.*]] = load i32 + // OGCG: [[SUB_FUNCTION_ID:%.*]] = load i32 + // OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 + // OGCG: [[SUB_FUNCTION_ID_ARG:%.*]] = load i32 + // OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 [[SUB_FUNCTION_ID_ARG]]) + // OGCG: [[CPU_INFO_PTR:%.*]] = load ptr + // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 + // OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 + // OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 + // OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 + // OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 +} >From bb16917941b9bdc38c1416b1efb02bc7e55b5bdf Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Fri, 9 Jan 2026 20:33:49 +0100 Subject: [PATCH 11/12] Address comments from Andy Kaylor's review CIROps.td: fit lines to 80 columns. LowerToLLVM.cpp: rename module to moduleOp. ms-x86-intrinsics.c: update cir.cpuid checks to new output. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 26 ++++++++++++------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 9 ++++--- .../CodeGenBuiltins/X86/ms-x86-intrinsics.c | 6 ++--- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 5aee244866fc0..775cfc98b8c01 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5907,27 +5907,33 @@ def CIR_CpuIdOp : CIR_Op<"cpuid"> { stores it in an array of 4 integers. This operation takes 3 arguments: `cpu_info`, a pointer to an array of 4 - integers; `function_id`, an integer determining what type of information to be - retrieved (for instance, basic information, processor information and - features, or cache/TLB information); and `sub_function_id`, an integer that adds - more detail about what information is requested. + integers; `function_id`, an integer determining what type of information to + be retrieved (for instance, basic information, processor information and + features, or cache/TLB information); and `sub_function_id`, an integer that + adds more detail about what information is requested. - As a result, the array of 4 integers is filled with the requested information. + As a result, the array of 4 integers is filled with the requested + information. Example: ```mlir - cir.cpuid %cpui_info, %function_id, %sub_function_id : (!cir.ptr<!s32i>, !s32i, !s32i) + cir.cpuid %cpui_info, %function_id, %sub_function_id : (!cir.ptr<!s32i>, + !s32i, !s32i) ``` }]; let arguments = - (ins Arg<CIR_PtrToType<CIR_SInt32>, "array address", [MemWrite]>:$cpu_info, - CIR_SInt32:$function_id, CIR_SInt32:$sub_function_id); + (ins Arg<CIR_PtrToType<CIR_SInt32>, "array address", + [MemWrite]>:$cpu_info, CIR_SInt32:$function_id, + CIR_SInt32:$sub_function_id); let assemblyFormat = [{ - $cpu_info`,` $function_id`,` $sub_function_id `:` functional-type(operands, results) attr-dict - }]; + $cpu_info`,` $function_id`,` $sub_function_id `:` + qualified(type($cpu_info)) `,` + type($function_id) `,` + type($sub_function_id) attr-dict + }]; } #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index edfadeb7b1f0c..80663e36a3201 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -4298,10 +4298,11 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( std::array<mlir::Value, 2> operands{funcId, subFuncId}; StringRef asmString, constraints; - mlir::ModuleOp module = op->getParentOfType<mlir::ModuleOp>(); - llvm::Triple triple(mlir::cast<mlir::StringAttr>( - module->getAttr(cir::CIRDialect::getTripleAttrName())) - .getValue()); + mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>(); + llvm::Triple triple( + mlir::cast<mlir::StringAttr>( + moduleOp->getAttr(cir::CIRDialect::getTripleAttrName())) + .getValue()); if (triple.getArch() == llvm::Triple::x86) { asmString = "cpuid"; constraints = "={ax},={bx},={cx},={dx},{ax},{cx}"; diff --git a/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c b/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c index d204a318aa821..daa31e0b7fa3f 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c @@ -17,7 +17,7 @@ void test__cpuid_with_cpu_info_as_pointer(int cpuInfo[4], int functionId) { // CIR: [[CPU_INFO_PTR:%.*]] = cir.load align(8) // CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) // CIR: [[SUB_FUNCTION_ID:%.*]] = cir.const #cir.int<0> : !s32i - // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () + // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : !cir.ptr<!s32i>, !s32i, !s32i // LLVM-LABEL: __cpuid_with_cpu_info_as_pointer // LLVM: [[CPU_INFO_PTR:%.*]] = load ptr @@ -63,7 +63,7 @@ void test__cpuid_with_cpu_info_as_array(int functionId) { // CIR: [[CPU_INFO:%.*]] = cir.cast array_to_ptrdecay // CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) // CIR: [[SUB_FUNCTION_ID:%.*]] = cir.const #cir.int<0> : !s32i - // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () + // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : !cir.ptr<!s32i>, !s32i, !s32i // LLVM-LABEL: _cpuid_with_cpu_info_as_array // LLVM: [[CPU_INFO_PTR:%.*]] = getelementptr i32, ptr @@ -107,7 +107,7 @@ void test__cpuidex(int cpuInfo[4], int functionId, int subFunctionId) { // CIR: [[CPU_INFO_PTR:%.*]] = cir.load align(8) // CIR: [[FUNCTION_ID:%.*]] = cir.load align(4) // CIR: [[SUB_FUNCTION_ID:%.*]] = cir.load align(4) - // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : (!cir.ptr<!s32i>, !s32i, !s32i) -> () + // CIR: cir.cpuid [[CPU_INFO_PTR]], [[FUNCTION_ID]], [[SUB_FUNCTION_ID]] : !cir.ptr<!s32i>, !s32i, !s32i // LLVM-LABEL: __cpuidex // LLVM: [[CPU_INFO_PTR:%.*]] = load ptr >From febd1056bd264aea39d4ea2595cf442c674ed6e5 Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Fri, 9 Jan 2026 22:46:40 +0100 Subject: [PATCH 12/12] Address comments from Andy Kaylor's review CIROps.td: use indentation of 2 spaces, and format arguments similar to how it is done in the rest of the file. LowerToLLVM.cpp: use {functionId, subFunctionId} instead of operands. ms-x86-intrinsics.c: change all LLVM-DAG and OGCG-DAG checks to LLVM and OGCG respectively. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 9 +- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 7 +- .../CodeGenBuiltins/X86/ms-x86-intrinsics.c | 144 +++++++++--------- 3 files changed, 80 insertions(+), 80 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 775cfc98b8c01..7d1c8e83c37b1 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5923,10 +5923,11 @@ def CIR_CpuIdOp : CIR_Op<"cpuid"> { ``` }]; - let arguments = - (ins Arg<CIR_PtrToType<CIR_SInt32>, "array address", - [MemWrite]>:$cpu_info, CIR_SInt32:$function_id, - CIR_SInt32:$sub_function_id); + let arguments = (ins + Arg<CIR_PtrToType<CIR_SInt32>, "array address", [MemWrite]>:$cpu_info, + CIR_SInt32:$function_id, + CIR_SInt32:$sub_function_id + ); let assemblyFormat = [{ $cpu_info`,` $function_id`,` $sub_function_id `:` diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 80663e36a3201..ad85a3c0cb222 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -4293,9 +4293,8 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( mlir::Type cpuidRetTy = mlir::LLVM::LLVMStructType::getLiteral( rewriter.getContext(), {i32Ty, i32Ty, i32Ty, i32Ty}); - mlir::Value funcId = adaptor.getFunctionId(); - mlir::Value subFuncId = adaptor.getSubFunctionId(); - std::array<mlir::Value, 2> operands{funcId, subFuncId}; + mlir::Value functionId = adaptor.getFunctionId(); + mlir::Value subFunctionId = adaptor.getSubFunctionId(); StringRef asmString, constraints; mlir::ModuleOp moduleOp = op->getParentOfType<mlir::ModuleOp>(); @@ -4316,7 +4315,7 @@ mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite( mlir::Value inlineAsm = mlir::LLVM::InlineAsmOp::create( - rewriter, op.getLoc(), cpuidRetTy, mlir::ValueRange(operands), + rewriter, op.getLoc(), cpuidRetTy, {functionId, subFunctionId}, rewriter.getStringAttr(asmString), rewriter.getStringAttr(constraints), /*has_side_effects=*/mlir::UnitAttr{}, diff --git a/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c b/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c index daa31e0b7fa3f..1f80a683aa3cd 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/ms-x86-intrinsics.c @@ -23,36 +23,36 @@ void test__cpuid_with_cpu_info_as_pointer(int cpuInfo[4], int functionId) { // LLVM: [[CPU_INFO_PTR:%.*]] = load ptr // LLVM: [[FUNCTION_ID:%.*]] = load i32 // LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) - // LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 - // LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 - // LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 - // LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 - // LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 - // LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 - // LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 - // LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 - // LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 - // LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 - // LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 - // LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + // LLVM: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // LLVM: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 + // LLVM: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // LLVM: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // LLVM: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 + // LLVM: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // LLVM: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // LLVM: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 + // LLVM: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // LLVM: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // LLVM: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 + // LLVM: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 // OGCG-LABEL: __cpuid_with_cpu_info_as_pointer // OGCG: [[FUNCTION_ID:%.*]] = load i32 // OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 // OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 0) // OGCG: [[CPU_INFO_PTR:%.*]] = load ptr - // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 - // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 - // OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 - // OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 - // OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 - // OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 - // OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 - // OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 - // OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 - // OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 - // OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 - // OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + // OGCG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // OGCG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 + // OGCG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // OGCG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // OGCG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 + // OGCG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // OGCG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // OGCG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 + // OGCG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // OGCG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // OGCG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 + // OGCG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 } void test__cpuid_with_cpu_info_as_array(int functionId) { @@ -69,36 +69,36 @@ void test__cpuid_with_cpu_info_as_array(int functionId) { // LLVM: [[CPU_INFO_PTR:%.*]] = getelementptr i32, ptr // LLVM: [[FUNCTION_ID:%.*]] = load i32 // LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 0) - // LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 - // LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 - // LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 - // LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 - // LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 - // LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 - // LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 - // LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 - // LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 - // LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 - // LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 - // LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + // LLVM: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // LLVM: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 + // LLVM: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // LLVM: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // LLVM: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 + // LLVM: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // LLVM: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // LLVM: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 + // LLVM: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // LLVM: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // LLVM: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 + // LLVM: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 // OGCG-LABEL: _cpuid_with_cpu_info_as_array // OGCG: [[FUNCTION_ID:%.*]] = load i32 // OGCG: [[FUNCTION_ID_ARG:%.*]] = load i32 // OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 0) // OGCG: [[CPU_INFO_PTR:%.*]] = getelementptr inbounds [4 x i32], ptr - // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 - // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 - // OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 - // OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 - // OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 - // OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 - // OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 - // OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 - // OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 - // OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 - // OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 - // OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + // OGCG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // OGCG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 + // OGCG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // OGCG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // OGCG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 + // OGCG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // OGCG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // OGCG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 + // OGCG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // OGCG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // OGCG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 + // OGCG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 } void test__cpuidex(int cpuInfo[4], int functionId, int subFunctionId) { __cpuidex(cpuInfo, functionId, subFunctionId); @@ -114,18 +114,18 @@ void test__cpuidex(int cpuInfo[4], int functionId, int subFunctionId) { // LLVM: [[FUNCTION_ID:%.*]] = load i32 // LLVM: [[SUB_FUNCTION_ID:%.*]] = load i32 // LLVM: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID]], i32 [[SUB_FUNCTION_ID]]) - // LLVM-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 - // LLVM-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 - // LLVM-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 - // LLVM-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 - // LLVM-DAG: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 - // LLVM-DAG: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 - // LLVM-DAG: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 - // LLVM-DAG: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 - // LLVM-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 - // LLVM-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 - // LLVM-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 - // LLVM-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + // LLVM: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // LLVM: [[ADDR_PTR_0:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 0 + // LLVM: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // LLVM: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // LLVM: [[ADDR_PTR_1:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 1 + // LLVM: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // LLVM: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // LLVM: [[ADDR_PTR_2:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 2 + // LLVM: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // LLVM: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // LLVM: [[ADDR_PTR_3:%.*]] = getelementptr i32, ptr [[CPU_INFO_PTR]], i64 3 + // LLVM: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 // OGCG-LABEL: __cpuidex // OGCG: [[FUNCTION_ID:%.*]] = load i32 @@ -134,16 +134,16 @@ void test__cpuidex(int cpuInfo[4], int functionId, int subFunctionId) { // OGCG: [[SUB_FUNCTION_ID_ARG:%.*]] = load i32 // OGCG: [[ASM_RESULTS:%.*]] = call { i32, i32, i32, i32 } asm "{{.*}}cpuid{{.*}}", "={ax},=r,={cx},={dx},0,2"(i32 [[FUNCTION_ID_ARG]], i32 [[SUB_FUNCTION_ID_ARG]]) // OGCG: [[CPU_INFO_PTR:%.*]] = load ptr - // OGCG-DAG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 - // OGCG-DAG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 - // OGCG-DAG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 - // OGCG-DAG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 - // OGCG-DAG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 - // OGCG-DAG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 - // OGCG-DAG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 - // OGCG-DAG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 - // OGCG-DAG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 - // OGCG-DAG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 - // OGCG-DAG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 - // OGCG-DAG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 + // OGCG: [[RESULT_0:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 0 + // OGCG: [[ADDR_PTR_0:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 0 + // OGCG: store i32 [[RESULT_0]], ptr [[ADDR_PTR_0]], align 4 + // OGCG: [[RESULT_1:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 1 + // OGCG: [[ADDR_PTR_1:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 1 + // OGCG: store i32 [[RESULT_1]], ptr [[ADDR_PTR_1]], align 4 + // OGCG: [[RESULT_2:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 2 + // OGCG: [[ADDR_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 2 + // OGCG: store i32 [[RESULT_2]], ptr [[ADDR_PTR_2]], align 4 + // OGCG: [[RESULT_3:%.*]] = extractvalue { i32, i32, i32, i32 } [[ASM_RESULTS]], 3 + // OGCG: [[ADDR_PTR_3:%.*]] = getelementptr inbounds i32, ptr [[CPU_INFO_PTR]], i32 3 + // OGCG: store i32 [[RESULT_3]], ptr [[ADDR_PTR_3]], align 4 } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
