https://github.com/rturrado updated 
https://github.com/llvm/llvm-project/pull/173197

>From 412f88f726643427c3be6137028d4938878d3ef3 Mon Sep 17 00:00:00 2001
From: rturrado <[email protected]>
Date: Fri, 19 Dec 2025 21:02:27 +0100
Subject: [PATCH 1/2] [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 7e7424fd71878..7d05fce0fdf09 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -5762,4 +5762,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 1c87e945de846..bf9810eff498d 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>
 
@@ -1835,7 +1836,16 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_cvtneps2bf16_256_mask:
   case X86::BI__builtin_ia32_cvtneps2bf16_512_mask:
   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 eb0a219f18618..24924085ea9ea 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -4193,6 +4193,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 5cc67c09a4be35870bcadb6f946e28298a7e3242 Mon Sep 17 00:00:00 2001
From: rturrado <[email protected]>
Date: Thu, 25 Dec 2025 19:32:54 +0100
Subject: [PATCH 2/2] Address review comments from Lancern

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 17 +++++++++++------
 clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp    |  5 ++++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 19 ++++++-------------
 3 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 7d05fce0fdf09..8158ec676ab46 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -5769,9 +5769,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:
 
@@ -5784,9 +5791,7 @@ 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 bf9810eff498d..4f90b6727d80f 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>
 
@@ -1835,6 +1834,10 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_cvtneps2bf16_128_mask:
   case X86::BI__builtin_ia32_cvtneps2bf16_256_mask:
   case X86::BI__builtin_ia32_cvtneps2bf16_512_mask:
+    cgm.errorNYI(expr->getSourceRange(),
+                 std::string("unimplemented X86 builtin call: ") +
+                     getContext().BuiltinInfo.getName(builtinID));
+    return mlir::Value{};
   case X86::BI__cpuid:
   case X86::BI__cpuidex: {
     mlir::Location loc = getLoc(expr->getExprLoc());
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 24924085ea9ea..1dbac4b9e1511 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>
 
@@ -4205,21 +4206,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 {
@@ -4260,6 +4251,8 @@ mlir::LogicalResult 
CIRToLLVMCpuIdOpLowering::matchAndRewrite(
     mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), extracted, storePtr,
                                 alignment);
   }
+
+  rewriter.eraseOp(op);
   return mlir::success();
 }
 

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

Reply via email to