Re: C aggregate passing (Rust kernel policy)

Linus Torvalds
2025-02-22T19:18:54Z

On Sat, 22 Feb 2025 at 10:54, Kent Overstreet <kent.overstreet@linux.dev> wrote:
>
> If that work is successful it could lead to significant improvements in
> code generation, since aliasing causes a lot of unnecessary spills and
> reloads - VLIW could finally become practical.

No.

Compiler people think aliasing matters. It very seldom does. And VLIW
will never become practical for entirely unrelated reasons (read: OoO
is fundamentally superior to VLIW in general purpose computing).

Aliasing is one of those bug-bears where compiler people can make
trivial code optimizations that look really impressive. So compiler
people *love* having simplistic aliasing rules that don't require real
analysis, because the real analysis is hard (not just expensive, but
basically unsolvable).

And they matter mainly on bad CPUs and HPC-style loads, or on trivial
example code. And for vectorization.

And the sane model for those was to just have the HPC people say what
the aliasing rules were (ie the C "restrict" keyword), but because it
turns out that nobody wants to use that, and because one of the main
targets was HPC where there was a very clear type distinction between
integer indexes and floating point arrays, some "clever" person
thought "why don't we use that obvious distinction to say that things
don't alias". Because then you didn't have to add "restrict" modifiers
to your compiler benchmarks, you could just use the existing syntax
("double *").

And so they made everything worse for everybody else, because it made
C HPC code run as fast as the old Fortran code, and the people who
cared about DGEMM and BLAS were happy. And since that was how you
defined supercomputer speeds (before AI), that largely pointless
benchmark was a BigDeal(tm).

End result: if you actually care about HPC and vectorization, just use
'restrict'. If you want to make it better (because 'restrict'
certainly isn't perfect either), extend on the concept. Don't make
things worse for everybody else by introducing stupid language rules
that are fundamentally based on "the compiler can generate code better
by relying on undefined behavior".

The C standards body has been much too eager to embrace "undefined behavior".

In original C, it was almost entirely about either hardware
implementation issues or about "you got your pointer arithetic wrong,
and the source code is undefined, so the result is undefined".
Together with some (very unfortunate) order of operations and sequence
point issues.

But instead of trying to tighten that up (which *has* happened: the
sequence point rules _have_ actually become better!) and turning the
language into a more reliable one by making for _fewer_ undefined or
platform-defined things, many C language features have been about
extending on the list of undefined behaviors.

The kernel basically turns all that off, as much as possible. Overflow
isn't undefined in the kernel. Aliasing isn't undefined in the kernel.
Things like that.

And making the rules stricter makes almost no difference for code
generation in practice. Really. The arguments for the garbage that is
integer overflow or 'strict aliasing' in C were always just wrong.

When 'integer overflow' means that you can _sometimes_ remove one
single ALU operation in *some* loops, but the cost of it is that you
potentially introduced some seriously subtle security bugs, I think we
know it was the wrong thing to do.

Linus