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