1*9f3f6d7bSStella Laurenzo# RUN: %PYTHON %s | FileCheck %s 2*9f3f6d7bSStella Laurenzo 3*9f3f6d7bSStella Laurenzofrom mlir.ir import * 4*9f3f6d7bSStella Laurenzoimport mlir.dialects.builtin as builtin 5*9f3f6d7bSStella Laurenzoimport mlir.dialects.std as std 6*9f3f6d7bSStella Laurenzo 7*9f3f6d7bSStella Laurenzo 8*9f3f6d7bSStella Laurenzodef run(f): 9*9f3f6d7bSStella Laurenzo print("\nTEST:", f.__name__) 10*9f3f6d7bSStella Laurenzo f() 11*9f3f6d7bSStella Laurenzo return f 12*9f3f6d7bSStella Laurenzo 13*9f3f6d7bSStella Laurenzo 14*9f3f6d7bSStella Laurenzo# CHECK-LABEL: TEST: testFromPyFunc 15*9f3f6d7bSStella Laurenzo@run 16*9f3f6d7bSStella Laurenzodef testFromPyFunc(): 17*9f3f6d7bSStella Laurenzo with Context() as ctx, Location.unknown() as loc: 18*9f3f6d7bSStella Laurenzo m = builtin.ModuleOp() 19*9f3f6d7bSStella Laurenzo f32 = F32Type.get() 20*9f3f6d7bSStella Laurenzo f64 = F64Type.get() 21*9f3f6d7bSStella Laurenzo with InsertionPoint(m.body): 22*9f3f6d7bSStella Laurenzo # CHECK-LABEL: func @unary_return(%arg0: f64) -> f64 23*9f3f6d7bSStella Laurenzo # CHECK: return %arg0 : f64 24*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f64) 25*9f3f6d7bSStella Laurenzo def unary_return(a): 26*9f3f6d7bSStella Laurenzo return a 27*9f3f6d7bSStella Laurenzo 28*9f3f6d7bSStella Laurenzo # CHECK-LABEL: func @binary_return(%arg0: f32, %arg1: f64) -> (f32, f64) 29*9f3f6d7bSStella Laurenzo # CHECK: return %arg0, %arg1 : f32, f64 30*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 31*9f3f6d7bSStella Laurenzo def binary_return(a, b): 32*9f3f6d7bSStella Laurenzo return a, b 33*9f3f6d7bSStella Laurenzo 34*9f3f6d7bSStella Laurenzo # CHECK-LABEL: func @none_return(%arg0: f32, %arg1: f64) 35*9f3f6d7bSStella Laurenzo # CHECK: return 36*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 37*9f3f6d7bSStella Laurenzo def none_return(a, b): 38*9f3f6d7bSStella Laurenzo pass 39*9f3f6d7bSStella Laurenzo 40*9f3f6d7bSStella Laurenzo # CHECK-LABEL: func @call_unary 41*9f3f6d7bSStella Laurenzo # CHECK: %0 = call @unary_return(%arg0) : (f64) -> f64 42*9f3f6d7bSStella Laurenzo # CHECK: return %0 : f64 43*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f64) 44*9f3f6d7bSStella Laurenzo def call_unary(a): 45*9f3f6d7bSStella Laurenzo return unary_return(a) 46*9f3f6d7bSStella Laurenzo 47*9f3f6d7bSStella Laurenzo # CHECK-LABEL: func @call_binary 48*9f3f6d7bSStella Laurenzo # CHECK: %0:2 = call @binary_return(%arg0, %arg1) : (f32, f64) -> (f32, f64) 49*9f3f6d7bSStella Laurenzo # CHECK: return %0#0, %0#1 : f32, f64 50*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 51*9f3f6d7bSStella Laurenzo def call_binary(a, b): 52*9f3f6d7bSStella Laurenzo return binary_return(a, b) 53*9f3f6d7bSStella Laurenzo 54*9f3f6d7bSStella Laurenzo # CHECK-LABEL: func @call_none 55*9f3f6d7bSStella Laurenzo # CHECK: call @none_return(%arg0, %arg1) : (f32, f64) -> () 56*9f3f6d7bSStella Laurenzo # CHECK: return 57*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 58*9f3f6d7bSStella Laurenzo def call_none(a, b): 59*9f3f6d7bSStella Laurenzo return none_return(a, b) 60*9f3f6d7bSStella Laurenzo 61*9f3f6d7bSStella Laurenzo ## Variants and optional feature tests. 62*9f3f6d7bSStella Laurenzo # CHECK-LABEL: func @from_name_arg 63*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64, name="from_name_arg") 64*9f3f6d7bSStella Laurenzo def explicit_name(a, b): 65*9f3f6d7bSStella Laurenzo return b 66*9f3f6d7bSStella Laurenzo 67*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 68*9f3f6d7bSStella Laurenzo def positional_func_op(a, b, func_op): 69*9f3f6d7bSStella Laurenzo assert isinstance(func_op, builtin.FuncOp) 70*9f3f6d7bSStella Laurenzo return b 71*9f3f6d7bSStella Laurenzo 72*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 73*9f3f6d7bSStella Laurenzo def kw_func_op(a, b=None, func_op=None): 74*9f3f6d7bSStella Laurenzo assert isinstance(func_op, builtin.FuncOp) 75*9f3f6d7bSStella Laurenzo return b 76*9f3f6d7bSStella Laurenzo 77*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 78*9f3f6d7bSStella Laurenzo def kwargs_func_op(a, b=None, **kwargs): 79*9f3f6d7bSStella Laurenzo assert isinstance(kwargs["func_op"], builtin.FuncOp) 80*9f3f6d7bSStella Laurenzo return b 81*9f3f6d7bSStella Laurenzo 82*9f3f6d7bSStella Laurenzo # CHECK-LABEL: func @explicit_results(%arg0: f32, %arg1: f64) -> f64 83*9f3f6d7bSStella Laurenzo # CHECK: return %arg1 : f64 84*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64, results=[f64]) 85*9f3f6d7bSStella Laurenzo def explicit_results(a, b): 86*9f3f6d7bSStella Laurenzo std.ReturnOp([b]) 87*9f3f6d7bSStella Laurenzo 88*9f3f6d7bSStella Laurenzo print(m) 89*9f3f6d7bSStella Laurenzo 90*9f3f6d7bSStella Laurenzo 91*9f3f6d7bSStella Laurenzo# CHECK-LABEL: TEST: testFromPyFuncErrors 92*9f3f6d7bSStella Laurenzo@run 93*9f3f6d7bSStella Laurenzodef testFromPyFuncErrors(): 94*9f3f6d7bSStella Laurenzo with Context() as ctx, Location.unknown() as loc: 95*9f3f6d7bSStella Laurenzo m = builtin.ModuleOp() 96*9f3f6d7bSStella Laurenzo f32 = F32Type.get() 97*9f3f6d7bSStella Laurenzo f64 = F64Type.get() 98*9f3f6d7bSStella Laurenzo with InsertionPoint(m.body): 99*9f3f6d7bSStella Laurenzo try: 100*9f3f6d7bSStella Laurenzo 101*9f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f64, results=[f64]) 102*9f3f6d7bSStella Laurenzo def unary_return(a): 103*9f3f6d7bSStella Laurenzo return a 104*9f3f6d7bSStella Laurenzo except AssertionError as e: 105*9f3f6d7bSStella Laurenzo # CHECK: Capturing a python function with explicit `results=` requires that the wrapped function returns None. 106*9f3f6d7bSStella Laurenzo print(e) 107*9f3f6d7bSStella Laurenzo 108*9f3f6d7bSStella Laurenzo 109*9f3f6d7bSStella Laurenzo# CHECK-LABEL: TEST: testBuildFuncOp 110*9f3f6d7bSStella Laurenzo@run 111*9f3f6d7bSStella Laurenzodef testBuildFuncOp(): 112*9f3f6d7bSStella Laurenzo ctx = Context() 113*9f3f6d7bSStella Laurenzo with Location.unknown(ctx) as loc: 114*9f3f6d7bSStella Laurenzo m = builtin.ModuleOp() 115*9f3f6d7bSStella Laurenzo 116*9f3f6d7bSStella Laurenzo f32 = F32Type.get() 117*9f3f6d7bSStella Laurenzo tensor_type = RankedTensorType.get((2, 3, 4), f32) 118*9f3f6d7bSStella Laurenzo with InsertionPoint.at_block_begin(m.body): 119*9f3f6d7bSStella Laurenzo func = builtin.FuncOp(name="some_func", 120*9f3f6d7bSStella Laurenzo type=FunctionType.get( 121*9f3f6d7bSStella Laurenzo inputs=[tensor_type, tensor_type], 122*9f3f6d7bSStella Laurenzo results=[tensor_type]), 123*9f3f6d7bSStella Laurenzo visibility="nested") 124*9f3f6d7bSStella Laurenzo # CHECK: Name is: "some_func" 125*9f3f6d7bSStella Laurenzo print("Name is: ", func.name) 126*9f3f6d7bSStella Laurenzo 127*9f3f6d7bSStella Laurenzo # CHECK: Type is: (tensor<2x3x4xf32>, tensor<2x3x4xf32>) -> tensor<2x3x4xf32> 128*9f3f6d7bSStella Laurenzo print("Type is: ", func.type) 129*9f3f6d7bSStella Laurenzo 130*9f3f6d7bSStella Laurenzo # CHECK: Visibility is: "nested" 131*9f3f6d7bSStella Laurenzo print("Visibility is: ", func.visibility) 132*9f3f6d7bSStella Laurenzo 133*9f3f6d7bSStella Laurenzo try: 134*9f3f6d7bSStella Laurenzo entry_block = func.entry_block 135*9f3f6d7bSStella Laurenzo except IndexError as e: 136*9f3f6d7bSStella Laurenzo # CHECK: External function does not have a body 137*9f3f6d7bSStella Laurenzo print(e) 138*9f3f6d7bSStella Laurenzo 139*9f3f6d7bSStella Laurenzo with InsertionPoint(func.add_entry_block()): 140*9f3f6d7bSStella Laurenzo std.ReturnOp([func.entry_block.arguments[0]]) 141*9f3f6d7bSStella Laurenzo pass 142*9f3f6d7bSStella Laurenzo 143*9f3f6d7bSStella Laurenzo try: 144*9f3f6d7bSStella Laurenzo func.add_entry_block() 145*9f3f6d7bSStella Laurenzo except IndexError as e: 146*9f3f6d7bSStella Laurenzo # CHECK: The function already has an entry block! 147*9f3f6d7bSStella Laurenzo print(e) 148*9f3f6d7bSStella Laurenzo 149*9f3f6d7bSStella Laurenzo # Try the callback builder and passing type as tuple. 150*9f3f6d7bSStella Laurenzo func = builtin.FuncOp(name="some_other_func", 151*9f3f6d7bSStella Laurenzo type=([tensor_type, tensor_type], [tensor_type]), 152*9f3f6d7bSStella Laurenzo visibility="nested", 153*9f3f6d7bSStella Laurenzo body_builder=lambda func: std.ReturnOp( 154*9f3f6d7bSStella Laurenzo [func.entry_block.arguments[0]])) 155*9f3f6d7bSStella Laurenzo 156*9f3f6d7bSStella Laurenzo # CHECK: module { 157*9f3f6d7bSStella Laurenzo # CHECK: func nested @some_func(%arg0: tensor<2x3x4xf32>, %arg1: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> { 158*9f3f6d7bSStella Laurenzo # CHECK: return %arg0 : tensor<2x3x4xf32> 159*9f3f6d7bSStella Laurenzo # CHECK: } 160*9f3f6d7bSStella Laurenzo # CHECK: func nested @some_other_func(%arg0: tensor<2x3x4xf32>, %arg1: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> { 161*9f3f6d7bSStella Laurenzo # CHECK: return %arg0 : tensor<2x3x4xf32> 162*9f3f6d7bSStella Laurenzo # CHECK: } 163*9f3f6d7bSStella Laurenzo print(m) 164