diff --git a/tests/filecheck/dialects/llvm/inline_asm.mlir b/tests/filecheck/dialects/llvm/inline_asm.mlir new file mode 100644 index 0000000000..aec189d4ac --- /dev/null +++ b/tests/filecheck/dialects/llvm/inline_asm.mlir @@ -0,0 +1,16 @@ +// RUN: XDSL_ROUNDTRIP + +%0 = "test.op"() : () -> i32 +%1 = "test.op"() : () -> i32 +"llvm.inline_asm"(%0, %1) <{asm_string = "csrw $0, $1", constraints = "i, r"}> {has_side_effect} : (i32, i32) -> () + +%2 = "test.op"() : () -> vector<8xf32> +%3 = "test.op"() : () -> vector<8xf32> +%4 = "llvm.inline_asm"(%2, %3) <{asm_dialect = 1 : i64, asm_string = "vaddps $0, $1, $2", constraints = "=x,x,x"}> : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + +// CHECK: %0 = "test.op"() : () -> i32 +// CHECK-NEXT: 1 = "test.op"() : () -> i32 +// CHECK-NEXT: "llvm.inline_asm"(%0, %1) <{"asm_string" = "csrw $0, $1", "constraints" = "i, r"}> {"has_side_effect"} : (i32, i32) -> () +// CHECK-NEXT: %2 = "test.op"() : () -> vector<8xf32> +// CHECK-NEXT: %3 = "test.op"() : () -> vector<8xf32> +// CHECK-NEXT: %4 = "llvm.inline_asm"(%2, %3) <{"asm_dialect" = 1 : i64, "asm_string" = "vaddps $0, $1, $2", "constraints" = "=x,x,x"}> : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> diff --git a/tests/filecheck/mlir-conversion/with-mlir/dialects/llvm/inline_asm.mlir b/tests/filecheck/mlir-conversion/with-mlir/dialects/llvm/inline_asm.mlir new file mode 100644 index 0000000000..acdaaf9273 --- /dev/null +++ b/tests/filecheck/mlir-conversion/with-mlir/dialects/llvm/inline_asm.mlir @@ -0,0 +1,16 @@ +/// RUN: mlir-opt %s --mlir-print-op-generic | xdsl-opt --print-op-generic | filecheck %s + +%0 = "test.op"() : () -> i32 +%1 = "test.op"() : () -> i32 +"llvm.inline_asm"(%0, %1) <{asm_string = "csrw $0, $1", constraints = "i, r"}> {has_side_effect} : (i32, i32) -> () + +%2 = "test.op"() : () -> vector<8xf32> +%3 = "test.op"() : () -> vector<8xf32> +%4 = "llvm.inline_asm"(%2, %3) <{asm_dialect = 1 : i64, asm_string = "vaddps $0, $1, $2", constraints = "=x,x,x"}> : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> + +// CHECK: %0 = "test.op"() : () -> i32 +// CHECK-NEXT: 1 = "test.op"() : () -> i32 +// CHECK-NEXT: "llvm.inline_asm"(%0, %1) <{"asm_string" = "csrw $0, $1", "constraints" = "i, r"}> {"has_side_effect"} : (i32, i32) -> () +// CHECK-NEXT: %2 = "test.op"() : () -> vector<8xf32> +// CHECK-NEXT: %3 = "test.op"() : () -> vector<8xf32> +// CHECK-NEXT: %4 = "llvm.inline_asm"(%2, %3) <{"asm_dialect" = 1 : i64, "asm_string" = "vaddps $0, $1, $2", "constraints" = "=x,x,x"}> : (vector<8xf32>, vector<8xf32>) -> vector<8xf32> diff --git a/xdsl/dialects/llvm.py b/xdsl/dialects/llvm.py index e1e943d5c9..ea62f4b73c 100644 --- a/xdsl/dialects/llvm.py +++ b/xdsl/dialects/llvm.py @@ -712,6 +712,60 @@ def __init__(self, input: SSAValue | Operation, ptr_type: Attribute | None = Non super().__init__(operands=[input], result_types=[ptr_type]) +@irdl_op_definition +class InlineAsmOp(IRDLOperation): + """ + https://mlir.llvm.org/docs/Dialects/LLVM/#llvminline_asm-llvminlineasmop + + To see what each field means, have a look at: + https://llvm.org/docs/LangRef.html#inline-assembler-expressions + """ + + name = "llvm.inline_asm" + + operands_: VarOperand = var_operand_def() + + res: OptOpResult = opt_result_def() + + # note: in MLIR upstream this is implemented as AsmDialectAttr; + # which is an instantiation of an LLVM_EnumAttr + # 0 for AT&T inline assembly dialect + # 1 for Intel inline assembly dialect + # In this context dialect does not refer to an MLIR dialect + asm_dialect = opt_prop_def(IntegerAttr[Annotated[IntegerType, IntegerType(64)]]) + + asm_string: StringAttr = prop_def(StringAttr) + constraints: StringAttr = prop_def(StringAttr) + has_side_effects: UnitAttr | None = opt_prop_def(UnitAttr) + is_align_stack: UnitAttr | None = opt_prop_def(UnitAttr) + + def __init__( + self, + operands_: list[SSAValue | Operation], + res_types: list[Attribute], + asm_string: str, + constraints: str, + asm_dialect: int = 0, + has_side_effects: bool = False, + is_align_stack: bool = False, + ): + props: dict[str, Attribute] = { + "asm_string": StringAttr(asm_string), + "constraints": StringAttr(constraints), + "asm_dialect": IntegerAttr.from_int_and_width(asm_dialect, 64), + } + if has_side_effects: + props["has_side_effects"] = UnitAttr() + if is_align_stack: + props["is_align_stack"] = UnitAttr() + + super().__init__( + operands=operands_, + properties=props, + result_types=res_types, + ) + + @irdl_op_definition class PtrToIntOp(IRDLOperation): name = "llvm.ptrtoint" @@ -1271,6 +1325,7 @@ def __init__( AShrOp, ExtractValueOp, InsertValueOp, + InlineAsmOp, UndefOp, AllocaOp, GEPOp,