arith.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
  2. ;;;
  3. ;;; Port Author: Andrew Whatson
  4. ;;;
  5. ;;; Original Authors: Richard Kelsey, Mike Sperber
  6. ;;;
  7. ;;; scheme48-1.9.2/ps-compiler/prescheme/primop/arith.scm
  8. (define-module (ps-compiler prescheme primop arith)
  9. #:use-module (prescheme scheme48)
  10. #:use-module (ps-compiler node let-nodes)
  11. #:use-module (ps-compiler node node)
  12. #:use-module (ps-compiler node node-util)
  13. #:use-module (ps-compiler node primop)
  14. #:use-module (ps-compiler prescheme primop primop)
  15. #:use-module (ps-compiler prescheme type)
  16. #:use-module (ps-compiler simp pattern)
  17. #:use-module (ps-compiler simp simplify))
  18. (define (put-literal-first call)
  19. (if (and (not (literal-node? (call-arg call 0)))
  20. (literal-node? (call-arg call 1)))
  21. (let ((arg1 (detach (call-arg call 0)))
  22. (arg0 (detach (call-arg call 1))))
  23. (attach call 0 arg0)
  24. (attach call 1 arg1))))
  25. (define-syntax addition-simplifier
  26. (syntax-rules ()
  27. ((addition-simplifier + - zero)
  28. (lambda (call)
  29. (simplify-args call 0)
  30. (put-literal-first call)
  31. ((pattern-simplifier
  32. ((+ 'zero x) x)
  33. ((+ 'a 'b) '(+ a b))
  34. ((+ 'a (+ 'b x)) (+ x '(+ a b)))
  35. ((+ 'a (- x 'b)) (+ x '(- a b))) ;; no overflow in Scheme, but what
  36. ((+ 'a (- 'b x)) (- '(+ a b) x)) ;; about PreScheme? Could check the
  37. ((+ (+ 'a x) (+ 'b y)) (+ '(+ a b) (+ x y)))
  38. ((+ x (+ 'a y)) (+ 'a (+ x y)))) ;; result of the literal. Maybe these
  39. call))))) ;; should be left out.
  40. (define-scheme-primop + #f type/integer (addition-simplifier + - 0))
  41. (define-scheme-primop fl+ #f type/float (addition-simplifier fl+ fl- 0.0))
  42. (define-scheme-primop un+ #f type/unsigned-integer (addition-simplifier un+ un- 0))
  43. ;; The simplifiers think that the constant folders have the same name as
  44. ;; the primops. It is easier to define these than to change the simplifiers.
  45. (define fl+ +)
  46. (define fl- -)
  47. (define fl* *)
  48. (define un+ +)
  49. (define un- -)
  50. (define un* *)
  51. (define-syntax subtraction-simplifier
  52. (syntax-rules ()
  53. ((subtraction-simplifier + - zero)
  54. (lambda (call)
  55. (simplify-args call 0)
  56. ((pattern-simplifier
  57. ((- 'a 'b) '(- a b))
  58. ((- x 'a) (+ '(- zero a) x))
  59. ((- 'a (+ 'b x)) (- '(- a b) x)) ;; more overflow problems
  60. ((- 'a (- 'b x)) (+ x '(- a b)))
  61. ((- x (+ 'a y)) (+ '(- zero a) (- x y)))
  62. ;; ((- (+ 'a x) y) (+ 'a (- x y))) need to come up with a normal form
  63. ((- (+ 'a x) (+ 'b y)) (- (+ '(- a b) x) y)))
  64. call)))))
  65. (define-scheme-primop - #f type/integer (subtraction-simplifier + - 0))
  66. (define-scheme-primop un- #f type/unsigned-integer (subtraction-simplifier un+ un- 0))
  67. (define-scheme-primop fl- #f type/float (subtraction-simplifier fl+ fl- 0.0))
  68. ;; This should check for multiply by powers of 2 (other constants can be
  69. ;; done later).
  70. (define (simplify-multiply call)
  71. (simplify-args call 0)
  72. (put-literal-first call)
  73. (cond ((power-of-two-literal (call-arg call 0))
  74. => (lambda (i)
  75. (set-call-primop! call (get-prescheme-primop 'ashl))
  76. (replace (call-arg call 0) (detach (call-arg call 1)))
  77. (attach call 1 (make-literal-node i type/unknown))))
  78. (else
  79. ((pattern-simplifier
  80. ((* '0 x) '0)
  81. ((* '1 x) x)
  82. ((* 'a 'b) '(* a b))
  83. ((* 'a (* x 'b)) (* x '(* a b)))
  84. ((* 'a (* 'b x)) (* x '(* a b))))
  85. call))))
  86. (define (power-of-two-literal node)
  87. (if (not (literal-node? node))
  88. #f
  89. (let ((value (literal-value node)))
  90. (if (not (and (integer? value)
  91. (<= 1 value)))
  92. #f
  93. (do ((v value (arithmetic-shift v -1))
  94. (i 0 (+ i 1)))
  95. ((odd? v)
  96. (if (= v 1) i #f)))))))
  97. (define simplify-float-multiply
  98. (pattern-simplifier
  99. ((fl* '0.0 x) '0.0)
  100. ((fl* '1.0 x) x)
  101. ((fl* 'a 'b) '(fl* a b))
  102. ((fl* 'a (fl* x 'b)) (fl* x '(fl* a b)))
  103. ((fl* 'a (fl* 'b x)) (fl* x '(fl* a b)))))
  104. (define-scheme-primop * #f type/integer simplify-multiply)
  105. (define-scheme-primop un* #f type/unsigned-integer simplify-multiply)
  106. (define-scheme-primop small* #f type/integer simplify-multiply)
  107. (define-scheme-primop fl* #f type/float simplify-float-multiply)
  108. (define-syntax quotient-simplifier
  109. (syntax-rules ()
  110. ((quotient-simplifier id zero one op)
  111. (lambda (call)
  112. (simplify-args call 0)
  113. ((pattern-simplifier
  114. ((id x 'zero) '((lambda ()
  115. (error "program divides by zero"))))
  116. ((id x 'one) x)
  117. ((id 'zero x) 'zero)
  118. ((id 'a 'b) '(op a b)))
  119. call)))))
  120. (define-scheme-primop quotient exception type/integer
  121. (quotient-simplifier quotient 0 1 quotient))
  122. (define-scheme-primop unquotient exception type/unsigned-integer
  123. (quotient-simplifier unquotient 0 1 quotient))
  124. (define-scheme-primop fl/ exception type/float
  125. (quotient-simplifier fl/ 0.0 1.0 /))
  126. (define-scheme-primop remainder exception type/integer)
  127. (define-scheme-primop unremainder exception type/unsigned-integer)
  128. (define (simplify-ashl call)
  129. (simplify-args call 0)
  130. ((pattern-simplifier
  131. ((ashl '0 x) '0)
  132. ((ashl x '0) x)
  133. ((ashl 'a 'b) '(arithmetic-shift a b))
  134. ((ashl (ashl x 'a) 'b) (ashl x '(+ a b)))
  135. ((ashl (ashr x 'a) 'b)
  136. (<= a b) ;; condition
  137. (ashl (bitwise-and x '(bitwise-not (- (expt 2 a) 1))) '(- b a)))
  138. ((ashl (ashr x 'a) 'b)
  139. (>= a b) ;; condition
  140. (bitwise-and (ashr x '(- a b)) '(bitwise-not (- (expt 2 b) 1))))
  141. ((ashl (+ 'a x) 'b) (+ (ashl x 'b) '(arithmetic-shift a b))))
  142. call))
  143. (define (simplify-ashr call)
  144. (simplify-args call 0)
  145. ((pattern-simplifier
  146. ((ashr '0 x) '0)
  147. ((ashr x '0) x)
  148. ((ashr 'a 'b) '(arithmetic-shift a (- b)))
  149. ((ashr (ashr x 'a) 'b) (ashr x '(+ a b))))
  150. call))
  151. (define (simplify-lshr call)
  152. (simplify-args call 0)
  153. ((pattern-simplifier
  154. ((lshr '0 x) '0)
  155. ((lshr x '0) x)
  156. ((lshr 'a 'b) '(lshr a (- b)))
  157. ((lshr (lshr x 'a) 'b) (lshr x '(+ a b)))
  158. ((ashr (lshr x 'a) 'b) (lshr x '(+ a b)))) ;; depends on shifts by zero
  159. ;; having been constant folded
  160. call))
  161. (define-scheme-primop ashl #f type/integer simplify-ashl)
  162. (define-scheme-primop ashr #f type/integer simplify-ashr)
  163. (define-scheme-primop lshr #f type/integer simplify-lshr)
  164. (define (simplify-bitwise-and call)
  165. (simplify-args call 0)
  166. (put-literal-first call)
  167. ((pattern-simplifier
  168. ((bitwise-and '0 x) '0)
  169. ((bitwise-and '-1 x) x)
  170. ((bitwise-and 'a 'b) '(bitwise-and a b)))
  171. call))
  172. (define (simplify-bitwise-ior call)
  173. (simplify-args call 0)
  174. (put-literal-first call)
  175. ((pattern-simplifier
  176. ((bitwise-ior '0 x) x)
  177. ((bitwise-ior '-1 x) '-1)
  178. ((bitwise-ior 'a 'b) '(bitwise-ior a b)))
  179. call))
  180. (define (simplify-bitwise-xor call)
  181. (simplify-args call 0)
  182. (put-literal-first call)
  183. ((pattern-simplifier
  184. ((bitwise-xor '0 x) x)
  185. ((bitwise-xor 'a 'b) '(bitwise-xor a b)))
  186. call))
  187. (define (simplify-bitwise-not call)
  188. (simplify-args call 0)
  189. ((pattern-simplifier
  190. ((bitwise-not 'a) '(bitwise-not a)))
  191. call))
  192. (define-scheme-primop bitwise-and #f type/integer simplify-bitwise-and)
  193. (define-scheme-primop bitwise-ior #f type/integer simplify-bitwise-ior)
  194. (define-scheme-primop bitwise-xor #f type/integer simplify-bitwise-xor)
  195. (define-scheme-primop bitwise-not #f type/integer simplify-bitwise-not)
  196. (define-syntax simplify-=
  197. (syntax-rules ()
  198. ((simplify-= = op + -)
  199. (lambda (call)
  200. (simplify-args call 0)
  201. (put-literal-first call)
  202. ((pattern-simplifier
  203. ((= 'a 'b) '(op a b))
  204. ((= 'a (+ 'b c)) (= '(- a b) c)) ;; will these ever be used?
  205. ((= 'a (- 'b c)) (= '(- b a) c)))
  206. call)))))
  207. (define-syntax simplify-<
  208. (syntax-rules ()
  209. ((simplify-< < op + -)
  210. (lambda (call)
  211. (simplify-args call 0)
  212. ((pattern-simplifier
  213. ((< 'a 'b) '(op a b))
  214. ((< 'a (+ 'b c)) (< '(- a b) c)) ;; will these ever be used?
  215. ((< (+ 'b c) 'a) (< c '(- a b)))
  216. ((< 'a (- 'b c)) (< c '(- b a)))
  217. ((< (- 'b c) 'a) (< '(- b a) c)))
  218. call)))))
  219. (define (simplify-char=? call)
  220. (simplify-args call 0)
  221. (put-literal-first call)
  222. ((pattern-simplifier
  223. ((char=? 'a 'b) '(char=? a b))
  224. ((char=? 'a (+ 'b c)) (char=? '(- a b) c))
  225. ((char=? 'a (- 'b c)) (char=? '(- b a) c)))
  226. call))
  227. (define (simplify-char<? call)
  228. (simplify-args call 0)
  229. ((pattern-simplifier
  230. ((char<? 'a 'b) '(char<? a b))
  231. ((char<? 'a (+ 'b c)) (char<? '(- a b) c))
  232. ((char<? (+ 'b c) 'a) (char<? c '(- a b)))
  233. ((char<? 'a (- 'b c)) (char<? c '(- b a)))
  234. ((char<? (- 'b c) 'a) (char<? '(- b a) c)))
  235. call))
  236. (define bool-type
  237. (lambda (call)
  238. type/boolean))
  239. (define-scheme-primop = #f bool-type (simplify-= = = + -))
  240. (define-scheme-primop fl= #f bool-type (simplify-= fl= = fl+ fl-))
  241. (define-scheme-primop un= #f bool-type (simplify-= un= = un+ un-))
  242. (define-scheme-primop < #f bool-type (simplify-< < < + -))
  243. (define-scheme-primop fl< #f bool-type (simplify-< fl< < fl+ fl-))
  244. (define-scheme-primop un< #f bool-type (simplify-< un< < un+ un-))
  245. (define-scheme-primop char=? #f bool-type simplify-char=?)
  246. (define-scheme-primop char<? #f bool-type simplify-char<?)
  247. (define (simplify-char->ascii call)
  248. (simplify-args call 0)
  249. (let ((arg (call-arg call 0)))
  250. (if (literal-node? arg)
  251. (let ((value (literal-value arg)))
  252. (if (char? value)
  253. (replace call (make-literal-node (char->ascii value) #f))
  254. (breakpoint "char->ascii is applied to a non-character literal ~S"
  255. value))))))
  256. (define (simplify-ascii->char call)
  257. (simplify-args call 0)
  258. (let ((arg (call-arg call 0)))
  259. (if (literal-node? arg)
  260. (let ((value (literal-value arg)))
  261. (if (integer? value)
  262. (replace call (make-literal-node (ascii->char value) #f))
  263. (breakpoint "ascii->char is applied to a non-integer literal ~S"
  264. value))))))
  265. (define-scheme-primop char->ascii #f type/integer simplify-char->ascii)
  266. (define-scheme-primop ascii->char #f type/integer simplify-ascii->char)
  267. (define-scheme-primop unsigned->integer type/integer)
  268. (define-scheme-primop integer->unsigned type/unsigned-integer)
  269. ;;(define (simplify-sign-extend call)
  270. ;; (simplify-args call 0)
  271. ;; (let ((value (call-arg call 0)))
  272. ;; (cond ((literal-node? value)
  273. ;; (set-literal-type! value type/integer)
  274. ;; (replace call (detach value))))))
  275. ;;
  276. ;;(define-scheme-primop sign-extend #f type/integer simplify-sign-extend)
  277. ;;(define-scheme-primop zero-extend #f type/integer simplify-sign-extend)