Skip to content

Commit 963cf44

Browse files
committed
[CIR] Add InlineAsmOp lowering to LLVM
1 parent 0c87d3b commit 963cf44

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
22722272
patterns.add<CIRToLLVMCastOpLowering>(converter, patterns.getContext(), dl);
22732273
patterns.add<CIRToLLVMPtrStrideOpLowering>(converter, patterns.getContext(),
22742274
dl);
2275+
patterns.add<CIRToLLVMInlineAsmOpLowering>(converter, patterns.getContext(),
2276+
dl);
22752277
patterns.add<
22762278
// clang-format off
22772279
CIRToLLVMAssumeOpLowering,
@@ -2905,6 +2907,71 @@ mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
29052907
return mlir::success();
29062908
}
29072909

2910+
mlir::LogicalResult CIRToLLVMInlineAsmOpLowering::matchAndRewrite(
2911+
cir::InlineAsmOp op, OpAdaptor adaptor,
2912+
mlir::ConversionPatternRewriter &rewriter) const {
2913+
mlir::Type llResTy;
2914+
if (op.getNumResults())
2915+
llResTy = getTypeConverter()->convertType(op.getType(0));
2916+
2917+
auto dialect = op.getAsmFlavor();
2918+
auto llDialect = dialect == cir::AsmFlavor::x86_att
2919+
? mlir::LLVM::AsmDialect::AD_ATT
2920+
: mlir::LLVM::AsmDialect::AD_Intel;
2921+
2922+
SmallVector<mlir::Attribute> opAttrs;
2923+
auto llvmAttrName = mlir::LLVM::InlineAsmOp::getElementTypeAttrName();
2924+
2925+
// this is for the lowering to LLVM from LLVM dialect. Otherwise, if we
2926+
// don't have the result (i.e. void type as a result of operation), the
2927+
// element type attribute will be attached to the whole instruction, but not
2928+
// to the operand
2929+
if (!op.getNumResults())
2930+
opAttrs.push_back(mlir::Attribute());
2931+
2932+
SmallVector<mlir::Value> llvmOperands;
2933+
SmallVector<mlir::Value> cirOperands;
2934+
auto llvmAsmOps = adaptor.getAsmOperands();
2935+
auto cirAsmOps = op.getAsmOperands();
2936+
for (size_t i = 0; i < llvmAsmOps.size(); ++i) {
2937+
auto llvmOps = llvmAsmOps[i];
2938+
auto cirOps = cirAsmOps[i];
2939+
llvmOperands.append(llvmOps.begin(), llvmOps.end());
2940+
cirOperands.append(cirOps.begin(), cirOps.end());
2941+
}
2942+
2943+
// so far we infer the llvm dialect element type attr from
2944+
// CIR operand type.
2945+
auto cirOpAttrs = op.getOperandAttrs();
2946+
for (std::size_t i = 0; i < cirOpAttrs.size(); ++i) {
2947+
if (!cirOpAttrs[i]) {
2948+
opAttrs.push_back(mlir::Attribute());
2949+
continue;
2950+
}
2951+
2952+
SmallVector<mlir::NamedAttribute> attrs;
2953+
auto typ = cast<cir::PointerType>(cirOperands[i].getType());
2954+
auto typAttr = mlir::TypeAttr::get(convertTypeForMemory(
2955+
*getTypeConverter(), dataLayout, typ.getPointee()));
2956+
2957+
attrs.push_back(rewriter.getNamedAttr(llvmAttrName, typAttr));
2958+
auto newDict = rewriter.getDictionaryAttr(attrs);
2959+
opAttrs.push_back(newDict);
2960+
}
2961+
2962+
rewriter.replaceOpWithNewOp<mlir::LLVM::InlineAsmOp>(
2963+
op, llResTy, llvmOperands, op.getAsmStringAttr(), op.getConstraintsAttr(),
2964+
op.getSideEffectsAttr(),
2965+
/*is_align_stack*/ mlir::UnitAttr(),
2966+
/*tail_call_kind*/
2967+
mlir::LLVM::TailCallKindAttr::get(
2968+
getContext(), mlir::LLVM::tailcallkind::TailCallKind::None),
2969+
mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect),
2970+
rewriter.getArrayAttr(opAttrs));
2971+
2972+
return mlir::success();
2973+
}
2974+
29082975
std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
29092976
return std::make_unique<ConvertCIRToLLVMPass>();
29102977
}

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,23 @@ class CIRToLLVMFAbsOpLowering : public mlir::OpConversionPattern<cir::FAbsOp> {
657657
mlir::ConversionPatternRewriter &) const override;
658658
};
659659

