specialize-primcalls.scm 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. ;;; Continuation-passing style (CPS) intermediate language (IL)
  2. ;; Copyright (C) 2013, 2014, 2015 Free Software Foundation, Inc.
  3. ;;;; This library is free software; you can redistribute it and/or
  4. ;;;; modify it under the terms of the GNU Lesser General Public
  5. ;;;; License as published by the Free Software Foundation; either
  6. ;;;; version 3 of the License, or (at your option) any later version.
  7. ;;;;
  8. ;;;; This library is distributed in the hope that it will be useful,
  9. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. ;;;; Lesser General Public License for more details.
  12. ;;;;
  13. ;;;; You should have received a copy of the GNU Lesser General Public
  14. ;;;; License along with this library; if not, write to the Free Software
  15. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. ;;; Commentary:
  17. ;;;
  18. ;;; Some bytecode operations can encode an immediate as an operand.
  19. ;;; This pass tranforms generic primcalls to these specialized
  20. ;;; primcalls, if possible.
  21. ;;;
  22. ;;; Code:
  23. (define-module (language cps specialize-primcalls)
  24. #:use-module (ice-9 match)
  25. #:use-module (language cps)
  26. #:use-module (language cps utils)
  27. #:use-module (language cps intmap)
  28. #:export (specialize-primcalls))
  29. (define (specialize-primcalls conts)
  30. (let ((constants (compute-constant-values conts)))
  31. (define (u6? var)
  32. (let ((val (intmap-ref constants var (lambda (_) #f))))
  33. (and (exact-integer? val) (<= 0 val 63))))
  34. (define (u8? var)
  35. (let ((val (intmap-ref constants var (lambda (_) #f))))
  36. (and (exact-integer? val) (<= 0 val 255))))
  37. (define (u64? var)
  38. (let ((val (intmap-ref constants var (lambda (_) #f))))
  39. (and (exact-integer? val) (<= 0 val #xffffFFFFffffFFFF))))
  40. (define (s64? var)
  41. (let ((val (intmap-ref constants var (lambda (_) #f))))
  42. (and (exact-integer? val)
  43. (<= (- #x8000000000000000) val #x7fffFFFFffffFFFF))))
  44. (define (f64? var)
  45. (let ((val (intmap-ref constants var (lambda (_) #f))))
  46. (and (number? val) (inexact? val) (real? val))))
  47. (define (specialize-primcall name args)
  48. (define (rename name)
  49. (build-exp ($primcall name args)))
  50. (match (cons name args)
  51. (('make-vector (? u8? n) init) (rename 'make-vector/immediate))
  52. (('vector-ref v (? u8? n)) (rename 'vector-ref/immediate))
  53. (('vector-set! v (? u8? n) x) (rename 'vector-set!/immediate))
  54. (('allocate-struct v (? u8? n)) (rename 'allocate-struct/immediate))
  55. (('struct-ref s (? u8? n)) (rename 'struct-ref/immediate))
  56. (('struct-set! s (? u8? n) x) (rename 'struct-set!/immediate))
  57. (('add x (? u8? y)) (build-exp ($primcall 'add/immediate (x y))))
  58. (('add (? u8? x) y) (build-exp ($primcall 'add/immediate (y x))))
  59. (('sub x (? u8? y)) (build-exp ($primcall 'sub/immediate (x y))))
  60. (('uadd x (? u8? y)) (build-exp ($primcall 'uadd/immediate (x y))))
  61. (('uadd (? u8? x) y) (build-exp ($primcall 'uadd/immediate (y x))))
  62. (('usub x (? u8? y)) (build-exp ($primcall 'usub/immediate (x y))))
  63. (('umul x (? u8? y)) (build-exp ($primcall 'umul/immediate (x y))))
  64. (('umul (? u8? x) y) (build-exp ($primcall 'umul/immediate (y x))))
  65. (('ursh x (? u6? y)) (build-exp ($primcall 'ursh/immediate (x y))))
  66. (('ulsh x (? u6? y)) (build-exp ($primcall 'ulsh/immediate (x y))))
  67. (('scm->f64 (? f64?)) (rename 'load-f64))
  68. (('scm->u64 (? u64?)) (rename 'load-u64))
  69. (('scm->u64/truncate (? u64?)) (rename 'load-u64))
  70. (('scm->s64 (? s64?)) (rename 'load-s64))
  71. (_ #f)))
  72. (intmap-map
  73. (lambda (label cont)
  74. (match cont
  75. (($ $kargs names vars ($ $continue k src ($ $primcall name args)))
  76. (let ((exp* (specialize-primcall name args)))
  77. (if exp*
  78. (build-cont
  79. ($kargs names vars ($continue k src ,exp*)))
  80. cont)))
  81. (_ cont)))
  82. conts)))