19f3f6d7bSStella Laurenzo# RUN: %PYTHON %s | FileCheck %s 29f3f6d7bSStella Laurenzo 39f3f6d7bSStella Laurenzofrom mlir.ir import * 49f3f6d7bSStella Laurenzoimport mlir.dialects.builtin as builtin 59f3f6d7bSStella Laurenzoimport mlir.dialects.std as std 69f3f6d7bSStella Laurenzo 79f3f6d7bSStella Laurenzo 89f3f6d7bSStella Laurenzodef run(f): 99f3f6d7bSStella Laurenzo print("\nTEST:", f.__name__) 109f3f6d7bSStella Laurenzo f() 119f3f6d7bSStella Laurenzo return f 129f3f6d7bSStella Laurenzo 139f3f6d7bSStella Laurenzo 149f3f6d7bSStella Laurenzo# CHECK-LABEL: TEST: testFromPyFunc 159f3f6d7bSStella Laurenzo@run 169f3f6d7bSStella Laurenzodef testFromPyFunc(): 179f3f6d7bSStella Laurenzo with Context() as ctx, Location.unknown() as loc: 189f3f6d7bSStella Laurenzo m = builtin.ModuleOp() 199f3f6d7bSStella Laurenzo f32 = F32Type.get() 209f3f6d7bSStella Laurenzo f64 = F64Type.get() 219f3f6d7bSStella Laurenzo with InsertionPoint(m.body): 229f3f6d7bSStella Laurenzo # CHECK-LABEL: func @unary_return(%arg0: f64) -> f64 239f3f6d7bSStella Laurenzo # CHECK: return %arg0 : f64 249f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f64) 259f3f6d7bSStella Laurenzo def unary_return(a): 269f3f6d7bSStella Laurenzo return a 279f3f6d7bSStella Laurenzo 289f3f6d7bSStella Laurenzo # CHECK-LABEL: func @binary_return(%arg0: f32, %arg1: f64) -> (f32, f64) 299f3f6d7bSStella Laurenzo # CHECK: return %arg0, %arg1 : f32, f64 309f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 319f3f6d7bSStella Laurenzo def binary_return(a, b): 329f3f6d7bSStella Laurenzo return a, b 339f3f6d7bSStella Laurenzo 349f3f6d7bSStella Laurenzo # CHECK-LABEL: func @none_return(%arg0: f32, %arg1: f64) 359f3f6d7bSStella Laurenzo # CHECK: return 369f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 379f3f6d7bSStella Laurenzo def none_return(a, b): 389f3f6d7bSStella Laurenzo pass 399f3f6d7bSStella Laurenzo 409f3f6d7bSStella Laurenzo # CHECK-LABEL: func @call_unary 419f3f6d7bSStella Laurenzo # CHECK: %0 = call @unary_return(%arg0) : (f64) -> f64 429f3f6d7bSStella Laurenzo # CHECK: return %0 : f64 439f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f64) 449f3f6d7bSStella Laurenzo def call_unary(a): 459f3f6d7bSStella Laurenzo return unary_return(a) 469f3f6d7bSStella Laurenzo 479f3f6d7bSStella Laurenzo # CHECK-LABEL: func @call_binary 489f3f6d7bSStella Laurenzo # CHECK: %0:2 = call @binary_return(%arg0, %arg1) : (f32, f64) -> (f32, f64) 499f3f6d7bSStella Laurenzo # CHECK: return %0#0, %0#1 : f32, f64 509f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 519f3f6d7bSStella Laurenzo def call_binary(a, b): 529f3f6d7bSStella Laurenzo return binary_return(a, b) 539f3f6d7bSStella Laurenzo 549f3f6d7bSStella Laurenzo # CHECK-LABEL: func @call_none 559f3f6d7bSStella Laurenzo # CHECK: call @none_return(%arg0, %arg1) : (f32, f64) -> () 569f3f6d7bSStella Laurenzo # CHECK: return 579f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 589f3f6d7bSStella Laurenzo def call_none(a, b): 599f3f6d7bSStella Laurenzo return none_return(a, b) 609f3f6d7bSStella Laurenzo 619f3f6d7bSStella Laurenzo ## Variants and optional feature tests. 629f3f6d7bSStella Laurenzo # CHECK-LABEL: func @from_name_arg 639f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64, name="from_name_arg") 649f3f6d7bSStella Laurenzo def explicit_name(a, b): 659f3f6d7bSStella Laurenzo return b 669f3f6d7bSStella Laurenzo 679f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 689f3f6d7bSStella Laurenzo def positional_func_op(a, b, func_op): 699f3f6d7bSStella Laurenzo assert isinstance(func_op, builtin.FuncOp) 709f3f6d7bSStella Laurenzo return b 719f3f6d7bSStella Laurenzo 729f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 739f3f6d7bSStella Laurenzo def kw_func_op(a, b=None, func_op=None): 749f3f6d7bSStella Laurenzo assert isinstance(func_op, builtin.FuncOp) 759f3f6d7bSStella Laurenzo return b 769f3f6d7bSStella Laurenzo 779f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64) 789f3f6d7bSStella Laurenzo def kwargs_func_op(a, b=None, **kwargs): 799f3f6d7bSStella Laurenzo assert isinstance(kwargs["func_op"], builtin.FuncOp) 809f3f6d7bSStella Laurenzo return b 819f3f6d7bSStella Laurenzo 829f3f6d7bSStella Laurenzo # CHECK-LABEL: func @explicit_results(%arg0: f32, %arg1: f64) -> f64 839f3f6d7bSStella Laurenzo # CHECK: return %arg1 : f64 849f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f32, f64, results=[f64]) 859f3f6d7bSStella Laurenzo def explicit_results(a, b): 869f3f6d7bSStella Laurenzo std.ReturnOp([b]) 879f3f6d7bSStella Laurenzo 889f3f6d7bSStella Laurenzo print(m) 899f3f6d7bSStella Laurenzo 909f3f6d7bSStella Laurenzo 919f3f6d7bSStella Laurenzo# CHECK-LABEL: TEST: testFromPyFuncErrors 929f3f6d7bSStella Laurenzo@run 939f3f6d7bSStella Laurenzodef testFromPyFuncErrors(): 949f3f6d7bSStella Laurenzo with Context() as ctx, Location.unknown() as loc: 959f3f6d7bSStella Laurenzo m = builtin.ModuleOp() 969f3f6d7bSStella Laurenzo f32 = F32Type.get() 979f3f6d7bSStella Laurenzo f64 = F64Type.get() 989f3f6d7bSStella Laurenzo with InsertionPoint(m.body): 999f3f6d7bSStella Laurenzo try: 1009f3f6d7bSStella Laurenzo 1019f3f6d7bSStella Laurenzo @builtin.FuncOp.from_py_func(f64, results=[f64]) 1029f3f6d7bSStella Laurenzo def unary_return(a): 1039f3f6d7bSStella Laurenzo return a 1049f3f6d7bSStella Laurenzo except AssertionError as e: 1059f3f6d7bSStella Laurenzo # CHECK: Capturing a python function with explicit `results=` requires that the wrapped function returns None. 1069f3f6d7bSStella Laurenzo print(e) 1079f3f6d7bSStella Laurenzo 1089f3f6d7bSStella Laurenzo 1099f3f6d7bSStella Laurenzo# CHECK-LABEL: TEST: testBuildFuncOp 1109f3f6d7bSStella Laurenzo@run 1119f3f6d7bSStella Laurenzodef testBuildFuncOp(): 1129f3f6d7bSStella Laurenzo ctx = Context() 1139f3f6d7bSStella Laurenzo with Location.unknown(ctx) as loc: 1149f3f6d7bSStella Laurenzo m = builtin.ModuleOp() 1159f3f6d7bSStella Laurenzo 1169f3f6d7bSStella Laurenzo f32 = F32Type.get() 1179f3f6d7bSStella Laurenzo tensor_type = RankedTensorType.get((2, 3, 4), f32) 1189f3f6d7bSStella Laurenzo with InsertionPoint.at_block_begin(m.body): 1199f3f6d7bSStella Laurenzo func = builtin.FuncOp(name="some_func", 1209f3f6d7bSStella Laurenzo type=FunctionType.get( 1219f3f6d7bSStella Laurenzo inputs=[tensor_type, tensor_type], 1229f3f6d7bSStella Laurenzo results=[tensor_type]), 1239f3f6d7bSStella Laurenzo visibility="nested") 1249f3f6d7bSStella Laurenzo # CHECK: Name is: "some_func" 1259f3f6d7bSStella Laurenzo print("Name is: ", func.name) 1269f3f6d7bSStella Laurenzo 1279f3f6d7bSStella Laurenzo # CHECK: Type is: (tensor<2x3x4xf32>, tensor<2x3x4xf32>) -> tensor<2x3x4xf32> 1289f3f6d7bSStella Laurenzo print("Type is: ", func.type) 1299f3f6d7bSStella Laurenzo 1309f3f6d7bSStella Laurenzo # CHECK: Visibility is: "nested" 1319f3f6d7bSStella Laurenzo print("Visibility is: ", func.visibility) 1329f3f6d7bSStella Laurenzo 1339f3f6d7bSStella Laurenzo try: 1349f3f6d7bSStella Laurenzo entry_block = func.entry_block 1359f3f6d7bSStella Laurenzo except IndexError as e: 1369f3f6d7bSStella Laurenzo # CHECK: External function does not have a body 1379f3f6d7bSStella Laurenzo print(e) 1389f3f6d7bSStella Laurenzo 1399f3f6d7bSStella Laurenzo with InsertionPoint(func.add_entry_block()): 1409f3f6d7bSStella Laurenzo std.ReturnOp([func.entry_block.arguments[0]]) 1419f3f6d7bSStella Laurenzo pass 1429f3f6d7bSStella Laurenzo 1439f3f6d7bSStella Laurenzo try: 1449f3f6d7bSStella Laurenzo func.add_entry_block() 1459f3f6d7bSStella Laurenzo except IndexError as e: 1469f3f6d7bSStella Laurenzo # CHECK: The function already has an entry block! 1479f3f6d7bSStella Laurenzo print(e) 1489f3f6d7bSStella Laurenzo 1499f3f6d7bSStella Laurenzo # Try the callback builder and passing type as tuple. 1509f3f6d7bSStella Laurenzo func = builtin.FuncOp(name="some_other_func", 1519f3f6d7bSStella Laurenzo type=([tensor_type, tensor_type], [tensor_type]), 1529f3f6d7bSStella Laurenzo visibility="nested", 1539f3f6d7bSStella Laurenzo body_builder=lambda func: std.ReturnOp( 1549f3f6d7bSStella Laurenzo [func.entry_block.arguments[0]])) 1559f3f6d7bSStella Laurenzo 1569f3f6d7bSStella Laurenzo # CHECK: module { 1579f3f6d7bSStella Laurenzo # CHECK: func nested @some_func(%arg0: tensor<2x3x4xf32>, %arg1: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> { 1589f3f6d7bSStella Laurenzo # CHECK: return %arg0 : tensor<2x3x4xf32> 1599f3f6d7bSStella Laurenzo # CHECK: } 1609f3f6d7bSStella Laurenzo # CHECK: func nested @some_other_func(%arg0: tensor<2x3x4xf32>, %arg1: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> { 1619f3f6d7bSStella Laurenzo # CHECK: return %arg0 : tensor<2x3x4xf32> 1629f3f6d7bSStella Laurenzo # CHECK: } 1639f3f6d7bSStella Laurenzo print(m) 164*afeda4b9SAlex Zinenko 165*afeda4b9SAlex Zinenko 166*afeda4b9SAlex Zinenko# CHECK-LABEL: TEST: testFuncArgumentAccess 167*afeda4b9SAlex Zinenko@run 168*afeda4b9SAlex Zinenkodef testFuncArgumentAccess(): 169*afeda4b9SAlex Zinenko with Context(), Location.unknown(): 170*afeda4b9SAlex Zinenko module = Module.create() 171*afeda4b9SAlex Zinenko f32 = F32Type.get() 172*afeda4b9SAlex Zinenko f64 = F64Type.get() 173*afeda4b9SAlex Zinenko with InsertionPoint(module.body): 174*afeda4b9SAlex Zinenko func = builtin.FuncOp("some_func", ([f32, f32], [f64, f64])) 175*afeda4b9SAlex Zinenko with InsertionPoint(func.add_entry_block()): 176*afeda4b9SAlex Zinenko std.ReturnOp(func.arguments) 177*afeda4b9SAlex Zinenko func.arg_attrs = ArrayAttr.get([ 178*afeda4b9SAlex Zinenko DictAttr.get({ 179*afeda4b9SAlex Zinenko "foo": StringAttr.get("bar"), 180*afeda4b9SAlex Zinenko "baz": UnitAttr.get() 181*afeda4b9SAlex Zinenko }), 182*afeda4b9SAlex Zinenko DictAttr.get({"qux": ArrayAttr.get([])}) 183*afeda4b9SAlex Zinenko ]) 184*afeda4b9SAlex Zinenko func.result_attrs = ArrayAttr.get([ 185*afeda4b9SAlex Zinenko DictAttr.get({"res1": FloatAttr.get(f32, 42.0)}), 186*afeda4b9SAlex Zinenko DictAttr.get({"res2": FloatAttr.get(f64, 256.0)}) 187*afeda4b9SAlex Zinenko ]) 188*afeda4b9SAlex Zinenko 189*afeda4b9SAlex Zinenko # CHECK: [{baz, foo = "bar"}, {qux = []}] 190*afeda4b9SAlex Zinenko print(func.arg_attrs) 191*afeda4b9SAlex Zinenko 192*afeda4b9SAlex Zinenko # CHECK: [{res1 = 4.200000e+01 : f32}, {res2 = 2.560000e+02 : f64}] 193*afeda4b9SAlex Zinenko print(func.result_attrs) 194*afeda4b9SAlex Zinenko 195*afeda4b9SAlex Zinenko # CHECK: func @some_func( 196*afeda4b9SAlex Zinenko # CHECK: %[[ARG0:.*]]: f32 {baz, foo = "bar"}, 197*afeda4b9SAlex Zinenko # CHECK: %[[ARG1:.*]]: f32 {qux = []}) -> 198*afeda4b9SAlex Zinenko # CHECK: f64 {res1 = 4.200000e+01 : f32}, 199*afeda4b9SAlex Zinenko # CHECK: f64 {res2 = 2.560000e+02 : f64}) 200*afeda4b9SAlex Zinenko # CHECK: return %[[ARG0]], %[[ARG1]] : f32, f32 201*afeda4b9SAlex Zinenko print(module) 202