/**
     * Determines whether this block is guaranteed to begin executing before the given block does.
     */
    boolean provablyExecutesBefore(BasicBlock thatBlock) {
      // If thatBlock is a descendant of this block, and there are no hoisted
      // blocks between them, then this block must start before thatBlock.
      BasicBlock currentBlock;
      for (currentBlock = thatBlock;
          currentBlock != null && currentBlock != this;
          currentBlock = currentBlock.getParent()) {}

      if (currentBlock == this) {
        return true;
      }
      return isGlobalScopeBlock() && thatBlock.isGlobalScopeBlock();
    }
    /** @return Whether the variable is only assigned a value once for its lifetime. */
    boolean isAssignedOnceInLifetime() {
      Reference ref = getOneAndOnlyAssignment();
      if (ref == null) {
        return false;
      }

      // Make sure this assignment is not in a loop.
      for (BasicBlock block = ref.getBasicBlock(); block != null; block = block.getParent()) {
        if (block.isFunction) {
          if (ref.getSymbol().getScope() != ref.scope) {
            return false;
          }
          break;
        } else if (block.isLoop) {
          return false;
        }
      }

      return true;
    }
    /**
     * Determines if the variable for this reference collection is "well-defined." A variable is
     * well-defined if we can prove at compile-time that it's assigned a value before it's used.
     *
     * <p>Notice that if this function returns false, this doesn't imply that the variable is used
     * before it's assigned. It just means that we don't have enough information to make a
     * definitive judgment.
     */
    protected boolean isWellDefined() {
      int size = references.size();
      if (size == 0) {
        return false;
      }

      // If this is a declaration that does not instantiate the variable,
      // it's not well-defined.
      Reference init = getInitializingReference();
      if (init == null) {
        return false;
      }

      Preconditions.checkState(references.get(0).isDeclaration());
      BasicBlock initBlock = init.getBasicBlock();
      for (int i = 1; i < size; i++) {
        if (!initBlock.provablyExecutesBefore(references.get(i).getBasicBlock())) {
          return false;
        }
      }

      return true;
    }