gjs-cselim.scm 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. ;;;; Simple-minded common-subexpression eliminator.
  21. ;;; GJS, 9 December 2005
  22. (declare (usual-integrations))
  23. (define* (gjs/cselim expression #:optional not-worth-subdividing?)
  24. (if (default-object? not-worth-subdividing?)
  25. (set! not-worth-subdividing? (lambda (expr) #f)))
  26. (let ((initial-expression-recorder
  27. (make-expression-recorder #f '())))
  28. (define (walk expression expression-recorder)
  29. (cond ((symbol? expression) expression)
  30. ((not-worth-subdividing? expression)
  31. (record-expression! expression-recorder expression '()))
  32. ((pair? expression)
  33. (case (car expression)
  34. ((quote) expression)
  35. ((lambda)
  36. (let* ((new-bound-variables (cadr expression))
  37. (local-expression-recorder
  38. (make-expression-recorder expression-recorder
  39. new-bound-variables))
  40. (canonicalized-body
  41. (if (symbol? (caddr expression))
  42. (record-expression! local-expression-recorder
  43. (caddr expression)
  44. '())
  45. (walk (caddr expression)
  46. local-expression-recorder)))
  47. (let-variables
  48. (expressions-seen local-expression-recorder))
  49. (lambda-body
  50. (variable->expression local-expression-recorder
  51. canonicalized-body))
  52. (canonical-expression
  53. `(lambda ,new-bound-variables
  54. ,(make-canonical-lets let-variables lambda-body))))
  55. (record-expression! expression-recorder
  56. canonical-expression
  57. new-bound-variables)))
  58. ((let)
  59. (if (symbol? (cadr expression))
  60. (error "Not implemented")
  61. (let* ((new-bound-variables (map car (cadr expression)))
  62. (values
  63. (map (lambda (subexpression)
  64. (walk subexpression expression-recorder))
  65. (map cadr (cadr expression))))
  66. (local-expression-recorder
  67. (make-expression-recorder expression-recorder
  68. new-bound-variables))
  69. (canonicalized-body
  70. (if (symbol? (caddr expression))
  71. (record-expression! local-expression-recorder
  72. (caddr expression)
  73. '())
  74. (walk (caddr expression)
  75. local-expression-recorder)))
  76. (let-variables
  77. (expressions-seen local-expression-recorder))
  78. (let-body
  79. (variable->expression local-expression-recorder
  80. canonicalized-body))
  81. (canonical-expression
  82. (make-let-expression (cadr expression)
  83. (make-canonical-lets let-variables
  84. let-body))))
  85. (record-expression! expression-recorder
  86. canonical-expression
  87. new-bound-variables))))
  88. (else
  89. (let ((canonical-expression
  90. (map (lambda (subexpression)
  91. (walk subexpression expression-recorder))
  92. expression)))
  93. (record-expression! expression-recorder
  94. canonical-expression
  95. '())))))
  96. (else expression)))
  97. (let* ((canonical-expression
  98. (walk expression initial-expression-recorder))
  99. (let-variables
  100. (expressions-seen initial-expression-recorder))
  101. (let-body
  102. (variable->expression initial-expression-recorder
  103. canonical-expression)))
  104. (make-canonical-lets let-variables let-body))))
  105. (define (make-let-expression bindings body)
  106. (let ((used-bindings
  107. (filter (lambda (b)
  108. (occurs-in? (car b) body))
  109. bindings)))
  110. (cond ((null? used-bindings) body)
  111. (else
  112. `(let ,used-bindings ,body)))))
  113. (define (make-canonical-lets variable-bindings body)
  114. (cond ((null? variable-bindings) body)
  115. ((null? (cdr variable-bindings))
  116. `(let ,variable-bindings ,body))
  117. (else
  118. `(let* ,variable-bindings ,body))))
  119. (define (make-expression-recorder parent-recorder bound-variables)
  120. (let ((local-expressions-seen '()))
  121. (lambda (message)
  122. (case message
  123. ((record!)
  124. (lambda (expression ignored-variables)
  125. (cond ((or (not parent-recorder)
  126. (occurs-in? bound-variables expression))
  127. (let ((vcell (assoc expression local-expressions-seen)))
  128. (cond (vcell
  129. ;; Increment reference count
  130. (set-car! (cddr vcell) (fix:+ (caddr vcell) 1))
  131. (cadr vcell))
  132. (else
  133. (let ((name (generate-uninterned-symbol)))
  134. (set! local-expressions-seen
  135. (cons (list expression name 1)
  136. local-expressions-seen))
  137. (set! bound-variables
  138. (cons name bound-variables))
  139. name)))))
  140. (else
  141. ((parent-recorder 'record!) expression ignored-variables)))))
  142. ((seen)
  143. (let lp ((entries (reverse local-expressions-seen)) (results '()))
  144. (cond ((null? entries) (reverse results))
  145. ((fix:= (caddar entries) 1)
  146. (for-each
  147. (lambda (entry)
  148. (set-car! entry
  149. (subst (caar entries) (cadar entries) (car entry))))
  150. (cdr entries))
  151. (lp (cdr entries) results))
  152. (else
  153. (lp (cdr entries)
  154. (cons (list (cadar entries) (caar entries))
  155. results))))))
  156. ((get-entry)
  157. (lambda (variable)
  158. (if (symbol? variable)
  159. (let ((entry
  160. (find-matching-item local-expressions-seen
  161. (lambda (entry) (eq? (cadr entry) variable)))))
  162. (if entry
  163. entry
  164. (if parent-recorder
  165. ((parent-recorder 'get-entry) variable)
  166. (error "Variable not present"))))
  167. (list variable))))
  168. (else
  169. (error "unknown message: expression-recorder" message))))))
  170. (define (record-expression! expression-recorder expression ignored-variables)
  171. ((expression-recorder 'record!) expression ignored-variables))
  172. (define (expressions-seen expression-recorder)
  173. (expression-recorder 'seen))
  174. (define (variable->expression expression-recorder variable)
  175. (car ((expression-recorder 'get-entry) variable)))
  176. (define (occurs-in? variables expression)
  177. (let lp ((expression expression))
  178. (cond ((pair? expression)
  179. (or (lp (car expression))
  180. (lp (cdr expression))))
  181. ((pair? variables)
  182. (memq expression variables))
  183. (else
  184. (eq? variables expression)))))
  185. #|
  186. (pp (gjs/cselim '(+ (* x 3) (- x y) (* x 3))))
  187. (let ((G306 (* x 3)))
  188. (+ G306 (- x y) G306))
  189. (pp (gjs/cselim
  190. '(lambda (x)
  191. (/ (+ (* x 3) (- y z) (- x y) (* x 3))
  192. (- y z)))))
  193. (let ((G301 (- y z)))
  194. (lambda (x)
  195. (let ((G300 (* x 3)))
  196. (/ (+ G300 G301 (- x y) G300)
  197. G301))))
  198. (pp (gjs/cselim
  199. '(let ((x 32) (y 5))
  200. (+ (* x 3) (- x y) (* x 3)))))
  201. (let ((x 32) (y 5))
  202. (let ((G296 (* x 3)))
  203. (+ G296 (- x y) G296)))
  204. (pp
  205. (gjs/cselim
  206. '(up
  207. (+ (/ (* 1/3 GM (expt dt 3) p_r_0) (* (expt m 2) (expt r_0 3)))
  208. (/ (* -1/2 (expt dt 3) (expt p_phi_0 2) p_r_0) (* (expt m 3) (expt r_0 4))))
  209. (+ (/ (* (expt dt 3) p_phi_0 (expt p_r_0 2)) (* (expt m 3) (expt r_0 4)))
  210. (/ (* 1/3 GM (expt dt 3) p_phi_0) (* (expt m 2) (expt r_0 5)))
  211. (/ (* -1/3 (expt dt 3) (expt p_phi_0 3)) (* (expt m 3) (expt r_0 6)))))
  212. (fringe-smaller-than? 7)))
  213. (let* ((G44125 (expt dt 3)) (G44128 (* (expt m 3) (expt r_0 4))))
  214. (up
  215. (+ (/ (* 1/3 GM (expt dt 3) p_r_0) (* (expt m 2) (expt r_0 3)))
  216. (/ (* -1/2 G44125 (expt p_phi_0 2) p_r_0) G44128))
  217. (+ (/ (* G44125 p_phi_0 (expt p_r_0 2)) G44128)
  218. (/ (* 1/3 GM (expt dt 3) p_phi_0) (* (expt m 2) (expt r_0 5)))
  219. (/ (* -1/3 G44125 (expt p_phi_0 3)) (* (expt m 3) (expt r_0 6))))))
  220. |#