; Copyright (c) 1994 by Richard Kelsey. See file COPYING. (define (put-literal-first call) (if (and (not (literal-node? (call-arg call 0))) (literal-node? (call-arg call 1))) (let ((arg1 (detach (call-arg call 0))) (arg0 (detach (call-arg call 1)))) (attach call 0 arg0) (attach call 1 arg1)))) (define (simplify-add call) (simplify-args call 0) (put-literal-first call) ((pattern-simplifier ((+ '0 x) x) ((+ 'a 'b) '(+ a b)) ((+ 'a (+ 'b x)) (+ x '(+ a b))) ((+ 'a (- x 'b)) (+ x '(- a b))) ; no overflow in Scheme, but what ((+ 'a (- 'b x)) (- '(+ a b) x)) ; about PreScheme? Could check the ((+ (+ 'a x) (+ 'b y)) (+ '(+ a b) (+ x y))) ((+ x (+ 'a y)) (+ 'a (+ x y)))) call)) ; result of the literal. Maybe these ; should be left out. (define-scheme-primop + #f type/integer simplify-add) (define (simplify-subtract call) (simplify-args call 0) ((pattern-simplifier ((- 'a 'b) '(- a b)) ((- x 'a) (+ '(- 0 a) x)) ((- 'a (+ 'b x)) (- '(- a b) x)) ; more overflow problems ((- 'a (- 'b x)) (+ x '(- a b))) ((- x (+ 'a y)) (+ '(- 0 a) (- x y))) ; ((- (+ 'a x) y) (+ 'a (- x y))) hmm - need to come up with a normal form ((- (+ 'a x) (+ 'b y)) (- (+ '(- a b) x) y))) call)) (define-scheme-primop - #f type/integer simplify-subtract) ; This should check for multiply by powers of 2 (other constants can be ; done later). (define (simplify-multiply call) (simplify-args call 0) (put-literal-first call) (cond ((power-of-two-literal (call-arg call 0)) => (lambda (i) (set-call-primop! call (get-prescheme-primop 'ashl)) (replace (call-arg call 0) (detach (call-arg call 1))) (attach call 1 (make-literal-node i type/unknown)))) (else ((pattern-simplifier ((* '0 x) '0) ((* '1 x) x) ((* 'a 'b) '(* a b)) ((* 'a (* x 'b)) (* x '(* a b))) ((* 'a (* 'b x)) (* x '(* a b)))) call)))) (define-scheme-primop * #f type/integer simplify-multiply) (define-scheme-primop small* #f type/integer simplify-multiply) (define (simplify-quotient call) (simplify-args call 0) (cond ;((power-of-two-literal (call-arg call 1)) ; => (lambda (i) ; (set-call-primop! call (get-prescheme-primop 'ashr)) ; (replace (call-arg call 1) (make-literal-node i type/unknown)))) (else ((pattern-simplifier ((quotient x '0) '((lambda () (error "program divides by zero")))) ((quotient x '1) x) ((quotient '0 x) '0) ((quotient 'a 'b) '(quotient a b))) call)))) (define (power-of-two-literal node) (if (not (literal-node? node)) #f (let ((value (literal-value node))) (if (not (and (integer? value) (<= 1 value))) #f (do ((v value (arithmetic-shift v -1)) (i 0 (+ i 1))) ((odd? v) (if (= v 1) i #f))))))) (define-scheme-primop quotient exception type/integer simplify-quotient) (define-scheme-primop remainder exception type/integer) (define (simplify-ashl call) (simplify-args call 0) ((pattern-simplifier ((ashl '0 x) '0) ((ashl x '0) x) ((ashl 'a 'b) '(arithmetic-shift a b)) ((ashl (ashl x 'a) 'b) (ashl x '(+ a b))) ((ashl (ashr x 'a) 'b) (<= a b) ; condition (ashl (bitwise-and x '(bitwise-not (- (expt 2 a) 1))) '(- b a))) ((ashl (ashr x 'a) 'b) (>= a b) ; condition (bitwise-and (ashr x '(- a b)) '(bitwise-not (- (expt 2 b) 1)))) ((ashl (+ 'a x) 'b) (+ (ashl x 'b) '(arithmetic-shift a b)))) call)) (define (simplify-ashr call) (simplify-args call 0) ((pattern-simplifier ((ashr '0 x) '0) ((ashr x '0) x) ((ashr 'a 'b) '(arithmetic-shift a (- b))) ((ashr (ashr x 'a) 'b) (ashr x '(+ a b)))) call)) (define (simplify-lshr call) (simplify-args call 0) ((pattern-simplifier ((lshr '0 x) '0) ((lshr x '0) x) ((lshr 'a 'b) '(lshr a (- b))) ((lshr (lshr x 'a) 'b) (lshr x '(+ a b))) ((ashr (lshr x 'a) 'b) (lshr x '(+ a b)))) ; depends on shifts by zero ; having been constant folded call)) (define-scheme-primop ashl #f type/integer simplify-ashl) (define-scheme-primop ashr #f type/integer simplify-ashr) (define-scheme-primop lshr #f type/integer simplify-lshr) (define (simplify-bitwise-and call) (simplify-args call 0) (put-literal-first call) ((pattern-simplifier ((bitwise-and '0 x) '0) ((bitwise-and '-1 x) x) ((bitwise-and 'a 'b) '(bitwise-and a b))) call)) (define (simplify-bitwise-ior call) (simplify-args call 0) (put-literal-first call) ((pattern-simplifier ((bitwise-ior '0 x) x) ((bitwise-ior '-1 x) '-1) ((bitwise-ior 'a 'b) '(bitwise-ior a b))) call)) (define (simplify-bitwise-xor call) (simplify-args call 0) (put-literal-first call) ((pattern-simplifier ((bitwise-xor '0 x) x) ((bitwise-xor 'a 'b) '(bitwise-xor a b))) call)) (define (simplify-bitwise-not call) (simplify-args call 0) ((pattern-simplifier ((bitwise-not 'a) '(bitwise-not a))) call)) (define-scheme-primop bitwise-and #f type/integer simplify-bitwise-and) (define-scheme-primop bitwise-ior #f type/integer simplify-bitwise-ior) (define-scheme-primop bitwise-xor #f type/integer simplify-bitwise-xor) (define-scheme-primop bitwise-not #f type/integer simplify-bitwise-not) (define (simplify-= call) (simplify-args call 0) (put-literal-first call) ((pattern-simplifier ((= 'a 'b) '(= a b)) ((= 'a (+ 'b c)) (= '(- a b) c)) ; will these ever be used? ((= 'a (- 'b c)) (= '(- b a) c))) call)) (define (simplify-< call) (simplify-args call 0) ((pattern-simplifier ((< 'a 'b) '(< a b)) ((< 'a (+ 'b c)) (< '(- a b) c)) ; will these ever be used? ((< (+ 'b c) 'a) (< c '(- a b))) ((< 'a (- 'b c)) (< c '(- b a))) ((< (- 'b c) 'a) (< '(- b a) c))) call)) (define (simplify-char=? call) (simplify-args call 0) (put-literal-first call) ((pattern-simplifier ((char=? 'a 'b) '(char=? a b)) ((char=? 'a (+ 'b c)) (char=? '(- a b) c)) ((char=? 'a (- 'b c)) (char=? '(- b a) c))) call)) (define (simplify-charascii call) (simplify-args call 0) (let ((arg (call-arg call 0))) (if (literal-node? arg) (let ((value (literal-value arg))) (if (char? value) (replace call (make-literal-node (char->ascii value) #f)) (breakpoint "char->ascii is applied to a non-character literal ~S" value)))))) (define (simplify-ascii->char call) (simplify-args call 0) (let ((arg (call-arg call 0))) (if (literal-node? arg) (let ((value (literal-value arg))) (if (integer? value) (replace call (make-literal-node (ascii->char value) #f)) (breakpoint "ascii->char is applied to a non-integer literal ~S" value)))))) (define-scheme-primop char->ascii #f type/integer simplify-char->ascii) (define-scheme-primop ascii->char #f type/integer simplify-ascii->char) ;(define (simplify-sign-extend call) ; (simplify-args call 0) ; (let ((value (call-arg call 0))) ; (cond ((literal-node? value) ; (set-literal-type! value type/integer) ; (replace call (detach value)))))) ; ;(define-scheme-primop sign-extend #f type/integer simplify-sign-extend) ;(define-scheme-primop zero-extend #f type/integer simplify-sign-extend)