https://github.com/rturrado updated https://github.com/llvm/llvm-project/pull/173197
>From 111be7a4c33baac0708f20231f4930a80bc79d5d Mon Sep 17 00:00:00 2001 From: rturrado <[email protected]> Date: Fri, 19 Dec 2025 21:02:27 +0100 Subject: [PATCH] [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..c1292ac6ce241 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..f44904d1d5e05 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::Type i32Ty = builder.getSInt32Ty(); + mlir::Value subFuncId = builtinID == X86::BI__cpuidex + ? ops[2] + : builder.getConstInt(getLoc(expr->getExprLoc(), + 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>(); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