660+
class CIRToLLVMInlineAsmOpLowering
661+
: public mlir::OpConversionPattern<cir::InlineAsmOp> {
662+
mlir::DataLayout const &dataLayout;
663+
664+
public:
665+
CIRToLLVMInlineAsmOpLowering(const mlir::TypeConverter &typeConverter,
666+
mlir::MLIRContext *context,
667+
mlir::DataLayout const &dataLayout)
668+
: OpConversionPattern(typeConverter, context), dataLayout(dataLayout) {}
669+
670+
using mlir::OpConversionPattern<cir::InlineAsmOp>::OpConversionPattern;
671+
672+
mlir::LogicalResult
673+
matchAndRewrite(cir::InlineAsmOp op, OpAdaptor,
674+
mlir::ConversionPatternRewriter &) const override;
675+
};
676+
660677
} // namespace direct
661678
} // namespace cir
662679

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// RUN: cir-translate %s -cir-to-llvmir --target x86_64-unknown-linux-gnu --disable-cc-lowering | FileCheck %s
2+
3+
!s32i = !cir.int<s, 32>
4+
!u32i = !cir.int<u, 32>
5+
6+
module {
7+
cir.func @f1() {
8+
// CHECK: call void asm "", "~{dirflag},~{fpsr},~{flags}"()
9+
cir.asm(x86_att,
10+
out = [],
11+
in = [],
12+
in_out = [],
13+
{"" "~{dirflag},~{fpsr},~{flags}"})
14+
cir.return
15+
}
16+
17+
cir.func @f2() {
18+
// CHECK: call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
19+
cir.asm(x86_att,
20+
out = [],
21+
in = [],
22+
in_out = [],
23+
{"" "~{dirflag},~{fpsr},~{flags}"}) side_effects
24+
cir.return
25+
}
26+
27+
cir.func @f3() {
28+
// CHECK: call void asm sideeffect "abc", "~{dirflag},~{fpsr},~{flags}"()
29+
cir.asm(x86_att,
30+
out = [],
31+
in = [],
32+
in_out = [],
33+
{"abc" "~{dirflag},~{fpsr},~{flags}"}) side_effects
34+
cir.return
35+
}
36+
37+
cir.func @f4(%arg0: !s32i) {
38+
%0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
39+
cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>
40+
// CHECK: call void asm sideeffect "", "*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) %2)
41+
cir.asm(x86_att,
42+
out = [],
43+
in = [%0 : !cir.ptr<!s32i> (maybe_memory)],
44+
in_out = [],
45+
{"" "*m,~{dirflag},~{fpsr},~{flags}"}) side_effects
46+
cir.return
47+
}
48+
49+
cir.func @f5() {
50+
// CHECK: call void asm inteldialect "", "~{dirflag},~{fpsr},~{flags}"()
51+
cir.asm(x86_intel,
52+
out = [],
53+
in = [],
54+
in_out = [],
55+
{"" "~{dirflag},~{fpsr},~{flags}"})
56+
cir.return
57+
}
58+
59+
cir.func @f6() -> !s32i {
60+
%0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
61+
// CHECK: %2 = call i32 asm sideeffect "movl $$42, $0", "=r,~{dirflag},~{fpsr},~{flags}"()
62+
%1 = cir.asm(x86_att,
63+
out = [],
64+
in = [],
65+
in_out = [],
66+
{"movl $$42, $0" "=r,~{dirflag},~{fpsr},~{flags}"}) side_effects -> !s32i
67+
cir.store align(4) %1, %0 : !s32i, !cir.ptr<!s32i>
68+
%3 = cir.load align(4) %0 : !cir.ptr<!s32i>, !s32i
69+
cir.return %3 : !s32i
70+
}
71+
72+
cir.func @f7(%arg0: !u32i) -> !u32i {
73+
%0 = cir.alloca !u32i, !cir.ptr<!u32i>, ["x", init] {alignment = 4 : i64}
74+
cir.store %arg0, %0 : !u32i, !cir.ptr<!u32i>
75+
%1 = cir.load align(4) %0 : !cir.ptr<!u32i>, !u32i
76+
// CHECK: %4 = call i32 asm sideeffect "addl $$42, $0", "=r,0,~{dirflag},~{fpsr},~{flags}"(i32 %3)
77+
%2 = cir.asm(x86_att,
78+
out = [],
79+
in = [],
80+
in_out = [%1 : !u32i],
81+
{"addl $$42, $0" "=r,0,~{dirflag},~{fpsr},~{flags}"}) side_effects -> !u32i
82+
cir.store align(4) %2, %0 : !u32i, !cir.ptr<!u32i>
83+
%3 = cir.load align(4) %0 : !cir.ptr<!u32i>, !u32i
84+
cir.return %3 : !u32i
85+
}
86+
}

0 commit comments

Comments
 (0)