parameters: (equiv_set, parfor1, parfor2)
return_statement: return fuse_parfors_inner(parfor1, parfor2)
docstring: try to fuse parfors and return a fused parfor, otherwise return None
docstring_summary: try to fuse parfors and return a fused parfor, otherwise return None
docstring_tokens: try to fuse parfors and return a fused parfor otherwise return None
function: def try_fuse(equiv_set, parfor1, parfor2):
      """try to fuse parfors and return a fused parfor, otherwise return None
      """
      dprint("try_fuse: trying to fuse \n", parfor1, "\n", parfor2)
  
      # default report is None
      report = None
  
      # fusion of parfors with different dimensions not supported yet
      if len(parfor1.loop_nests) != len(parfor2.loop_nests):
          dprint("try_fuse: parfors number of dimensions mismatch")
          msg = "- fusion failed: number of loops mismatched, %s, %s."
          fmt = "parallel loop #%s has a nest of %s loops"
          l1 = fmt % (parfor1.id, len(parfor1.loop_nests))
          l2 = fmt % (parfor2.id, len(parfor2.loop_nests))
          report = FusionReport(parfor1.id, parfor2.id, msg % (l1, l2))
          return None, report
  
      ndims = len(parfor1.loop_nests)
      # all loops should be equal length
  
      def is_equiv(x, y):
          return x == y or equiv_set.is_equiv(x, y)
  
      for i in range(ndims):
          nest1 = parfor1.loop_nests[i]
          nest2 = parfor2.loop_nests[i]
          if not (is_equiv(nest1.start, nest2.start) and
                  is_equiv(nest1.stop, nest2.stop) and
                  is_equiv(nest1.step, nest2.step)):
              dprint("try_fuse: parfor dimension correlation mismatch", i)
              msg = "- fusion failed: loop dimension mismatched in axis %s. "
              msg += "slice(%s, %s, %s) != " % (nest1.start, nest1.stop, nest1.step)
              msg += "slice(%s, %s, %s)" % (nest2.start, nest2.stop, nest2.step)
              report = FusionReport(parfor1.id, parfor2.id, msg % i)
              return None, report
  
      # TODO: make sure parfor1's reduction output is not used in parfor2
      # only data parallel loops
      if has_cross_iter_dep(parfor1) or has_cross_iter_dep(parfor2):
          dprint("try_fuse: parfor cross iteration dependency found")
          msg = ("- fusion failed: cross iteration dependency found "
                  "between loops #%s and #%s")
          report = FusionReport(parfor1.id, parfor2.id,
                                  msg % (parfor1.id, parfor2.id))
          return None, report
  
  
      # find parfor1's defs, only body is considered since init_block will run
      # first after fusion as well
      p1_body_usedefs = compute_use_defs(parfor1.loop_body)
      p1_body_defs = set()
      for defs in p1_body_usedefs.defmap.values():
          p1_body_defs |= defs
  
      p2_usedefs = compute_use_defs(parfor2.loop_body)
      p2_uses = compute_use_defs({0: parfor2.init_block}).usemap[0]
      for uses in p2_usedefs.usemap.values():
          p2_uses |= uses
  
      if not p1_body_defs.isdisjoint(p2_uses):
          dprint("try_fuse: parfor2 depends on parfor1 body")
          msg = ("- fusion failed: parallel loop %s has a dependency on the "
                  "body of parallel loop %s. ")
          report = FusionReport(parfor1.id, parfor2.id,
                                  msg % (parfor1.id, parfor2.id))
          return None, report
  
      return fuse_parfors_inner(parfor1, parfor2)
function_tokens: def try_fuse ( equiv_set , parfor1 , parfor2 ) : dprint ( "try_fuse: trying to fuse \n" , parfor1 , "\n" , parfor2 ) # default report is None report = None # fusion of parfors with different dimensions not supported yet if len ( parfor1 . loop_nests ) != len ( parfor2 . loop_nests ) : dprint ( "try_fuse: parfors number of dimensions mismatch" ) msg = "- fusion failed: number of loops mismatched, %s, %s." fmt = "parallel loop #%s has a nest of %s loops" l1 = fmt % ( parfor1 . id , len ( parfor1 . loop_nests ) ) l2 = fmt % ( parfor2 . id , len ( parfor2 . loop_nests ) ) report = FusionReport ( parfor1 . id , parfor2 . id , msg % ( l1 , l2 ) ) return None , report ndims = len ( parfor1 . loop_nests ) # all loops should be equal length def is_equiv ( x , y ) : return x == y or equiv_set . is_equiv ( x , y ) for i in range ( ndims ) : nest1 = parfor1 . loop_nests [ i ] nest2 = parfor2 . loop_nests [ i ] if not ( is_equiv ( nest1 . start , nest2 . start ) and is_equiv ( nest1 . stop , nest2 . stop ) and is_equiv ( nest1 . step , nest2 . step ) ) : dprint ( "try_fuse: parfor dimension correlation mismatch" , i ) msg = "- fusion failed: loop dimension mismatched in axis %s. " msg += "slice(%s, %s, %s) != " % ( nest1 . start , nest1 . stop , nest1 . step ) msg += "slice(%s, %s, %s)" % ( nest2 . start , nest2 . stop , nest2 . step ) report = FusionReport ( parfor1 . id , parfor2 . id , msg % i ) return None , report # TODO: make sure parfor1's reduction output is not used in parfor2 # only data parallel loops if has_cross_iter_dep ( parfor1 ) or has_cross_iter_dep ( parfor2 ) : dprint ( "try_fuse: parfor cross iteration dependency found" ) msg = ( "- fusion failed: cross iteration dependency found " "between loops #%s and #%s" ) report = FusionReport ( parfor1 . id , parfor2 . id , msg % ( parfor1 . id , parfor2 . id ) ) return None , report # find parfor1's defs, only body is considered since init_block will run # first after fusion as well p1_body_usedefs = compute_use_defs ( parfor1 . loop_body ) p1_body_defs = set ( ) for defs in p1_body_usedefs . defmap . values ( ) : p1_body_defs |= defs p2_usedefs = compute_use_defs ( parfor2 . loop_body ) p2_uses = compute_use_defs ( { 0 : parfor2 . init_block } ) . usemap [ 0 ] for uses in p2_usedefs . usemap . values ( ) : p2_uses |= uses if not p1_body_defs . isdisjoint ( p2_uses ) : dprint ( "try_fuse: parfor2 depends on parfor1 body" ) msg = ( "- fusion failed: parallel loop %s has a dependency on the " "body of parallel loop %s. " ) report = FusionReport ( parfor1 . id , parfor2 . id , msg % ( parfor1 . id , parfor2 . id ) ) return None , report return fuse_parfors_inner ( parfor1 , parfor2 )