[llvm-branch-commits] [clang] [CIR] Add InlineAsmOp lowering to LLVM (PR #153387)
Iris Shi via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Aug 14 09:00:45 PDT 2025
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.0 at 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.0 at 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.0 at owo.li>
Date: Thu, 14 Aug 2025 23:57:19 +0800
Subject: [PATCH 3/3] Address comments
Co-authored-by: Morris Hafner <mhafner at 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()));
More information about the llvm-branch-commits
mailing list