[clang] [CIR][X86] Add support for `cpuid`/`cpuidex` (PR #173197)
Roberto Turrado Camblor via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 9 11:34:52 PST 2026
https://github.com/rturrado updated https://github.com/llvm/llvm-project/pull/173197
>From bab70fe98ebcbaa0d4a9ff13e46c22f5c7cd886c Mon Sep 17 00:00:00 2001
From: rturrado <rturrado at gmail.com>
Date: Fri, 19 Dec 2025 21:02:27 +0100
Subject: [PATCH 01/11] [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 <rturrado at gmail.com>
Date: Thu, 25 Dec 2025 19:32:54 +0100
Subject: [PATCH 02/11] 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 <rturrado at gmail.com>
Date: Wed, 7 Jan 2026 23:08:06 +0100
Subject: [PATCH 03/11] 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 <rturrado at gmail.com>
Date: Wed, 7 Jan 2026 23:16:09 +0100
Subject: [PATCH 04/11] 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 <rturrado at gmail.com>
Date: Wed, 7 Jan 2026 23:30:24 +0100
Subject: [PATCH 05/11] 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 <rturrado at gmail.com>
Date: Thu, 8 Jan 2026 19:48:26 +0100
Subject: [PATCH 06/11] 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 <rturrado at gmail.com>
Date: Fri, 9 Jan 2026 19:26:44 +0100
Subject: [PATCH 07/11] 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 <rturrado at gmail.com>
Date: Fri, 9 Jan 2026 19:49:07 +0100
Subject: [PATCH 08/11] 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 <rturrado at gmail.com>
Date: Fri, 9 Jan 2026 19:49:37 +0100
Subject: [PATCH 09/11] 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 <rturrado at gmail.com>
Date: Fri, 9 Jan 2026 20:04:52 +0100
Subject: [PATCH 10/11] 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 <rturrado at gmail.com>
Date: Fri, 9 Jan 2026 20:33:49 +0100
Subject: [PATCH 11/11] 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
More information about the cfe-commits
mailing list