home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / compiler / stack.lisp < prev    next >
Encoding:
Text File  |  1991-11-06  |  9.8 KB  |  260 lines

  1. ;;; -*- Package: C; Log: C.Log -*-
  2. ;;;
  3. ;;; **********************************************************************
  4. ;;; This code was written as part of the CMU Common Lisp project at
  5. ;;; Carnegie Mellon University, and has been placed in the public domain.
  6. ;;; If you want to use this code or any part of CMU Common Lisp, please contact
  7. ;;; Scott Fahlman or slisp-group@cs.cmu.edu.
  8. ;;;
  9. (ext:file-comment
  10.   "$Header: stack.lisp,v 1.5 91/05/08 01:15:34 ram Exp $")
  11. ;;;
  12. ;;; **********************************************************************
  13. ;;;
  14. ;;;    The stack analysis phase in the compiler.  We do a graph walk to
  15. ;;; determine which unknown-values continuations are on the stack at each point
  16. ;;; in the program, and then we insert cleanup code to pop off unused values.
  17. ;;;
  18. ;;; Written by Rob MacLachlan
  19. ;;;
  20. (in-package 'c)
  21.  
  22.  
  23. ;;; Find-Pushed-Continuations  --  Internal
  24. ;;;
  25. ;;;    Scan through Block looking for uses of :Unknown continuations that have
  26. ;;; their Dest outside of the block.  We do some checking to verify the
  27. ;;; invariant that all pushes come after the last pop.
  28. ;;;
  29. (defun find-pushed-continuations (block)
  30.   (let* ((2block (block-info block))
  31.      (popped (ir2-block-popped 2block))
  32.      (last-pop (if popped
  33.                (continuation-dest (car (last popped)))
  34.                nil)))
  35.     (collect ((pushed))
  36.       (let ((saw-last nil))
  37.     (do-nodes (node cont block)
  38.       (when (eq node last-pop)
  39.         (setq saw-last t))
  40.  
  41.       (let ((dest (continuation-dest cont))
  42.         (2cont (continuation-info cont)))
  43.         (when (and dest
  44.                (not (eq (node-block dest) block))
  45.                2cont
  46.                (eq (ir2-continuation-kind 2cont) :unknown))
  47.           (assert (or saw-last (not last-pop)))
  48.           (pushed cont)))))
  49.  
  50.       (setf (ir2-block-pushed 2block) (pushed))))
  51.   (undefined-value))
  52.  
  53.  
  54. ;;;; Annotation graph walk:
  55.  
  56. ;;; Stack-Simulation-Walk  --  Internal
  57. ;;;
  58. ;;;    Do a backward walk in the flow graph simulating the run-time stack of
  59. ;;; unknown-values continuations and annotating the blocks with the result.
  60. ;;;
  61. ;;;    Block is the block that is currently being walked and Stack is the stack
  62. ;;; of unknown-values continuations in effect immediately after block.  We
  63. ;;; simulate the stack by popping off the unknown-values generated by this
  64. ;;; block (if any) and pushing the continuations for values received by this
  65. ;;; block.  (The role of push and pop are interchanged because we are doing a
  66. ;;; backward walk.)
  67. ;;;
  68. ;;;    If we run into a values generator whose continuation isn't on stack top,
  69. ;;; then the receiver hasn't yet been reached on any walk to this use.  In this
  70. ;;; case, we ignore the push for now, counting on Annotate-Dead-Values to clean
  71. ;;; it up if we discover that it isn't reachable at all.
  72. ;;;
  73. ;;;    If our final stack isn't empty, then we walk all the predecessor blocks
  74. ;;; that don't have all the continuations that we have on our Start-Stack on
  75. ;;; their End-Stack.  This is our termination condition for the graph walk.  We
  76. ;;; put the test around the recursive call so that the initial call to this
  77. ;;; function will do something even though there isn't initially anything on
  78. ;;; the stack.
  79. ;;;
  80. ;;;    We can use the tailp test, since the only time we want to bottom out
  81. ;;; with a non-empty stack is when we intersect with another path from the same
  82. ;;; top-level call to this function that has more values receivers on that
  83. ;;; path.  When we bottom out in this way, we are counting on
  84. ;;; DISCARD-UNUSED-VALUES doing its thing.
  85. ;;;
  86. ;;;    When we do recurse, we check that predecessor's END-STACK is a
  87. ;;; subsequence of our START-STACK.  There may be extra stuff on the top
  88. ;;; of our stack because the last path to the predecessor may have discarded
  89. ;;; some values that we use.  There may be extra stuff on the bottom of our
  90. ;;; stack because this walk may be from a values receiver whose lifetime
  91. ;;; encloses that of the previous walk.
  92. ;;;
  93. ;;;    If a predecessor block is the component head, then it must be the case
  94. ;;; that this is a NLX entry stub.  If so, we just stop our walk, since the
  95. ;;; stack at the exit point doesn't have anything to do with our stack.
  96. ;;;
  97. (defun stack-simulation-walk (block stack)
  98.   (declare (type cblock block) (list stack))
  99.   (let ((2block (block-info block)))
  100.     (setf (ir2-block-end-stack 2block) stack)
  101.     (let ((new-stack stack))
  102.       (dolist (push (reverse (ir2-block-pushed 2block)))
  103.     (if (eq (car new-stack) push)
  104.         (pop new-stack)
  105.         (assert (not (member push new-stack)))))
  106.       
  107.       (dolist (pop (reverse (ir2-block-popped 2block)))
  108.     (push pop new-stack))
  109.       
  110.       (setf (ir2-block-start-stack 2block) new-stack)
  111.       
  112.       (when new-stack
  113.     (dolist (pred (block-pred block))
  114.       (if (eq pred (component-head (block-component block)))
  115.           (assert (find block
  116.                 (environment-nlx-info (block-environment block))
  117.                 :key #'nlx-info-target))
  118.           (let ((pred-stack (ir2-block-end-stack (block-info pred))))
  119.         (unless (tailp new-stack pred-stack)
  120.           (assert (search pred-stack new-stack))
  121.           (stack-simulation-walk pred new-stack))))))))
  122.  
  123.   (undefined-value))
  124.  
  125.  
  126. ;;; Annotate-Dead-Values  --  Internal
  127. ;;;
  128. ;;;    Do stack annotation for any values generators in Block that were
  129. ;;; unreached by all walks (i.e. the continuation isn't live at the point that
  130. ;;; it is generated.)  This will only happen when the values receiver cannot be
  131. ;;; reached from this particular generator (due to an unconditional control
  132. ;;; transfer.)
  133. ;;;
  134. ;;;    What we do is push on the End-Stack all continuations in Pushed that
  135. ;;; aren't already present in the End-Stack.  When we find any pushed
  136. ;;; continuation that isn't live, it must be the case that all continuations
  137. ;;; pushed after (on top of) it aren't live.
  138. ;;;
  139. ;;;    If we see a pushed continuation that is the CONT of a tail call, then we
  140. ;;; ignore it, since the tail call didn't actually push anything.  The tail
  141. ;;; call must always the last in the block. 
  142. ;;;
  143. (defun annotate-dead-values (block)
  144.   (declare (type cblock block))
  145.   (let* ((2block (block-info block))
  146.      (stack (ir2-block-end-stack 2block))
  147.      (last (block-last block))
  148.      (tailp-cont (if (node-tail-p last) (node-cont last))))
  149.     (do ((pushes (ir2-block-pushed 2block) (rest pushes))
  150.      (popping nil))
  151.     ((null pushes))
  152.       (let ((push (first pushes)))
  153.     (cond ((member push stack)
  154.            (assert (not popping)))
  155.           ((eq push tailp-cont)
  156.            (assert (null (rest pushes))))
  157.           (t
  158.            (push push (ir2-block-end-stack 2block))
  159.            (setq popping t))))))
  160.   
  161.   (undefined-value))
  162.  
  163.  
  164. ;;; Discard-Unused-Values  --  Internal
  165. ;;;
  166. ;;;    Called when we discover that the stack-top unknown-values continuation
  167. ;;; at the end of Block1 is different from that at the start of Block2 (its
  168. ;;; successor.)
  169. ;;;
  170. ;;;    We insert a call to a funny function in a new cleanup block introduced
  171. ;;; between Block1 and Block2.  Since control analysis and LTN have already
  172. ;;; run, we must do make an IR2 block, then do ADD-TO-EMIT-ORDER and
  173. ;;; LTN-ANALYZE-BLOCK on the new block.  The new block is inserted after Block1
  174. ;;; in the emit order.
  175. ;;;
  176. ;;;    If the control transfer between Block1 and Block2 represents a
  177. ;;; tail-recursive return (:Deleted IR2-continuation) or a non-local exit, then
  178. ;;; the cleanup code will never actually be executed.  It doesn't seem to be
  179. ;;; worth the risk of trying to optimize this, since this rarely happens and
  180. ;;; wastes only space.
  181. ;;;
  182. (defun discard-unused-values (block1 block2)
  183.   (declare (type cblock block1 block2))
  184.   (let* ((block1-stack (ir2-block-end-stack (block-info block1)))
  185.      (block2-stack (ir2-block-start-stack (block-info block2)))
  186.      (last-popped (elt block1-stack
  187.                (- (length block1-stack)
  188.                   (length block2-stack)
  189.                   1))))
  190.     (assert (tailp block2-stack block1-stack))
  191.  
  192.     (let* ((block (insert-cleanup-code block1 block2
  193.                        (continuation-next (block-start block2))
  194.                        `(%pop-values ',last-popped)))
  195.        (2block (make-ir2-block block)))
  196.       (setf (block-info block) 2block)
  197.       (add-to-emit-order 2block (block-info block1))
  198.       (ltn-analyze-block block)))
  199.  
  200.   (undefined-value))
  201.  
  202.  
  203. ;;;; Stack analyze:
  204.  
  205.  
  206. ;;; FIND-VALUES-GENERATORS  --  Internal
  207. ;;;
  208. ;;;    Return a list of all the blocks containing genuine uses of one of the
  209. ;;; Receivers.  Exits are excluded, since they don't drop through to the
  210. ;;; receiver.
  211. ;;;
  212. (defun find-values-generators (receivers)
  213.   (declare (list receivers))
  214.   (collect ((res nil adjoin))
  215.     (dolist (rec receivers)
  216.       (dolist (pop (ir2-block-popped (block-info rec)))
  217.     (do-uses (use pop)
  218.       (unless (exit-p use)
  219.         (res (node-block use))))))
  220.     (res)))
  221.  
  222.  
  223. ;;; Stack-Analyze  --  Interface
  224. ;;;
  225. ;;;    Analyze the use of unknown-values continuations in Component, inserting
  226. ;;; cleanup code to discard values that are generated but never received.  This
  227. ;;; phase doesn't need to be run when Values-Receivers is null, i.e. there are
  228. ;;; no unknown-values continuations used across block boundaries.
  229. ;;;
  230. ;;;    Do the backward graph walk, starting at each values receiver.  We ignore
  231. ;;; receivers that already have a non-null Start-Stack.  These are nested
  232. ;;; values receivers that have already been reached on another walk.  We don't
  233. ;;; want to clobber that result with our null initial stack. 
  234. ;;;
  235. (defun stack-analyze (component)
  236.   (declare (type component component))
  237.   (let* ((2comp (component-info component))
  238.      (receivers (ir2-component-values-receivers 2comp))
  239.      (generators (find-values-generators receivers)))
  240.  
  241.     (dolist (block generators)
  242.       (find-pushed-continuations block))
  243.     
  244.     (dolist (block receivers)
  245.       (unless (ir2-block-start-stack (block-info block))
  246.     (stack-simulation-walk block ())))
  247.     
  248.     (dolist (block generators)
  249.       (annotate-dead-values block))
  250.     
  251.     (do-blocks (block component)
  252.       (let ((top (car (ir2-block-end-stack (block-info block)))))
  253.     (dolist (succ (block-succ block))
  254.       (when (and (block-start succ)
  255.              (not (eq (car (ir2-block-start-stack (block-info succ)))
  256.                   top)))
  257.         (discard-unused-values block succ))))))
  258.   
  259.   (undefined-value))
  260.