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 1/9] [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 2/9] 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 3/9] 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 4/9] 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 5/9] 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 6/9] 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 7/9] 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 8/9] 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 9/9] 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

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to