File: cells.lsp

package info (click to toggle)
xlispstat 3.52.14-1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 7,560 kB
  • ctags: 12,676
  • sloc: ansic: 91,357; lisp: 21,759; sh: 1,525; makefile: 521; csh: 1
file content (145 lines) | stat: -rw-r--r-- 4,536 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
(in-package "XLSCMP")

;;;;;
;;;;; Cell Insertion Phase
;;;;;

;;**** check this over carefully!!!
;;**** assumes cells can be determined from tree
;;**** change %setq to %set-cell-value here
(defun find-variables-set (tree)
  (let ((svars nil)
	(nodes (list tree)))
    (loop
     (if (null nodes) (return))
     (let ((n (pop nodes)))
       (dolist (c (node-children n))
	 (if (call-node-p c)
	     (let ((f (call-node-function c)))
	       (if (gfun-eq f '%setq)
		   (push (call-node-arg c 1) svars))))
	 (push c nodes))))
    svars))

(defun insert-cells (tree)
  (let ((svars (find-variables-set tree)))
    (dolist (sv (remove-duplicates svars))
      (let* ((owner (symbol-node-owner sv))
	     (ob (lambda-node-body owner))
	     (refs (find-references sv ob))
	     (cn (make-leaf-node (gensym "C"))))
	(insert-node-tree
	 (make-call-node (get-gfun-node '%make-cell)
			 (make-continuation-node (list cn) ob)
			 sv)
	 owner
	 0)
	(dolist (r refs)
          (let* ((form (car r))
		 (i (cdr r))
		 (f (call-node-function form))
		 (p (node-parent form))
		 (j (position form (node-children p))))
	    (if (and (gfun-eq f '%setq) (= i 2))
		(substitute-value cn r nil) ;**** better choice??
	        (let ((vn (make-leaf-node (gensym "V"))))
		  (substitute-value vn r nil) ;**** better choice??
		  (insert-node-tree
		   (make-call-node (get-gfun-node '%cell-value)
				   (make-continuation-node
				    (list vn)
				    form)
				   cn)
		   p
		   j))))))))
  (flet ((fixup (s ns n)
	   (let ((nf (get-gfun-node ns)))
	     (dolist (r (find-references (get-gfun-node s) n))
	       (substitute-value nf r nil)))))
    (fixup '%setq '%set-cell-value tree))
  tree)

;;;;;
;;;;; Drop Unused Cells
;;;;;
				     
(defun cell-used-p (refs n)
  (dolist (r refs nil)
    (let* ((form (car r))
	   (i (cdr r))
	   (f (call-node-function form)))
      (unless (leaf-node-p f) (return t))
      (case (gfun-symbol f)
        ((%cell-value %set-cell-value)
	 (unless (= i 2) (return t)))
	(t (return t))))))

(defun find-unused-cell-variable-references (n)
  (let ((refs (find-references (get-gfun-node '%make-cell) n))
	(vrlist nil))
    (dolist (r refs vrlist)
      (let* ((c (call-node-arg (car r) 0))
	     (cc (if (lambda-node-p c) c (find-lambda-binding c)))
	     (v (first (lambda-node-arglist cc)))
	     (vrefs (find-references v n)))
	(unless (cell-used-p vrefs n)
		(push (list v (car r) vrefs) vrlist))))))

#|
;; **** this should produce correct results, but it may not get rid of all
;; **** the copies that could be dropped.
(defun safe-cell-access-p (ref)
  (let* ((form (car ref))
	 (var (nth (cdr ref) (node-children form))) ;;****more efficient way?
	 (cc (symbol-node-owner var)))
    (do ((p (node-parent form) (node-parent p)))
	((eq p cc) t)
	(if (and (call-node-p p)
		 (not (gfun-member (call-node-function p)
				   '(%copy %cell-value))))
	    (return nil)))))
|#
;; **** this is a little more agressive, but should still be OK
;; **** it would be better if the function could be recognized as a real fun
(defun safe-cell-access-p (ref)
  (let* ((form (car ref))
	 (var (nth (cdr ref) (node-children form))) ;;****more efficient way?
	 (cc (symbol-node-owner var)))
    (do ((p (node-parent form) (node-parent p)))
	((eq p cc) t)
	(if (call-node-p p)
	    (let ((f (call-node-function p))
		  (a (call-node-args p)))
	      (cond
	       ((lambda-node-p f) (if (some #'lambda-node-p a) (return nil)))
	       ((gfun-member f '(%setq %set-cell-value))
		(let ((cell (call-node-arg (node-parent cc) 1)))
		  (if (eq cell (second a)) (return nil))))
	       (t (if (some #'lambda-node-p (rest a)) (return nil)))))))))

(defun remove-unused-cells (n)
  (let ((cvars (find-unused-cell-variable-references n)))
    (dolist (vr cvars)
      (let* ((cname (first vr))
	     (refs (third vr))
	     (mcf (second vr))
	     (v (call-node-arg mcf 1))
	     (c (call-node-arg mcf 0)))
	(dolist (r refs)
	  (let ((form (car r)))
	    (case (gfun-symbol (call-node-function form))
	      (%set-cell-value
	       (change-gfun form '%setq))
	      (%cell-value
	       (let* ((cc (call-node-arg form 0))
		      (vv (first (lambda-node-arglist cc)))
		      (vvrefs (find-references vv cc)))
		 (cond
		  ((every #'safe-cell-access-p vvrefs)
		   (dolist (r vvrefs) (substitute-value cname r nil))
		   (set-lambda-node-arglist-fix cc nil)
		   (set-node-children form (list cc))
		   (set-node-parent cc form))
		  (t (change-gfun form '%copy))))))))
	(change-gfun mcf '%copy))))
  (collapse-null-lambda-calls n))