llvm/mlir/test/python/dialects/pdl_ops.py

# RUN: %PYTHON %s | FileCheck %s

from mlir.ir import *
from mlir.dialects.pdl import *


def constructAndPrintInModule(f):
    print("\nTEST:", f.__name__)
    with Context(), Location.unknown():
        module = Module.create()
        with InsertionPoint(module.body):
            f()
        print(module)
    return f


# CHECK: module  {
# CHECK:   pdl.pattern @operations : benefit(1)  {
# CHECK:     %0 = attribute
# CHECK:     %1 = type
# CHECK:     %2 = operation  {"attr" = %0} -> (%1 : !pdl.type)
# CHECK:     %3 = result 0 of %2
# CHECK:     %4 = operand
# CHECK:     %5 = operation(%3, %4 : !pdl.value, !pdl.value)
# CHECK:     rewrite %5 with "rewriter"
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_operations():
    pattern = PatternOp(1, "operations")
    with InsertionPoint(pattern.body):
        attr = AttributeOp()
        ty = TypeOp()
        op0 = OperationOp(attributes={"attr": attr}, types=[ty])
        op0_result = ResultOp(op0, 0)
        input = OperandOp()
        root = OperationOp(args=[op0_result, input])
        RewriteOp(root, "rewriter")


# CHECK: module  {
# CHECK:   pdl.pattern @rewrite_with_args : benefit(1)  {
# CHECK:     %0 = operand
# CHECK:     %1 = operation(%0 : !pdl.value)
# CHECK:     rewrite %1 with "rewriter"(%0 : !pdl.value)
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_rewrite_with_args():
    pattern = PatternOp(1, "rewrite_with_args")
    with InsertionPoint(pattern.body):
        input = OperandOp()
        root = OperationOp(args=[input])
        RewriteOp(root, "rewriter", args=[input])


# CHECK: module  {
# CHECK:   pdl.pattern @rewrite_multi_root_optimal : benefit(1)  {
# CHECK:     %0 = operand
# CHECK:     %1 = operand
# CHECK:     %2 = type
# CHECK:     %3 = operation(%0 : !pdl.value)  -> (%2 : !pdl.type)
# CHECK:     %4 = result 0 of %3
# CHECK:     %5 = operation(%4 : !pdl.value)
# CHECK:     %6 = operation(%1 : !pdl.value)  -> (%2 : !pdl.type)
# CHECK:     %7 = result 0 of %6
# CHECK:     %8 = operation(%4, %7 : !pdl.value, !pdl.value)
# CHECK:     rewrite with "rewriter"(%5, %8 : !pdl.operation, !pdl.operation)
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_rewrite_multi_root_optimal():
    pattern = PatternOp(1, "rewrite_multi_root_optimal")
    with InsertionPoint(pattern.body):
        input1 = OperandOp()
        input2 = OperandOp()
        ty = TypeOp()
        op1 = OperationOp(args=[input1], types=[ty])
        val1 = ResultOp(op1, 0)
        root1 = OperationOp(args=[val1])
        op2 = OperationOp(args=[input2], types=[ty])
        val2 = ResultOp(op2, 0)
        root2 = OperationOp(args=[val1, val2])
        RewriteOp(name="rewriter", args=[root1, root2])


