[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 03/30: Better support for unboxed signed arithmetic
From: |
Andy Wingo |
Subject: |
[Guile-commits] 03/30: Better support for unboxed signed arithmetic |
Date: |
Fri, 24 Nov 2017 09:24:19 -0500 (EST) |
wingo pushed a commit to branch master
in repository guile.
commit 5fbd4b8f9ea6af69085c4a6ffe784845b10b6315
Author: Andy Wingo <address@hidden>
Date: Mon Nov 20 15:18:02 2017 +0100
Better support for unboxed signed arithmetic
* module/language/cps/primitives.scm (*macro-instruction-arities*):
Declare new u64->s64, s64->u64, sadd, ssub, smul, sadd/immediate,
ssub/immediate, smul/immediate, slsh, and slsh/immediate primcalls
that don't have corresponding VM instructions.
* module/language/cps/effects-analysis.scm: The new instructions are
effect-free.
* module/language/cps/reify-primitives.scm (wrap-unary, wrap-binary):
(wrap-binary/exp, reify-primitives): Add horrible code that turns
e.g. sadd into a series of s64->u64, uadd, and then u64->s64. This
way we keep our ability to do range inference on unboxed signed
arithmetic, but we still bottom out to the same instructions for both
unboxed signed and unboxed unsigned arithmetic.
* module/language/cps/types.scm: Add type inferrers for new
instructions. Remove type checkers for some effect-free primitives.
* module/language/cps/compile-bytecode.scm (compile-function): Add
pseudo-emitter for u64->s64 and s64->u64 no-ops.
---
module/language/cps/compile-bytecode.scm | 2 +
module/language/cps/effects-analysis.scm | 10 ++++
module/language/cps/primitives.scm | 12 ++++-
module/language/cps/reify-primitives.scm | 86 +++++++++++++++++++++++++++++++-
module/language/cps/slot-allocation.scm | 4 +-
module/language/cps/types.scm | 62 +++++++++++++++++++++--
6 files changed, 168 insertions(+), 8 deletions(-)
diff --git a/module/language/cps/compile-bytecode.scm
b/module/language/cps/compile-bytecode.scm
index 6391a67..dfd8129 100644
--- a/module/language/cps/compile-bytecode.scm
+++ b/module/language/cps/compile-bytecode.scm
@@ -133,6 +133,8 @@
(match exp
(($ $values (arg))
(maybe-mov dst (slot arg)))
+ (($ $primcall (or 's64->u64 'u64->s64) #f (arg))
+ (maybe-mov dst (slot arg)))
(($ $const exp)
(emit-load-constant asm (from-sp dst) exp))
(($ $primcall 'load-const/unlikely exp ())
diff --git a/module/language/cps/effects-analysis.scm
b/module/language/cps/effects-analysis.scm
index 5ef22c2..52f0d5b 100644
--- a/module/language/cps/effects-analysis.scm
+++ b/module/language/cps/effects-analysis.scm
@@ -375,6 +375,8 @@ is or might be a read or a write to the same location as A."
((load-s64))
((s64->scm _))
((s64->scm/unlikely _))
+ ((u64->s64 _))
+ ((s64->u64 _))
((untag-fixnum _))
((tag-fixnum _))
((tag-fixnum/unlikely _)))
@@ -453,6 +455,12 @@ is or might be a read or a write to the same location as
A."
((uadd/immediate . _))
((usub/immediate . _))
((umul/immediate . _))
+ ((sadd . _))
+ ((ssub . _))
+ ((smul . _))
+ ((sadd/immediate . _))
+ ((ssub/immediate . _))
+ ((smul/immediate . _))
((quo . _) &type-check)
((rem . _) &type-check)
((mod . _) &type-check)
@@ -482,9 +490,11 @@ is or might be a read or a write to the same location as
A."
((ursh . _))
((srsh . _))
((ulsh . _))
+ ((slsh . _))
((ursh/immediate . _))
((srsh/immediate . _))
((ulsh/immediate . _))
+ ((slsh/immediate . _))
((logtest a b) &type-check)
((logbit? a b) &type-check)
((sqrt _) &type-check)
diff --git a/module/language/cps/primitives.scm
b/module/language/cps/primitives.scm
index c9688d1..5e102d8 100644
--- a/module/language/cps/primitives.scm
+++ b/module/language/cps/primitives.scm
@@ -66,7 +66,17 @@
(bytevector-ieee-double-native-set! . bv-f64-set!)))
(define *macro-instruction-arities*
- '((u64->scm/unlikely . (1 . 1))
+ '((u64->s64 . (1 . 1))
+ (s64->u64 . (1 . 1))
+ (sadd . (2 . 1))
+ (ssub . (2 . 1))
+ (smul . (2 . 1))
+ (sadd/immediate . (1 . 1))
+ (ssub/immediate . (1 . 1))
+ (smul/immediate . (1 . 1))
+ (slsh . (2 . 1))
+ (slsh/immediate . (1 . 1))
+ (u64->scm/unlikely . (1 . 1))
(s64->scm/unlikely . (1 . 1))
(tag-fixnum/unlikely . (1 . 1))
(load-const/unlikely . (0 . 1))
diff --git a/module/language/cps/reify-primitives.scm
b/module/language/cps/reify-primitives.scm
index bac85ad..71e1ba9 100644
--- a/module/language/cps/reify-primitives.scm
+++ b/module/language/cps/reify-primitives.scm
@@ -121,6 +121,50 @@
(_
(with-cps cps k))))
+(define (wrap-unary cps k src wrap unwrap op param a)
+ (with-cps cps
+ (letv a* res*)
+ (letk kres ($kargs ('res*) (res*)
+ ($continue k src
+ ($primcall 'u64->s64 #f (res*)))))
+ (letk ka ($kargs ('a*) (a*)
+ ($continue kres src
+ ($primcall op param (a*)))))
+ (build-term
+ ($continue ka src
+ ($primcall 's64->u64 #f (a))))))
+
+(define (wrap-binary cps k src wrap unwrap op param a b)
+ (with-cps cps
+ (letv a* b* res*)
+ (letk kres ($kargs ('res*) (res*)
+ ($continue k src
+ ($primcall 'u64->s64 #f (res*)))))
+ (letk kb ($kargs ('b*) (b*)
+ ($continue kres src
+ ($primcall op param (a* b*)))))
+ (letk ka ($kargs ('a*) (a*)
+ ($continue kb src
+ ($primcall 's64->u64 #f (b)))))
+ (build-term
+ ($continue ka src
+ ($primcall 's64->u64 #f (a))))))
+
+(define (wrap-binary/exp cps k src wrap unwrap op param a b-exp)
+ (with-cps cps
+ (letv a* b* res*)
+ (letk kres ($kargs ('res*) (res*)
+ ($continue k src
+ ($primcall 'u64->s64 #f (res*)))))
+ (letk kb ($kargs ('b*) (b*)
+ ($continue kres src
+ ($primcall op param (a* b*)))))
+ (letk ka ($kargs ('a*) (a*)
+ ($continue kb src ,b-exp)))
+ (build-term
+ ($continue ka src
+ ($primcall 's64->u64 #f (a))))))
+
(define (reify-primitives cps)
(define (visit-cont label cont cps)
(define (resolve-prim cps name k src)
@@ -203,7 +247,47 @@
;; ((ursh/immediate (u6? y) x) (ursh x y))
;; ((srsh/immediate (u6? y) x) (srsh x y))
;; ((ulsh/immediate (u6? y) x) (ulsh x y))
- (_ cps))))))
+ (_
+ (match (cons name args)
+ (((or 'sadd 'ssub 'smul) a b)
+ (let ((op (match name
+ ('sadd 'uadd) ('ssub 'usub) ('smul 'umul))))
+ (with-cps cps
+ (let$ body
+ (wrap-binary k src 's64->u64 'u64->s64 op #f a b))
+ (setk label ($kargs names vars ,body)))))
+ (((or 'sadd/immediate 'ssub/immediate 'smul/immediate) a)
+ (if (u8? param)
+ (let ((op (match name
+ ('sadd/immediate 'uadd/immediate)
+ ('ssub/immediate 'usub/immediate)
+ ('smul/immediate 'umul/immediate))))
+ (with-cps cps
+ (let$ body (wrap-unary k src 's64->u64 'u64->s64 op
param a))
+ (setk label ($kargs names vars ,body))))
+ (let* ((op (match name
+ ('sadd/immediate 'uadd)
+ ('ssub/immediate 'usub)
+ ('smul/immediate 'umul)))
+ (param (logand param (1- (ash 1 64))))
+ (exp (build-exp ($primcall 'load-u64 param ()))))
+ (with-cps cps
+ (let$ body (wrap-binary/exp k src 's64->u64 'u64-s64
+ op #f a exp))
+ (setk label ($kargs names vars ,body))))))
+ (('slsh a b)
+ (let ((op 'ulsh)
+ (exp (build-exp ($values (b)))))
+ (with-cps cps
+ (let$ body (wrap-binary/exp k src 's64->u64 'u64-s64
+ op #f a exp))
+ (setk label ($kargs names vars ,body)))))
+ (('slsh/immediate a)
+ (let ((op 'ulsh/immediate))
+ (with-cps cps
+ (let$ body (wrap-unary k src 's64->u64 'u64->s64 op
param a))
+ (setk label ($kargs names vars ,body)))))
+ (_ cps))))))))
(param (error "unexpected param to reified primcall" name))
(else
(with-cps cps
diff --git a/module/language/cps/slot-allocation.scm
b/module/language/cps/slot-allocation.scm
index 17471c6..992639f 100644
--- a/module/language/cps/slot-allocation.scm
+++ b/module/language/cps/slot-allocation.scm
@@ -768,7 +768,7 @@ are comparable with eqv?. A tmp slot may be used."
'fadd 'fsub 'fmul 'fdiv))
(intmap-add representations var 'f64))
(($ $primcall (or 'scm->u64 'scm->u64/truncate 'load-u64
- 'char->integer
+ 'char->integer 's64->u64
'bv-length 'vector-length 'string-length
'uadd 'usub 'umul
'ulogand 'ulogior 'ulogxor 'ulogsub 'ursh 'ulsh
@@ -777,7 +777,7 @@ are comparable with eqv?. A tmp slot may be used."
'bv-u8-ref 'bv-u16-ref 'bv-u32-ref 'bv-u64-ref))
(intmap-add representations var 'u64 meet-s64-u64))
(($ $primcall (or 'untag-fixnum
- 'scm->s64 'load-s64
+ 'scm->s64 'load-s64 'u64->s64
'srsh 'srsh/immediate
'bv-s8-ref 'bv-s16-ref 'bv-s32-ref 'bv-s64-ref))
(intmap-add representations var 's64 meet-s64-u64))
diff --git a/module/language/cps/types.scm b/module/language/cps/types.scm
index 3edd9ef..8ff7556 100644
--- a/module/language/cps/types.scm
+++ b/module/language/cps/types.scm
@@ -676,6 +676,16 @@ minimum, and maximum."
(define! result (type-entry-type ent)
(type-entry-min ent) (type-entry-max ent))))
+(define-type-inferrer (u64->s64 u64 s64)
+ (if (<= (&max u64) &s64-max)
+ (define! s64 &s64 (&min u64) (&max u64))
+ (define! s64 &s64 &s64-min &s64-max)))
+
+(define-type-inferrer (s64->u64 s64 u64)
+ (if (<= 0 (&min s64))
+ (define! u64 &u64 (&min s64) (&max s64))
+ (define! u64 &u64 0 &u64-max)))
+
;;;
@@ -1094,8 +1104,6 @@ minimum, and maximum."
(define-simple-type-checker (add &number &number))
(define-simple-type-checker (add/immediate &number))
-(define-type-checker (fadd a b) #t)
-(define-type-checker (uadd a b) #t)
(define-type-inferrer (add a b result)
(define-binary-result! (&type a) (&type b) result #t
(+ (&min a) (&min b))
@@ -1115,12 +1123,26 @@ minimum, and maximum."
(if (<= max &u64-max)
(define! result &u64 (+ (&min/0 a) (&min/0 b)) max)
(define! result &u64 0 &u64-max))))
+(define-type-inferrer (sadd a b result)
+ ;; Handle wraparound.
+ (let ((min (+ (&min/s64 a) (&min/s64 b)))
+ (max (+ (&max/s64 a) (&max/s64 b))))
+ (if (<= &s64-min min max &s64-max)
+ (define! result &s64 min max)
+ (define! result &s64 &s64-min &s64-max))))
(define-type-inferrer/param (uadd/immediate param a result)
;; Handle wraparound.
(let ((max (+ (&max/u64 a) param)))
(if (<= max &u64-max)
(define! result &u64 (+ (&min/0 a) param) max)
(define! result &u64 0 &u64-max))))
+(define-type-inferrer/param (sadd/immediate param a result)
+ ;; Handle wraparound.
+ (let ((min (+ (&min/s64 a) param))
+ (max (+ (&max/s64 a) param)))
+ (if (<= &s64-min min max &s64-max)
+ (define! result &s64 min max)
+ (define! result &s64 &s64-min &s64-max))))
(define-simple-type-checker (sub &number &number))
(define-simple-type-checker (sub/immediate &number))
@@ -1153,8 +1175,6 @@ minimum, and maximum."
(define! result &u64 min (- (&max/u64 a) param)))))
(define-simple-type-checker (mul &number &number))
-(define-type-checker (fmul a b) #t)
-(define-type-checker (umul a b) #t)
(define (mul-result-range same? nan-impossible? min-a max-a min-b max-b)
(define (nan* a b)
(if (and (or (and (inf? a) (zero? b))
@@ -1203,12 +1223,32 @@ minimum, and maximum."
(if (<= max &u64-max)
(define! result &u64 (* (&min/0 a) (&min/0 b)) max)
(define! result &u64 0 &u64-max))))
+(define-type-inferrer (smul a b result)
+ (call-with-values (lambda ()
+ (mul-result-range (eqv? a b) #t
+ (&min/s64 a) (&max/s64 a)
+ (&min/s64 b) (&max/s64 b)))
+ (lambda (min max)
+ ;; Handle wraparound.
+ (if (<= &s64-min min max &s64-max)
+ (define! result &s64 min max)
+ (define! result &s64 &s64-min &s64-max)))))
(define-type-inferrer/param (umul/immediate param a result)
;; Handle wraparound.
(let ((max (* (&max/u64 a) param)))
(if (<= max &u64-max)
(define! result &u64 (* (&min/0 a) param) max)
(define! result &u64 0 &u64-max))))
+(define-type-inferrer/param (smul/immediate param a result)
+ (call-with-values (lambda ()
+ (mul-result-range #f #t
+ (&min/s64 a) (&max/s64 a)
+ param param))
+ (lambda (min max)
+ ;; Handle wraparound.
+ (if (<= &s64-min min max &s64-max)
+ (define! result &s64 min max)
+ (define! result &s64 &s64-min &s64-max)))))
(define-type-checker (div a b)
(and (check-type a &number -inf.0 +inf.0)
@@ -1422,6 +1462,20 @@ minimum, and maximum."
;; Otherwise assume the whole range.
(define! result &u64 0 &u64-max)))
+(define-type-inferrer (slsh a b result)
+ (let-values (((min max) (compute-ash-range (&min a) (&max a)
+ (min 63 (&min/0 b))
+ (min 63 (&max/u64 b)))))
+ (if (<= &s64-min min max &s64-max)
+ (define! result &s64 min max)
+ (define! result &s64 &s64-min &s64-max))))
+(define-type-inferrer (slsh/immediate param a result)
+ (let-values (((min max) (compute-ash-range (&min a) (&max a)
+ param param)))
+ (if (<= &s64-min min max &s64-max)
+ (define! result &s64 min max)
+ (define! result &s64 &s64-min &s64-max))))
+
(define (next-power-of-two n)
(let lp ((out 1))
(if (< n out)
- [Guile-commits] 02/30: Revert specialization of fixnum phi variables, (continued)
- [Guile-commits] 02/30: Revert specialization of fixnum phi variables, Andy Wingo, 2017/11/24
- [Guile-commits] 09/30: Fix logand type inference, Andy Wingo, 2017/11/24
- [Guile-commits] 08/30: Revert "Slot allocation allows s64/u64 representations of same var", Andy Wingo, 2017/11/24
- [Guile-commits] 07/30: Fix u64/s64 typesafety around fixnum (un)tagging, Andy Wingo, 2017/11/24
- [Guile-commits] 14/30: Fix type check elision for branches, Andy Wingo, 2017/11/24
- [Guile-commits] 06/30: Separate u64 and s64 type inferrers now that ops are monomorphic, Andy Wingo, 2017/11/24
- [Guile-commits] 18/30: Remove thunk?, integer? simple predicate inferrers, Andy Wingo, 2017/11/24
- [Guile-commits] 17/30: Add support for bignum? CPS primitive., Andy Wingo, 2017/11/24
- [Guile-commits] 22/30: Fix inference of generic < on NaN values, Andy Wingo, 2017/11/24
- [Guile-commits] 20/30: Add &exact-number helper definition, Andy Wingo, 2017/11/24
- [Guile-commits] 03/30: Better support for unboxed signed arithmetic,
Andy Wingo <=
- [Guile-commits] 30/30: Optimize check-urange in assembler.scm, Andy Wingo, 2017/11/24
- [Guile-commits] 27/30: Add integer devirtualization pass., Andy Wingo, 2017/11/24
- [Guile-commits] 12/30: Remove effects-analysis exports that were undefined, Andy Wingo, 2017/11/24
- [Guile-commits] 11/30: Specialize fixnum and s64 phis, Andy Wingo, 2017/11/24
- [Guile-commits] 19/30: Add exact-integer? as interesting Tree-IL effect-free primitive, Andy Wingo, 2017/11/24
- [Guile-commits] 24/30: Declare bignum? as effect-free, Andy Wingo, 2017/11/24
- [Guile-commits] 13/30: Minor compile-cps refactor, Andy Wingo, 2017/11/24
- [Guile-commits] 15/30: DCE eliminates effect-free branches to the same continuation, Andy Wingo, 2017/11/24
- [Guile-commits] 29/30: DCE of branches punches through dead terms, Andy Wingo, 2017/11/24
- [Guile-commits] 21/30: Improve type and range inference on bignums, Andy Wingo, 2017/11/24