https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/153387
>From 963cf4441b361f9e4b6135b75d00db20e8299367 Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Wed, 13 Aug 2025 18:49:31 +0800 Subject: [PATCH 1/3] [CIR] Add InlineAsmOp lowering to LLVM --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 67 +++++++++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 17 ++++ clang/test/CIR/Lowering/inline-asm.cir | 86 +++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 clang/test/CIR/Lowering/inline-asm.cir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index ad5f52034f92a..cd36b42ce3e28 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2272,6 +2272,8 @@ void ConvertCIRToLLVMPass::runOnOperation() { patterns.add<CIRToLLVMCastOpLowering>(converter, patterns.getContext(), dl); patterns.add<CIRToLLVMPtrStrideOpLowering>(converter, patterns.getContext(), dl); + patterns.add<CIRToLLVMInlineAsmOpLowering>(converter, patterns.getContext(), + dl); patterns.add< // clang-format off CIRToLLVMAssumeOpLowering, @@ -2905,6 +2907,71 @@ mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite( + cir::InlineAsmOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type llResTy; + if (op.getNumResults()) + llResTy = getTypeConverter()->convertType(op.getType(0)); + + auto dialect = op.getAsmFlavor(); + auto llDialect = dialect == cir::AsmFlavor::x86_att + ? mlir::LLVM::AsmDialect::AD_ATT + : mlir::LLVM::AsmDialect::AD_Intel; + + SmallVector<mlir::Attribute> opAttrs; + auto llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName(); + + // this is for the lowering to LLVM from LLVM dialect. Otherwise, if we + // don't have the result (i.e. void type as a result of operation), the + // element type attribute will be attached to the whole instruction, but not + // to the operand + if (!op.getNumResults()) + opAttrs.push_back(mlir::Attribute()); + + SmallVector<mlir::Value> llvmOperands; + SmallVector<mlir::Value> cirOperands; + auto llvmAsmOps = adaptor.getAsmOperands(); + auto cirAsmOps = op.getAsmOperands(); + for (size_t i = 0; i < llvmAsmOps.size(); ++i) { + auto llvmOps = llvmAsmOps[i]; + auto cirOps = cirAsmOps[i]; + llvmOperands.append(llvmOps.begin(), llvmOps.end()); + cirOperands.append(cirOps.begin(), cirOps.end()); + } + + // so far we infer the llvm dialect element type attr from + // CIR operand type. + auto cirOpAttrs = op.getOperandAttrs(); + for (std::size_t i = 0; i < cirOpAttrs.size(); ++i) { + if (!cirOpAttrs[i]) { + opAttrs.push_back(mlir::Attribute()); + continue; + } + + SmallVector<mlir::NamedAttribute> attrs; + auto typ = cast<cir::PointerType>(cirOperands[i].getType()); + auto typAttr = mlir::TypeAttr::get(convertTypeForMemory( + *getTypeConverter(), dataLayout, typ.getPointee())); + + attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr)); + auto newDict = rewriter.getDictionaryAttr(attrs); + opAttrs.push_back(newDict); + } + + rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>( + op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(), + op.getSideEffectsAttr(), + /*is_align_stack*/ mlir::UnitAttr(), + /*tail_call_kind*/ + mlir::LLVM::TailCallKindAttr::get( + getContext(), mlir::LLVM::tailcallkind::TailCallKind::None), + mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect), + rewriter.getArrayAttr(opAttrs)); + + return mlir::success(); +} + std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index a6d2d6559005b..a77562f242432 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -657,6 +657,23 @@ class CIRToLLVMFAbsOpLowering : public mlir::OpConversionPattern<cir::FAbsOp> { mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMInlineAsmOpLowering + : public mlir::OpConversionPattern<cir::InlineAsmOp> { + mlir::DataLayout const &dataLayout; + +public: + CIRToLLVMInlineAsmOpLowering(const mlir::TypeConverter &typeConverter, + mlir::MLIRContext *context, + mlir::DataLayout const &dataLayout) + : OpConversionPattern(typeConverter, context), dataLayout(dataLayout) {} + + using mlir::OpConversionPattern<cir::InlineAsmOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::InlineAsmOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + } // namespace direct } // namespace cir diff --git a/clang/test/CIR/Lowering/inline-asm.cir b/clang/test/CIR/Lowering/inline-asm.cir new file mode 100644 index 0000000000000..a8545d4c0f059 --- /dev/null +++ b/clang/test/CIR/Lowering/inline-asm.cir @@ -0,0 +1,86 @@ +// RUN: cir-translate %s -cir-to-llvmir --target x86_64-unknown-linux-gnu --disable-cc-lowering | FileCheck %s + +!s32i = !cir.int<s, 32> +!u32i = !cir.int<u, 32> + +module { +cir.func @f1() { + // CHECK: call void asm "", "~{dirflag},~{fpsr},~{flags}"() + cir.asm(x86_att, + out = [], + in = [], + in_out = [], + {"" "~{dirflag},~{fpsr},~{flags}"}) + cir.return +} + +cir.func @f2() { + // CHECK: call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() + cir.asm(x86_att, + out = [], + in = [], + in_out = [], + {"" "~{dirflag},~{fpsr},~{flags}"}) side_effects + cir.return +} + +cir.func @f3() { + // CHECK: call void asm sideeffect "abc", "~{dirflag},~{fpsr},~{flags}"() + cir.asm(x86_att, + out = [], + in = [], + in_out = [], + {"abc" "~{dirflag},~{fpsr},~{flags}"}) side_effects + cir.return +} + +cir.func @f4(%arg0: !s32i) { + %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64} + cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i> + // CHECK: call void asm sideeffect "", "*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) %2) + cir.asm(x86_att, + out = [], + in = [%0 : !cir.ptr<!s32i> (maybe_memory)], + in_out = [], + {"" "*m,~{dirflag},~{fpsr},~{flags}"}) side_effects + cir.return +} + +cir.func @f5() { + // CHECK: call void asm inteldialect "", "~{dirflag},~{fpsr},~{flags}"() + cir.asm(x86_intel, + out = [], + in = [], + in_out = [], + {"" "~{dirflag},~{fpsr},~{flags}"}) + cir.return +} + +cir.func @f6() -> !s32i { + %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64} + // CHECK: %2 = call i32 asm sideeffect "movl $$42, $0", "=r,~{dirflag},~{fpsr},~{flags}"() + %1 = cir.asm(x86_att, + out = [], + in = [], + in_out = [], + {"movl $$42, $0" "=r,~{dirflag},~{fpsr},~{flags}"}) side_effects -> !s32i + cir.store align(4) %1, %0 : !s32i, !cir.ptr<!s32i> + %3 = cir.load align(4) %0 : !cir.ptr<!s32i>, !s32i + cir.return %3 : !s32i +} + +cir.func @f7(%arg0: !u32i) -> !u32i { + %0 = cir.alloca !u32i, !cir.ptr<!u32i>, ["x", init] {alignment = 4 : i64} + cir.store %arg0, %0 : !u32i, !cir.ptr<!u32i> + %1 = cir.load align(4) %0 : !cir.ptr<!u32i>, !u32i + // CHECK: %4 = call i32 asm sideeffect "addl $$42, $0", "=r,0,~{dirflag},~{fpsr},~{flags}"(i32 %3) + %2 = cir.asm(x86_att, + out = [], + in = [], + in_out = [%1 : !u32i], + {"addl $$42, $0" "=r,0,~{dirflag},~{fpsr},~{flags}"}) side_effects -> !u32i + cir.store align(4) %2, %0 : !u32i, !cir.ptr<!u32i> + %3 = cir.load align(4) %0 : !cir.ptr<!u32i>, !u32i + cir.return %3 : !u32i +} +} >From 0b5b910dbd5bcf549e9a9bed73198172906a8538 Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Thu, 14 Aug 2025 11:35:17 +0800 Subject: [PATCH 2/3] Apply review suggestions --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index cd36b42ce3e28..172cde0301e1b 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2914,13 +2914,13 @@ mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite( if (op.getNumResults()) llResTy = getTypeConverter()->convertType(op.getType(0)); - auto dialect = op.getAsmFlavor(); - auto llDialect = dialect == cir::AsmFlavor::x86_att - ? mlir::LLVM::AsmDialect::AD_ATT - : mlir::LLVM::AsmDialect::AD_Intel; + cir::AsmFlavor dialect = op.getAsmFlavor(); + mlir::LLVM::AsmDialect llDialect = dialect == cir::AsmFlavor::x86_att + ? mlir::LLVM::AsmDialect::AD_ATT + : mlir::LLVM::AsmDialect::AD_Intel; SmallVector<mlir::Attribute> opAttrs; - auto llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName(); + StringRef llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName(); // this is for the lowering to LLVM from LLVM dialect. Otherwise, if we // don't have the result (i.e. void type as a result of operation), the @@ -2931,31 +2931,28 @@ mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite( SmallVector<mlir::Value> llvmOperands; SmallVector<mlir::Value> cirOperands; - auto llvmAsmOps = adaptor.getAsmOperands(); - auto cirAsmOps = op.getAsmOperands(); - for (size_t i = 0; i < llvmAsmOps.size(); ++i) { - auto llvmOps = llvmAsmOps[i]; - auto cirOps = cirAsmOps[i]; - llvmOperands.append(llvmOps.begin(), llvmOps.end()); - cirOperands.append(cirOps.begin(), cirOps.end()); + for (auto [llvmOp, cirOp] : + llvm::zip(adaptor.getAsmOperands(), op.getAsmOperands())) { + llvmOperands.append(llvmOp.begin(), llvmOp.end()); + cirOperands.append(cirOp.begin(), cirOp.end()); } // so far we infer the llvm dialect element type attr from // CIR operand type. - auto cirOpAttrs = op.getOperandAttrs(); - for (std::size_t i = 0; i < cirOpAttrs.size(); ++i) { - if (!cirOpAttrs[i]) { + for (auto [i, cirOpAttr] : llvm::enumerate(op.getOperandAttrs())) { + if (!cirOpAttr) { opAttrs.push_back(mlir::Attribute()); continue; } SmallVector<mlir::NamedAttribute> attrs; - auto typ = cast<cir::PointerType>(cirOperands[i].getType()); - auto typAttr = mlir::TypeAttr::get(convertTypeForMemory( + cir::PointerType typ = + mlir::cast<cir::PointerType>(cirOperands[i].getType()); + mlir::TypeAttr typAttr = mlir::TypeAttr::get(convertTypeForMemory( *getTypeConverter(), dataLayout, typ.getPointee())); attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr)); - auto newDict = rewriter.getDictionaryAttr(attrs); + mlir::DictionaryAttr newDict = rewriter.getDictionaryAttr(attrs); opAttrs.push_back(newDict); } >From dec7dd8c9da35b30655d564978e6e623474a6540 Mon Sep 17 00:00:00 2001 From: Iris Shi <0...@owo.li> Date: Thu, 14 Aug 2025 23:57:19 +0800 Subject: [PATCH 3/3] Address comments Co-authored-by: Morris Hafner <mhaf...@nvidia.com> --- .../lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 172cde0301e1b..2546558bc66ce 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2931,23 +2931,23 @@ mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite( SmallVector<mlir::Value> llvmOperands; SmallVector<mlir::Value> cirOperands; - for (auto [llvmOp, cirOp] : - llvm::zip(adaptor.getAsmOperands(), op.getAsmOperands())) { - llvmOperands.append(llvmOp.begin(), llvmOp.end()); - cirOperands.append(cirOp.begin(), cirOp.end()); + for (auto const&[llvmOp, cirOp] : + zip(adaptor.getAsmOperands(), op.getAsmOperands())) { + append_range(llvmOperands, llvmOp); + append_range(cirOperands, cirOp); } // so far we infer the llvm dialect element type attr from // CIR operand type. - for (auto [i, cirOpAttr] : llvm::enumerate(op.getOperandAttrs())) { + for (auto const&[cirOpAttr, cirOp] : zip(op.getOperandAttrs(), cirOperands)) { if (!cirOpAttr) { opAttrs.push_back(mlir::Attribute()); continue; } - SmallVector<mlir::NamedAttribute> attrs; + llvm::SmallVector<mlir::NamedAttribute, 1> attrs; cir::PointerType typ = - mlir::cast<cir::PointerType>(cirOperands[i].getType()); + mlir::cast<cir::PointerType>(cirOp.getType()); mlir::TypeAttr typAttr = mlir::TypeAttr::get(convertTypeForMemory( *getTypeConverter(), dataLayout, typ.getPointee())); _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits