1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-11 22:31:12 +02:00

Fix NaN handling in <= and >=

* module/language/cps/compile-bytecode.scm (compile-function): Add
  support for emitting <= via < and jge / jnge.
* module/language/cps/effects-analysis.scm: Declare effects for <= and
  f64-<=.
* module/language/cps/primitives.scm (*comparisons*): Add <=, f64-<=.
* module/language/cps/specialize-numbers.scm (specialize-operations):
  Specialize <= to < for integer comparisons.  Specialize to f64-<= for
  f64 ops.
* module/language/cps/type-fold.scm (<=): Add folder.
* module/language/cps/types.scm (infer-<=): Add inferrer.
* module/language/tree-il/compile-cps.scm (canonicalize): Canonicalize
  <= and >= to <=, so that nans are handled correctly.
This commit is contained in:
Andy Wingo 2017-12-02 21:07:48 +01:00
parent 40dac99d42
commit 64acf24b40
7 changed files with 40 additions and 7 deletions

View file

@ -427,6 +427,8 @@
(binary op emit-je emit-jne a b))
(define (binary-< emit-<? a b)
(binary emit-<? emit-jl emit-jnl a b))
(define (binary-<= emit-<? a b)
(binary emit-<? emit-jge emit-jnge b a))
(define (binary-test/imm op a b)
(op asm (from-sp (slot a)) b)
(emit-branch emit-je emit-jne))
@ -458,6 +460,7 @@
(($ $primcall 'heap-numbers-equal? #f (a b))
(binary-test emit-heap-numbers-equal? a b))
(($ $primcall '< #f (a b)) (binary-< emit-<? a b))
(($ $primcall '<= #f (a b)) (binary-<= emit-<? a b))
(($ $primcall '= #f (a b)) (binary-test emit-=? a b))
(($ $primcall 'u64-< #f (a b)) (binary-< emit-u64<? a b))
(($ $primcall 'u64-imm-< b (a)) (binary-</imm emit-u64-imm<? a b))
@ -470,6 +473,7 @@
(($ $primcall 's64-imm-< b (a)) (binary-</imm emit-s64-imm<? a b))
(($ $primcall 'imm-s64-< b (a)) (binary-</imm emit-imm-s64<? a b))
(($ $primcall 'f64-< #f (a b)) (binary-< emit-f64<? a b))
(($ $primcall 'f64-<= #f (a b)) (binary-<= emit-f64<? a b))
(($ $primcall 'f64-= #f (a b)) (binary-test emit-f64=? a b))))
(define (compile-trunc label k exp nreq rest-var)

View file

@ -449,6 +449,7 @@ the LABELS that are clobbered by the effects of LABEL."
(define-primitive-effects
((heap-numbers-equal? . _))
((= . _) &type-check)
((<= . _) &type-check)
((< . _) &type-check)
((u64-= . _))
((u64-imm-= . _))
@ -462,6 +463,7 @@ the LABELS that are clobbered by the effects of LABEL."
((imm-s64-< . _))
((f64-= . _))
((f64-< . _))
((f64-<= . _))
((zero? . _) &type-check)
((add . _) &type-check)
((add/immediate . _) &type-check)

View file

@ -144,6 +144,7 @@ before it is lowered to CPS?"
heap-numbers-equal?
<
<=
=
u64-<
@ -152,6 +153,7 @@ before it is lowered to CPS?"
s64-<
f64-<
f64-<=
f64-=))
(define *branching-primcall-arities* (make-hash-table))

View file

@ -565,6 +565,17 @@ BITS indicating the significant bits needed for a variable. BITS may be
(define (specialize-branch cps kf kt src op param args)
(match (cons op args)
(('<= a b)
(cond
((f64-operands? a b)
(specialize-comparison cps kf kt src 'f64-<= a b
(unbox-f64 a) (unbox-f64 b)))
((and (exact-integer-operand? a) (exact-integer-operand? b))
;; If NaN is impossible, reduce (<= a b) to (not (< b a)) and
;; try again.
(specialize-branch cps kt kf src '< param (list b a)))
(else
(with-cps cps #f))))
(((or '< '=) a b)
(cond
((f64-operands? a b)

View file

@ -160,6 +160,14 @@
;;
;; (define-branch-folder-alias f64-< <)
(define-binary-branch-folder (<= type0 min0 max0 type1 min1 max1)
(if (type<=? (logior type0 type1) &exact-number)
(case (compare-exact-ranges min0 max0 min1 max1)
((< <= =) (values #t #t))
((>) (values #t #f))
(else (values #f #f)))
(values #f #f)))
(define-unary-branch-folder* (u64-imm-= c type min max)
(cond
((= c min max) (values #t #t))

View file

@ -1068,6 +1068,12 @@ minimum, and maximum."
(restrict! a &exact-number (max min0 min1) max0)
(restrict! b &exact-number min1 (min max0 max1)))))))))
(define (infer-<= types succ param a b)
;; Infer "(<= a b)" as "(not (< b a))", knowing that we only make
;; inferences when NaN is impossible.
((hashq-ref *type-inferrers* '<) types (match succ (0 1) (1 0)) param b a))
(hashq-set! *type-inferrers* '<= infer-<=)
(define-predicate-inferrer (u64-= a b true?)
(infer-= a b true?))
(define-predicate-inferrer (u64-< a b true?)

View file

@ -1140,16 +1140,16 @@ integer."
(make-const src #f)))))
(($ <primcall> src '<= (a b))
;; No need to reduce as < is a branching primitive.
(make-conditional src (make-primcall src '< (list b a))
(make-const src #f)
(make-const src #t)))
;; No need to reduce as <= is a branching primitive.
(make-conditional src (make-primcall src '<= (list a b))
(make-const src #t)
(make-const src #f)))
(($ <primcall> src '>= (a b))
;; No need to reduce as < is a branching primitive.
(make-conditional src (make-primcall src '< (list a b))
(make-const src #f)
(make-const src #t)))
(make-conditional src (make-primcall src '<= (list b a))
(make-const src #t)
(make-const src #f)))
(($ <primcall> src '> (a b))
;; No need to reduce as < is a branching primitive.