Marc:
I'm going over c#prim-procs to see which other routines could be inlined.
First, I'm comparing
(##define-macro (macro-number-dispatch num err fix big rat flo cpx) `(cond ((##fixnum? ,num) ,fix) ((##flonum? ,num) ,flo) ((##subtyped? ,num) (let ((##s (##subtype ,num))) (cond ((##fixnum.= ##s (macro-subtype-bignum)) ,big) ((##fixnum.= ##s (macro-subtype-ratnum)) ,rat) ((##fixnum.= ##s (macro-subtype-cpxnum)) ,cpx) (else ,err)))) (else ,err)))
in _num#.scm with
(define-prim (##flonum? obj) (and (##subtyped? obj) (##eq? (##subtype obj) (macro-subtype-flonum))))
in sys.scm, and I suggest macro-number-dispatch be redefined as
(##define-macro (macro-number-dispatch num err fix big rat flo cpx) `(cond ((##fixnum? ,num) ,fix) ((##subtyped? ,num) (let ((##s (##subtype ,num))) (cond ((##fixnum.= ##s (macro-subtype-flonum)) ,flo) ((##fixnum.= ##s (macro-subtype-bignum)) ,big) ((##fixnum.= ##s (macro-subtype-ratnum)) ,rat) ((##fixnum.= ##s (macro-subtype-cpxnum)) ,cpx) (else ,err)))) (else ,err)))
Now, I look at
(define-prim (##eqv? obj1 obj2) (macro-number-dispatch obj1 (##eq? obj1 obj2) (and (##fixnum? obj2) (##fixnum.= obj1 obj2)) ; obj1 = fixnum (and (##bignum? obj2) (##bignum.= obj1 obj2)) ; obj1 = bignum (and (##ratnum? obj2) (##ratnum.= obj1 obj2)) ; obj1 = ratnum (and (##flonum? obj2) (##bvector-equal? obj1 obj2)) ; obj1 = flonum (and (##cpxnum? obj2) ; obj1 = cpxnum (##eqv? (macro-cpxnum-real obj1) (macro-cpxnum-real obj2)) (##eqv? (macro-cpxnum-imag obj1) (macro-cpxnum-imag obj2)))))
in sys.scm. I think one can (should?) inline (##eqv? x y) as
(or (##eq? x y) (and (##subtyped? x) (##subtyped? y) (let ((##sx (##subtype x))) (and (##fixnum.= ##sx (##subtype y)) (or (##fixnum.= ##sx (macro-subtype-flonum)) (##fixnum.= ##sx (macro-subtype-bignum)) (##fixnum.= ##sx (macro-subtype-ratnum)) (##fixnum.= ##sx (macro-subtype-cpxnum))) (##eqv? x y)))))
The second limb of the first "or" can be be eliminated for many compile-time constants (please use the commutativity of ##eqv? if y happens to be a compile-time constant and x isn't), which can be especially important for compiling "case" forms.
There are a number of "case" forms in the files compiler, dynamic, early, graphs, lattice, matrix, nboyer, nucleic, sboyer, scheme, and test in bench/src. In your latest benchmarks Bigloo beat Gambit in boyer, dynamic, and scheme; maybe the lack of inlining of eqv? in case contributed.
Perhaps one can use a similar strategy for inlining equal?
Other things that could (should?) be inlined (perhaps some of these already are inlined for special values of the arguments):
boolean?
list-ref (like memv)
memv (now that eqv? can be inlined)
assv (ditto)
number?, complex?, real?, rational?, integer?, exact?, inexact? (it doesn't seem so bad to inline macro-number-dispatch since the results are boolean, or at least these could be tested for fixnum and flonum)
abs (for fixnum, using ##fixnum.-? if the argument is negative)
gcd and lcm (for one argument)
numerator and denominator (for fixnums)
floor, ceiling, truncate, round (for fixnums)
real-part, imag-part, magnitude (for fixnum and flonum arguments)
string
string=? and friends with 0 and 1 arguments.
Generally, I went through all the items in prim-procs, and generated little programs that used them with varying number of arguments, then visually inspected the expanded code and (sometimes) the C code to see what's going on. I'm including my little test file at the end.
Brad