//
  // This can help use eliminate writes to %block that are not used since this is
  // a special local-variable, not programmer-defined local-variable
  public void computeScopeFlags() {
    if (flagsComputed) {
      return;
    }

    // init
    canModifyCode = true;
    canCaptureCallersBinding = false;
    usesZSuper = false;
    usesEval = false;
    usesBackrefOrLastline = false;
    // NOTE: bindingHasEscaped is the crucial flag and it effectively is
    // unconditionally true whenever it has a call that receives a closure.
    // See CallInstr.computeRequiresCallersBindingFlag
    bindingHasEscaped =
        (this instanceof IREvalScript); // for eval scopes, bindings are considered escaped ...
    hasBreakInstrs = false;
    hasNonlocalReturns = false;
    canReceiveBreaks = false;
    canReceiveNonlocalReturns = false;

    // recompute flags -- we could be calling this method different times
    // definitely once after ir generation and local optimizations propagates constants locally
    // but potentially at a later time after doing ssa generation and constant propagation
    if (cfg == null) {
      computeScopeFlags(false, getInstrs());
    } else {
      boolean receivesClosureArg = false;
      for (BasicBlock b : cfg.getBasicBlocks()) {
        receivesClosureArg = computeScopeFlags(receivesClosureArg, b.getInstrs());
      }
    }

    // Compute flags for nested closures (recursively) and set derived flags.
    for (IRClosure cl : getClosures()) {
      cl.computeScopeFlags();
      if (cl.hasBreakInstrs || cl.canReceiveBreaks) {
        canReceiveBreaks = true;
      }
      if (cl.hasNonlocalReturns || cl.canReceiveNonlocalReturns) {
        canReceiveNonlocalReturns = true;
      }
      if (cl.usesZSuper()) {
        usesZSuper = true;
      }
    }

    flagsComputed = true;
  }