On 2/4/24 05:11, felix.winkelm...@bevuta.com wrote:

1. The egg itself is not compiled with -O3, whereas if I link to
(chicken fixnum) I believe that these procedures will be inlined by the
CHICKEN compiler when the arrays egg is compiled with -O3 or higher.

That's correct. As -O3 implies "unsafe", the compiler can just ignore
type checks and always inline numeric primitives.


Awesome, glad my intuition about this wasn't unfounded. This is probably the biggest factor.


2. There may be some rewriting rules that the compiler uses for
procedures in the (chicken ...) namespace that optimizes these directly
into their equivalent optimized C procedures. I'm not sure the compiler
has the same visibility if you re-export these from behind a module, and
especially not if you link dynamically (any hope of inlining those is
thus gone forever).

As a general rule all renamings and rexports preserve the run-time
semantics - as long as a procedure definition is not wrapped inside
another procedure, the original procedure gets compiled and any
optimizations and inlinings the compiler performs for "known" primitives will be
applied. Syntax- and module-specific expansions perform renaming
only and never introduce run-time code that wasn't explicitly given by
the user.


Aha, so as long as something is wrapped we don't see the same kind of inlining.


In fact on the latter point above, this raises an interesting question I
had for the mailing list: if I re-export a CHICKEN-specific procedure,
does the way the compiler handles translation units prevent certain
optimizations from applying? I've somewhat noticed that to be the case
but I haven't seen any writing about it nor have I understood the extent
to which that might affect certain SRFIs or eggs.

See above - unless something is wrapped, you get the inlining. But as
I see in the SRFI-143 spec, their operations take any number of
arguments, where the ones from (chicken fixnum) have arity 2,
so I assume the srfi code wraps the primitives into multi-argument
procedures and thus preserves imports from the srfi-143 module to be inlined.


And yup, that's probably it. From what I can tell from the source locally they are wrapped e.g.:

    (define (fx+ . args)
      (foldr chicken:fx+ 0 args))


If you have time/energy, it would be useful to make Chicken's
implementation do what it was originally intended.  See the
"Implementation" section in the SRFI, or feel free to ask me for
explanations of details.

One approach would be to extend those exports from (chicken fixnum)
that match the multi-argument operations from srfi-143 and make the
compiler aware of these, internally expanding the multi-arg cases into
nested applications of inline calls to the 2-argument C runtime primitive
ops.


So what would this look like? I can see fx+ above, which uses `chicken:fx+` (prefixed, 2-arity) and foldr to accomplish its multi-arg case. Is adding `(inline-file)` to the srfi-143.egg enough for this? I suspect partly that the foldr and `(fx+ . args)` form in general is going to be hard to optimize out, but perhaps a case-lambda is faster?

I suppose in pretty much all cases since I'm using the 2-arity versions in the generalized-arrays library there's very little pushing me to use the SRFI-143 versions, but any improvement to SRFI-143 is probably worthwhile considering the kinds of performance differences I was measuring with chicken-profile.


It might also be a good idea to enforce SRFI-143's behaviour around
overflow / underflow as part of CHICKEN's default behaviour in CHICKEN
6, but I don't really know how I would get started having that discussion.

The SRFI-page doesn't seem to specify any behaviour. The runtime system
is compiled with "-fwrapv" in the hope to preserve wrapping semantics for
integer arithmetic, but I'm not sure how reliable that is.


Interesting! I believed the SRFI-143 was specifying twos-complement behaviour, but I now see that I was wrong. I would think in general that if -fwrapv is passed, we should assume that twos-complement is used. Recent C standards have codified this explicitly, but pretty much every major compiler I've used over the last 10 years has all-but-standardized twos-complement as well.

I guess as long as the runtime system is always using -fwrapv it isn't a concern. It would be undefined behaviour without that flag though, which I suppose someone could maybe force, with great effort?

Either way, probably not worth worrying about.

Thanks for the really informed reply Felix, this was very helpful in understanding what's happening with SRFI-143. I can hopefully start crafting a patch for this now.

Cheers,
--
Jeremy Steward

Reply via email to