code: def loop_invariant_elimination_block(block):
      # Phase 1: Find vars needed to be renamed.
      #
      # while_loop outputs need to be renamed if the output will be eliminated
      # (due to loop invariant) and is returned as block output (which would
      # change the return var name and the program interface).
      #
      # list[(v_src, v_tgt, before_op)]: will rename v_src to v_tgt before
      # before_op (a while_loop)
      output_rename = []
      for op in list(block.operations):
          for b in op.blocks:
              loop_invariant_elimination_block(b)
  
          if op.op_type != "while_loop":
              continue
  
          loop_invariant_ids = detect_loop_invariants(op)
          for i in loop_invariant_ids:
              output_rename.append((op.loop_vars[i], op.outputs[i], op))
          if len(loop_invariant_ids) > 0:
              # Avoid the following case:
              # %a, %b = while_loop(..., name="b")
              # becomes
              # %b = identity(..., name="b")
              # %a = while_loop(..., name="b")
              # (two ops with the same name -> name collision)
              op.name = op.name + "_renamed"
  
      # Phase 2: insert rename ops. This changes block.operations
      for v_src, v_tgt, op in output_rename:
          if v_tgt in block.outputs:
              # rename the loop output to existing block output names
              with block:
                  res = mb.identity(
                      x=v_src, before_op=op, name=v_tgt.name
                  )
                  op.enclosing_block.replace_uses_of_var_after_op(
                      anchor_op=op, old_var=v_tgt, new_var=res
                  )
  
      # Phase 3: Perform loop invariant elimination without fear!
      for op in list(block.operations):
          if op.op_type != "while_loop":
              continue
          block = op.blocks[0]
          loop_invariant_ids = detect_loop_invariants(op)
  
          loop_variant_vars = []
  
          # replace uses of loop_invariants with its source from outside of the
          # while_loop op.
          for i in loop_invariant_ids:
              block.replace_uses_of_var_after_op(
                  anchor_op=None,
                  old_var=block.inputs[i],
                  new_var=op.loop_vars[i],
              )
  
          # replace block inputs
          block.remove_inputs(
              [block.inputs[i] for i in loop_invariant_ids]
          )
  
          # remove invariants from while_loop loop_vars
          for i in loop_invariant_ids:
              # replace usage of while_loop outputs that we'll eliminate.
              op.enclosing_block.replace_uses_of_var_after_op(
                  anchor_op=op,
                  old_var=op.outputs[i],
                  new_var=op.loop_vars[i],
              )
  
          # Remove after replacing to ensure program is valid
          for i in loop_invariant_ids:
              op.loop_vars[i].remove_child_op(op)
  
          op.loop_vars = tuple(
              v
              for i, v in enumerate(op.loop_vars)
              if i not in loop_invariant_ids
          )
          op._input_vars["loop_vars"] = op.loop_vars
  
          # remove invariants from while_loop outputs
          # block.outputs[0] is cond var
          block.set_outputs(
              [block.outputs[0]]
              + [
                  v
                  for i, v in enumerate(block.outputs[1:])
                  if i not in loop_invariant_ids
              ]
          )
  
          # op._output_vars doesn't include cond var
          op._output_vars = [
              v
              for i, v in enumerate(op._output_vars)
              if i not in loop_invariant_ids
          ]
  
          # check healthy state
          op.enclosing_block.validate()
  
file_path: turicreate/src/external/coremltools_wrap/coremltools/coremltools/converters/mil/mil/passes/loop_invariant_elimination.py
imports: from __future__ import print_function
  from __future__ import division
  from __future__ import absolute_import
  import numpy
  import six
  from coremltools.converters.mil.mil import Builder
  from coremltools.converters.mil.mil.passes.pass_registry import register_pass
label_desc: Use image node_id 2 for calling a global function with example usage: loop_invariant_elimination_block(block) without return types