# CHECK: module  {
# CHECK:   pdl.pattern @rewrite_multi_root_forced : benefit(1)  {
# CHECK:     %0 = operand
# CHECK:     %1 = operand
# CHECK:     %2 = type
# CHECK:     %3 = operation(%0 : !pdl.value)  -> (%2 : !pdl.type)
# CHECK:     %4 = result 0 of %3
# CHECK:     %5 = operation(%4 : !pdl.value)
# CHECK:     %6 = operation(%1 : !pdl.value)  -> (%2 : !pdl.type)
# CHECK:     %7 = result 0 of %6
# CHECK:     %8 = operation(%4, %7 : !pdl.value, !pdl.value)
# CHECK:     rewrite %5 with "rewriter"(%8 : !pdl.operation)
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_rewrite_multi_root_forced():
    pattern = PatternOp(1, "rewrite_multi_root_forced")
    with InsertionPoint(pattern.body):
        input1 = OperandOp()
        input2 = OperandOp()
        ty = TypeOp()
        op1 = OperationOp(args=[input1], types=[ty])
        val1 = ResultOp(op1, 0)
        root1 = OperationOp(args=[val1])
        op2 = OperationOp(args=[input2], types=[ty])
        val2 = ResultOp(op2, 0)
        root2 = OperationOp(args=[val1, val2])
        RewriteOp(root1, name="rewriter", args=[root2])


# CHECK: module  {
# CHECK:   pdl.pattern @rewrite_add_body : benefit(1)  {
# CHECK:     %0 = type : i32
# CHECK:     %1 = type
# CHECK:     %2 = operation  -> (%0, %1 : !pdl.type, !pdl.type)
# CHECK:     rewrite %2  {
# CHECK:       %3 = type
# CHECK:       %4 = operation "foo.op"  -> (%0, %3 : !pdl.type, !pdl.type)
# CHECK:       replace %2 with %4
# CHECK:     }
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_rewrite_add_body():
    pattern = PatternOp(1, "rewrite_add_body")
    with InsertionPoint(pattern.body):
        ty1 = TypeOp(IntegerType.get_signless(32))
        ty2 = TypeOp()
        root = OperationOp(types=[ty1, ty2])
        rewrite = RewriteOp(root)
        with InsertionPoint(rewrite.add_body()):
            ty3 = TypeOp()
            newOp = OperationOp(name="foo.op", types=[ty1, ty3])
            ReplaceOp(root, with_op=newOp)


# CHECK: module  {
# CHECK:   pdl.pattern @rewrite_type : benefit(1)  {
# CHECK:     %0 = type : i32
# CHECK:     %1 = type
# CHECK:     %2 = operation  -> (%0, %1 : !pdl.type, !pdl.type)
# CHECK:     rewrite %2  {
# CHECK:       %3 = operation "foo.op"  -> (%0, %1 : !pdl.type, !pdl.type)
# CHECK:     }
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_rewrite_type():
    pattern = PatternOp(1, "rewrite_type")
    with InsertionPoint(pattern.body):
        ty1 = TypeOp(IntegerType.get_signless(32))
        ty2 = TypeOp()
        root = OperationOp(types=[ty1, ty2])
        rewrite = RewriteOp(root)
        with InsertionPoint(rewrite.add_body()):
            newOp = OperationOp(name="foo.op", types=[ty1, ty2])


# CHECK: module  {
# CHECK:   pdl.pattern @rewrite_types : benefit(1)  {
# CHECK:     %0 = types
# CHECK:     %1 = operation  -> (%0 : !pdl.range<type>)
# CHECK:     rewrite %1  {
# CHECK:       %2 = types : [i32, i64]
# CHECK:       %3 = operation "foo.op"  -> (%0, %2 : !pdl.range<type>, !pdl.range<type>)
# CHECK:     }
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_rewrite_types():
    pattern = PatternOp(1, "rewrite_types")
    with InsertionPoint(pattern.body):
        types = TypesOp()
        root = OperationOp(types=[types])
        rewrite = RewriteOp(root)
        with InsertionPoint(rewrite.add_body()):
            otherTypes = TypesOp(
                [IntegerType.get_signless(32), IntegerType.get_signless(64)]
            )
            newOp = OperationOp(name="foo.op", types=[types, otherTypes])


