code: private Node tryRemoveRedundantExit(Node n) {
      Node exitExpr = n.getFirstChild();
  
      Node follow = ControlFlowAnalysis.computeFollowNode(n);
  
      // Skip pass all the finally blocks because both the fall through and return
      // will also trigger all the finally blocks.
      Node prefinallyFollows = follow;
      follow = skipFinallyNodes(follow);
      if (prefinallyFollows != follow) {
        // There were finally clauses
        if (!isPure(exitExpr)) {
          // Can't replace the return
          return n;
        }
      }
  
      if (follow == null && (n.isThrow() || exitExpr != null)) {
        // Can't complete remove a throw here or a return with a result.
        return n;
      }
  
      // When follow is null, this mean the follow of a break target is the
      // end of a function. This means a break is same as return.
      if (follow == null || areMatchingExits(n, follow)) {
        reportChangeToEnclosingScope(n);
        n.detach();
        return null;
      }
  
      return n;
    }
docs: Remove duplicate exits.  If the node following the exit node expression
  has the same effect as exit node, the node can be removed.
  For example:
  "if (a) {return f()} return f();" ==> "if (a) {} return f();"
  "if (a) {throw 'ow'} throw 'ow';" ==> "if (a) {} throw 'ow';"
  
  @param n An follow control exit expression (a THROW or RETURN node)
  @return The replacement for n, or the original if no change was made.