code: def _optimize_1(graph, live_out, alloc):
      """Optimize the variable allocation strategy for one CFG.
  
      Args:
        graph: `ControlFlowGraph` to traverse.
        live_out: Set of `str` variable names that are live out of this graph (i.e.,
          returned by the function this graph represents).
        alloc: Dictionary of allocation strategy deductions made so far.
          This is mutated; but no variable is moved to a cheaper strategy.
      """
      liveness_map = liveness.liveness_analysis(graph, set(live_out))
      if graph.exit_index() > 0:
          _variable_crosses_block_boundary(inst.pc_var, alloc)
      for i in range(graph.exit_index()):
          block = graph.block(i)
          for op, live_out in zip(
              block.instructions,
              liveness_map[block].live_out_instructions,
          ):
              for varname in inst.pattern_traverse(_vars_read_by(op)):
                  _variable_is_read(varname, alloc)
              if isinstance(op, inst.FunctionCallOp):
                  callee_writes = _indirectly_writes(op.function)
                  for varname in live_out - set(
                      inst.pattern_flatten(op.vars_out)
                  ):
                      # A variable only needs the conservative storage strategy if it
                      # crosses a call to some function that writes it (e.g., a recursive
                      # self-call).
                      if varname in callee_writes:
                          _variable_crosses_function_call_boundary(
                              varname, alloc
                          )
                      else:
                          _variable_crosses_block_boundary(
                              varname, alloc
                          )
                  # TODO(axch): Actually, the PC only needs a stack at this site if this
                  # is not a tail call.
                  _variable_crosses_function_call_boundary(
                      inst.pc_var, alloc
                  )
          if isinstance(block.terminator, inst.BranchOp):
              # TODO(axch): Actually, being read by BranchOp only implies
              # _variable_is_read.  However, the downstream VM doesn't know how to pop a
              # condition variable that is not needed after the BranchOp, so for now we
              # have to allocate a register for it.
              _variable_crosses_block_boundary(
                  block.terminator.cond_var, alloc
              )
          for varname in liveness_map[block].live_out_of_block:
              _variable_crosses_block_boundary(varname, alloc)
  
file_path: probability/tensorflow_probability/python/experimental/auto_batching/allocation_strategy.py
imports: from absl import logging
  import six
  from tensorflow_probability.python.experimental.auto_batching import instructions
  from tensorflow_probability.python.experimental.auto_batching import liveness
label_desc: Use image node_id 6 for calling a global function with example usage: _optimize_1(graph, live_out, alloc) without return types