# CHECK: module  {
# CHECK:   pdl.pattern @rewrite_operands : benefit(1)  {
# CHECK:     %0 = types
# CHECK:     %1 = operands : %0
# CHECK:     %2 = operation(%1 : !pdl.range<value>)
# CHECK:     rewrite %2  {
# CHECK:       %3 = operation "foo.op"  -> (%0 : !pdl.range<type>)
# CHECK:     }
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_rewrite_operands():
    pattern = PatternOp(1, "rewrite_operands")
    with InsertionPoint(pattern.body):
        types = TypesOp()
        operands = OperandsOp(types)
        root = OperationOp(args=[operands])
        rewrite = RewriteOp(root)
        with InsertionPoint(rewrite.add_body()):
            newOp = OperationOp(name="foo.op", types=[types])


# CHECK: module  {
# CHECK:   pdl.pattern @native_rewrite : benefit(1)  {
# CHECK:     %0 = operation
# CHECK:     rewrite %0  {
# CHECK:       apply_native_rewrite "NativeRewrite"(%0 : !pdl.operation)
# CHECK:     }
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_native_rewrite():
    pattern = PatternOp(1, "native_rewrite")
    with InsertionPoint(pattern.body):
        root = OperationOp()
        rewrite = RewriteOp(root)
        with InsertionPoint(rewrite.add_body()):
            ApplyNativeRewriteOp([], "NativeRewrite", args=[root])


# CHECK: module  {
# CHECK:   pdl.pattern @attribute_with_value : benefit(1)  {
# CHECK:     %0 = operation
# CHECK:     rewrite %0  {
# CHECK:       %1 = attribute = "value"
# CHECK:       apply_native_rewrite "NativeRewrite"(%1 : !pdl.attribute)
# CHECK:     }
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_attribute_with_value():
    pattern = PatternOp(1, "attribute_with_value")
    with InsertionPoint(pattern.body):
        root = OperationOp()
        rewrite = RewriteOp(root)
        with InsertionPoint(rewrite.add_body()):
            attr = AttributeOp(value=Attribute.parse('"value"'))
            ApplyNativeRewriteOp([], "NativeRewrite", args=[attr])


# CHECK: module  {
# CHECK:   pdl.pattern @erase : benefit(1)  {
# CHECK:     %0 = operation
# CHECK:     rewrite %0  {
# CHECK:       erase %0
# CHECK:     }
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_erase():
    pattern = PatternOp(1, "erase")
    with InsertionPoint(pattern.body):
        root = OperationOp()
        rewrite = RewriteOp(root)
        with InsertionPoint(rewrite.add_body()):
            EraseOp(root)


# CHECK: module  {
# CHECK:   pdl.pattern @operation_results : benefit(1)  {
# CHECK:     %0 = types
# CHECK:     %1 = operation  -> (%0 : !pdl.range<type>)
# CHECK:     %2 = results of %1
# CHECK:     %3 = operation(%2 : !pdl.range<value>)
# CHECK:     rewrite %3 with "rewriter"
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_operation_results():
    valueRange = RangeType.get(ValueType.get())
    pattern = PatternOp(1, "operation_results")
    with InsertionPoint(pattern.body):
        types = TypesOp()
        inputOp = OperationOp(types=[types])
        results = ResultsOp(valueRange, inputOp)
        root = OperationOp(args=[results])
        RewriteOp(root, name="rewriter")


# CHECK: module  {
# CHECK:   pdl.pattern : benefit(1)  {
# CHECK:     %0 = type
# CHECK:     apply_native_constraint "typeConstraint"(%0 : !pdl.type)
# CHECK:     %1 = operation  -> (%0 : !pdl.type)
# CHECK:     rewrite %1 with "rewrite"
# CHECK:   }
# CHECK: }
@constructAndPrintInModule
def test_apply_native_constraint():
    pattern = PatternOp(1)
    with InsertionPoint(pattern.body):
        resultType = TypeOp()
        ApplyNativeConstraintOp([], "typeConstraint", args=[resultType])
        root = OperationOp(types=[resultType])
        RewriteOp(root, name="rewrite")