@@ -127,12 +127,14 @@ def _fuse_node_pair(input_node, other_node):
127127
128128
129129def _fuse_kernel_pair (input_kernel , other_kernel , mapping ):
130- arrangement , tensors = _fuse_arrangement_pair (input_kernel , other_kernel , mapping )
130+ arrangement , tensors , fusion_info = _fuse_arrangement_pair (
131+ input_kernel , other_kernel , mapping
132+ )
131133
132134 if arrangement is None :
133135 return None
134136
135- application = _fuse_application_pair (input_kernel , other_kernel )
137+ application = _fuse_application_pair (input_kernel , other_kernel , fusion_info )
136138
137139 if application is None :
138140 return None
@@ -351,13 +353,15 @@ def arrangement(*tensors):
351353
352354 return tuple (tensors_arranged )
353355
354- return arrangement , tuple (tensors )
356+ return arrangement , tuple (tensors ), fusion_info
355357
356358
357- def _fuse_application_pair (input_kernel , other_kernel ):
359+ def _fuse_application_pair (input_kernel , other_kernel , fusion_info ):
358360 count = 0
359361
360- def _generate_invocation_info (application ):
362+ def _generate_invocation_info (application , prefix , suffix , indent = 4 ):
363+ indentation = " " * indent
364+
361365 def _make_param ():
362366 nonlocal count
363367
@@ -368,21 +372,79 @@ def _make_param():
368372
369373 params = inspect .signature (application ).parameters
370374
371- param_names = ", " .join (_make_param () for _ in params )
375+ arg_names = [_make_param () for _ in params ]
376+
377+ param_names = ", " .join (arg_names )
378+
379+ tile_func_count = 0
380+
381+ for func , args , kwargs in itertools .chain (prefix , suffix ):
382+ if func is not Tensor .tile :
383+ continue
384+
385+ if len (args ) != 1 or kwargs :
386+ return None , None , None
387+
388+ tile_shape = args [0 ]
389+
390+ if (
391+ any (tile_size not in (1 , - 1 ) for tile_size in tile_shape )
392+ or sum (1 if tile_size == - 1 else 0 for tile_size in tile_shape ) != 1
393+ ):
394+ return None , None , None
395+
396+ tile_func_count += 1
397+
398+ if tile_func_count > 1 :
399+ return None , None , None
400+
401+ def _generate_for_loop_source ():
402+ reduction_dim = tile_shape .index (- 1 )
403+
404+ index_name = naming .auto_generate (f"index_{ count } " )
405+ range_stop = f"{ arg_names [0 ]} .shape[{ reduction_dim } ]"
406+
407+ tensor_indexing = ", " .join (
408+ index_name if dim == reduction_dim else "0"
409+ for dim in range (len (tile_shape ))
410+ )
411+
412+ for i , arg_name in enumerate (arg_names ):
413+ arg_names [i ] = f"{ arg_name } [{ tensor_indexing } ]"
414+
415+ return f"for { index_name } in range({ range_stop } )"
372416
373417 module = inspect .getmodule (application )
374418
375- invocation_source = f"{ module .__name__ } .{ application .__name__ } ({ param_names } )"
419+ invocation_source = ""
420+
421+ if tile_func_count != 0 :
422+ invocation_source += f"{ _generate_for_loop_source ()} :\n { indentation * 2 } "
423+
424+ invocation_source += (
425+ f"{ module .__name__ } .{ application .__name__ } ({ ', ' .join (arg_names )} )"
426+ )
376427
377428 return param_names , module , invocation_source
378429
379430 input_param_names , input_module , input_invocation_source = (
380- _generate_invocation_info (input_kernel .application )
431+ _generate_invocation_info (
432+ input_kernel .application , fusion_info .input_prefix , fusion_info .input_suffix
433+ )
381434 )
435+
436+ if input_param_names is None :
437+ return None
438+
382439 other_param_names , other_module , other_invocation_source = (
383- _generate_invocation_info (other_kernel .application )
440+ _generate_invocation_info (
441+ other_kernel .application , fusion_info .other_prefix , fusion_info .other_suffix
442+ )
384443 )
385444
445+ if other_param_names is None :
446+ return None
447+
386448 param_names = f"{ input_param_names } , { other_param_names } "
387449
388450 _APPLICATION_NAME = "application"
0 commit comments