pcs/newpcs/psimp.s

428 lines
11 KiB
Common Lisp
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; -*- Mode: Lisp -*- Filename: psimp.s
; Last Revision: 1-Oct-85 1630ct
;--------------------------------------------------------------------------;
; ;
; TI SCHEME -- PCS Compiler ;
; Copyright 1985 (c) Texas Instruments ;
; ;
; David Bartley ;
; ;
; Program Simplification ;
; (for use only after alpha conversion) ;
; ;
;--------------------------------------------------------------------------;
(define pcs-simplify
(lambda (exp)
(letrec
;-------!
((simp
(lambda (x)
(if (atom? x)
x
(case (car x)
(quote x)
(T x) ; ID record
(lambda (simp-lambda x))
(if (simp-if (simp (if-pred x))
(simp (if-then x))
(simp (if-else x))))
(set! (simp-set! (set!-id x)
(simp (set!-exp x))))
(begin (simp-begin (simp-args (cdr x) '())))
(letrec (simp-letrec
(simp-pairs (letrec-pairs x) '())
(simp (letrec-body x))))
(else (simp-application (simp-args x '())))
))))
(simp-lambda
(lambda (x) ; note: preserve extra slots in the node
(begin ; This changes the apparent output of PME!!
(set-lambda-body x (simp (lambda-body x)))
x)))
(simp-if
(lambda (p th el)
(cond ;; --- (if p (if p a b) c) ==> (if p a c)
((and (eq? (car th) 'if)
(dupe? p) ; no side effects
(equal? p (if-pred th)))
(simp-if p (if-then th) el))
;; --- (if p a (if p b c)) ==> (if p a c)
((and (eq? (car el) 'if)
(dupe? p) ; no side effects
(equal? p (if-pred el)))
(simp-if p th (if-else el)))
;; --- (if #!false a b) ==> b
;; --- (if '* a b) ==> a
((eq? (car p) 'quote)
(if (cadr p) th el))
;; --- (if (not a) b c) ==> (if a c b)
((eq? (car p) 'not)
(simp-if (cadr p) el th))
;; --- (if (begin ... p) a b)
;; ==> (begin ... (if p a b))
((eq? (car p) 'begin)
(let ((sl (reverse (cdr p))))
(simp-begin
(reverse! (cons (simp-if (car sl) th el)
(cdr sl))))))
;; --- (if (if a b c) d e)
;;
;; ==> (if a (if b d e)
;; (if c d e))
((eq? (car p) 'if)
(cond ((dupe? th)
(let ((a (if-pred p))
(b (if-then p))
(c (if-else p)))
(cond
;; --- (if (if a 't c) d e)
;; ==> (if a d (if c d e))
((and (pair? b)
(eq? (car b) 'QUOTE)
(cadr b))
(simp-if a th
(simp-if c th el)))
;; --- (if (if a b 't) d e)
;; ==> (if a (if b d e) d)
((and (pair? c)
(eq? (car c) 'QUOTE)
(cadr c))
(simp-if a (simp-if b th el) th))
;; --- (if (if a a c) d e)
;; ==> (if a d (if c d e))
((and (dupe? a)(equal? a b))
(simp-if a th (simp-if c th el)))
(else
(list 'if p th el)))))
;; The following turns out to "pessimize" the code
;; given the current code generator algorithms
;; ((dupe? el)
;; (let ((a (if-pred p))
;; (b (if-then p))
;; (c (if-else p)))
;; (cond
;; --- (if (if a #!false c) d e)
;; ==> (if a e (if c d e))
;; ((equal? b '(quote #!false))
;; (simp-if a el (simp-if c th el)))
;; --- (if (if a b #!false) d e)
;; ==> (if a (if b d e) e)
;; ((equal? c '(quote #!false))
;; (simp-if a (simp-if b th el) el))
;; (else
;; (list 'if p th el)))))
(else
(list 'if p th el))))
(else
(list 'if p th el)))))
(dupe?
(lambda (x)
(or (atom? x)
(memq (car x)
'(T QUOTE %%get-global%% %%get-fluid%%)))))
(simp-set!
(lambda (id exp)
(cond
;; --- (set! a a) ==> a
((eq? id exp) id)
;; --- (set! x (if a b c))
;; ==> (if a (set! x b)(set! x c))
((eq? (car exp) 'if)
(simp-if (if-pred exp)
(simp-set! id (if-then exp))
(simp-set! id (if-else exp))))
(else
(list 'set! id exp)))))
(simp-begin
(lambda (sl)
(let ((sl (s-begin (reverse! sl) '())))
(cond ((null? sl) '(quote ()))
((null? (cdr sl)) (car sl))
(else
(cons 'begin sl))))))
(s-begin
(lambda (old new)
(if (null? old)
new
(let ((s (car old)))
(cond ((and new ; not last exp
(memq (car s)
'(T QUOTE LAMBDA
%%get-global%%
%%get-fluid%%)))
(s-begin (cdr old) new)) ; delete s
((or (eq? (car s) 'begin)
(and new (no-se-op (car s))))
(s-begin (append! (reverse! (cdr s))
(cdr old))
new))
(t (s-begin (cdr old)
(cons s new))))))))
;;; (simp-apply
;;; (lambda (fun arg)
;;; (cond
;;; ;; --- (apply (lambda (a ...) body) arg)
;;; ;; ==> (let ((L arg))
;;; ;; (let ((a (car L))...) body))
;;;
;;; ((and (eq? (car fun) 'lambda)
;;; (not (negative? (lambda-nargs fun))))
;;; (simp-apply-letrec
;;; (lambda-bvl fun) (lambda-body fun) arg #!false))
;;;
;;; (t (list '%apply fun arg)))))
;;;(simp-apply-letrec
;;;(lambda (bvl body arg dupe?)
;;; ;; (apply (lambda () body) L)
;;; ;; ==> (begin L body)
;;; (if (null? bvl)
;;; (simp-begin (list arg body))
;;; (let ((a (car bvl)))
;;; (cond
;;; ;; (apply (lambda (a ...) body) (cons x y))
;;; ;; ==> (let ((a x))
;;; ;; (apply (lambda (...) body) y))
;;; ((eq? (car arg) 'cons)
;;; (simp-letrec
;;; `((,a ,(cadr arg)))
;;; (simp-apply-letrec
;;; (cdr bvl) body (caddr arg) #!false)))
;;;
;;; ;; (apply (lambda (a) body) L)
;;; ;; ==> (let ((a (car L))) body)
;;; ((null? (cdr bvl))
;;; (simp-letrec
;;; `((,a (car ,arg)))
;;; body))
;;; ;; (apply (lambda (a...) body) triv)
;;; ;; ==> (let ((a (car triv)))
;;; ;; (apply (lambda (...) body)
;;; ;; (cdr triv)))
;;; ((or dupe?
;;; (memq (car arg) '(T QUOTE)))
;;; (simp-letrec
;;; `((,a (car ,arg)))
;;; (simp-apply-letrec
;;; (cdr bvl) body `(cdr ,arg) 't)))
;;;
;;; ;; (apply (lambda (a...) body) L)
;;; ;; ==> (let ((temp L))
;;; ;; (let ((a (car L)))
;;; ;; (apply (lambda (...) body)
;;; ;; (cdr temp))))
;;; (t
;;; (let ((temp (pcs-make-id '())))
;;; (simp-letrec
;;; `((,temp ,arg))
;;; (simp-letrec
;;; `((,a (car ,temp)))
;;; (simp-apply-letrec
;;; (cdr bvl) body `(cdr ,temp) 't)))))
;;; )))))
(simp-letrec
(lambda (pairs body)
(cond
;; --- (letrec () body) ==> body
((and (null? pairs)
(not debug-mode))
body)
;; --- (letrec ((a '*)...)
;; (begin (set! a value) ...))
;; --- (letrec (...(a value))
;; (begin ...))
;;; omit: works, but not worth doing
;;; ((and (eq? (car body) 'begin)
;;; (eq? (car (cadr body)) 'set!)
;;; (eq? (set!-id (cadr body)) (caar pairs))
;;; (eq? (car (cadar pairs)) 'quote)
;;; (memq (car (set!-exp (cadr body)))
;;; '(quote lambda)))
;;; (simp-letrec
;;; (append (cdr pairs)
;;; (list
;;; (list (caar pairs)
;;; (set!-exp (cadr body)))))
;;; (simp-begin
;;; (cddr body))))
;; --- (letrec ((a '*)...)
;; (set! a value))
;; --- (letrec (...(a value))
;; a)
;;; omit: works, but not worth doing
;;; ((and (eq? (car body) 'set!)
;;; (eq? (set!-id body) (caar pairs))
;;; (eq? (car (cadar pairs)) 'quote)
;;; (memq (car (set!-exp body))
;;; '(quote lambda)))
;;; (simp-letrec
;;; (append! (cdr pairs)
;;; (list
;;; (list (set!-id body)
;;; (set!-exp body))))
;;; (set!-id body)))
(t (list 'letrec pairs body)))))
(simp-pairs
(lambda (old new)
(if (null? old)
(reverse! new)
(simp-pairs (cdr old)
(cons (list (caar old)
(simp (cadar old)))
new)))))
(simp-car
(lambda (x)
(if (atom? x)
(list 'CAR x)
(let ((op (assq (car x) '((CAR . CAAR)(CADR . CAADR)
(CDR . CADR)(CDDR . CADDR)
(CDDDR . CADDDR)))))
(if op
(cons (cdr op)(cdr x))
(list 'CAR x))))))
(simp-cdr
(lambda (x)
(if (atom? x)
(list 'CDR x)
(let ((op (assq (car x) '((CAR . CDAR)(CADR . CDADR)
(CDR . CDDR)(CDDR . CDDDR)))))
(if op
(cons (cdr op)(cdr x))
(list 'CDR x))))))
(simp-=
(lambda (op x y)
(if (and (eq? (car y) 'QUOTE)
(number? (cadr y)))
(let ((rop (assq op '((= . =) (< . >) (> . <)
(<= . >=) (>= . <=) (<> . <>)))))
(if rop
(list (cdr rop) y x)
(list op x y)))
(list op x y))))
(simp-application
(lambda (comb) ; COMB is already simplified
(let ((f (car comb))
(args (cdr comb)))
(cond ((atom? f) ; primitive
(case f
;;; ((%apply) (simp-apply (car args) (cadr args)))
((car) (simp-car (car args)))
((cdr) (simp-cdr (car args)))
((= < > <= >= <>)
(simp-= f (car args) (cadr args)))
(else
comb)))
;; --- ((lambda () body)) ==> body
((and (not debug-mode)
(eq? (car f) 'lambda)
(null? args)
(null? (lambda-bvl f)))
(lambda-body f))
;; --- ((lambda (a b)(foo a b))
;; x y)
;; ==> (foo x y)
((and (not debug-mode)
(eq? (car f) 'lambda)
(let ((foo (car (lambda-body f))))
(cond ((atom? foo)
(getprop foo 'pcs*opcode))
((eq? (car foo) 'T)
(not (memq foo (lambda-bvl f))))
(else
(eq? (car foo) '%%get-global%%))))
(equal? (cdr (lambda-body f)) ; (... a b)
(lambda-bvl f))) ; (a b)
(simp-application
(cons (car (lambda-body f))
args)))
;; --- ((letrec pairs body) . args)
;; ==> (letrec pairs (body . args))
((eq? (car f) 'letrec)
(simp-letrec
(letrec-pairs f)
(simp-application
`(,(letrec-body f) . ,args))))
(t comb)))))
(simp-args
(lambda (old new)
(if (null? old)
(reverse! new)
(simp-args (cdr old)
(cons (simp (car old))
new)))))
(no-se-op
(lambda (op)
(and (symbol? op)
(getprop op 'pcs*primop-handler) ; not a 'magic' primop
(let ((opcode (getprop op 'pcs*opcode)))
(and (integer? opcode)
(positive? opcode))))))
;;; data
(debug-mode pcs-debug-mode)
;-------!
)
(simp exp))))