[llvm-dev] A libc in LLVM

Stephen Canon via llvm-dev
Fri, 28 Jun 2019 16:58:08 -0000

> On Jun 26, 2019, at 2:20 PM, Siva Chandra via llvm-dev <llvm-dev at
lists.llvm.org> wrote:
>
> 5. Avoid assembly language as far as possible - Again, there will be
> places where one cannot avoid assembly level implementations. But,
> wherever possible, we want to avoid assembly level implementations.
> There are a few reasons here as well:
>
> a) We want to leverage the compiler for performance wherever possible,
> and as part of the LLVM project, fix compiler bugs rather than use
> assembly.

As a long time libm and libc developer, and occasional compiler contributor, I
will point out that this is either fundamentally in conflict with your other
stated goals, entails a commitment to wide-ranging compiler improvements, or
requires some very specific choices about your implementation. Much of a libc
can be implemented quite easily in C or C++. However:

- You say you want to conform to relevant standards; however, e.g. the UNIX test
suite requires that math.h functions not set spurious flags. This is impossible
to reliably achieve in C with clang, because clang and LLVM do not precisely
model the floating-point environment. On Apple’s platforms, much of the math
library is written in assembly as much for this reason as for performance. I see
four basic options for you here:

1. You could partially work around this by adding builtins and an extensive
conformance suite, making your implementations fragile to compiler optimization
but detecting the breakages immediately.
2. You could do the work of precisely modeling the floating-point environment.
3. You could simply declare that you are not going to care about flags at all,
which is fine for 99% of users, but is a clear break from relevant standards
(and would make your libc unable to be adopted by some platform maintainers).
4. You could implement significant pieces of the math library in assembly.

None of these is a decision to be undertaken lightly. Have you thought about
this issue at all?

I would also be curious what your plans are with regard to reproducible results
in the math library: is it your intention to produce the same result on all
platforms? On all microarchitectures? If so, and you’re developing for baseline
x86_64 first, you’re locking yourself out of using many architectural features
that are critical to delivering 30-50% of performance for these functions on
other platforms (and even on newer x86)—static rounding control, FMA, etc. Even
if you don’t care about that, implementation choices you make for around x86_64
will severely restrict your performance on other platforms if exact
reproducibility is a requirement and you don’t carefully choose a set of
“required ISA operations” on which to implement your math functions.

- For most platforms, there are significant performance wins available for some
of the core strings and memory functions using assembly, even as compared to the
best compiler auto-vectorization output. There are a few reasons for this, but
one of the major ones is that—in assembly, on most architectures—we can safely
do aligned memory accesses that are partially outside the buffer that has been
passed in, and mask off or ignore the bytes that are invalid. This is a hugely
significant optimization for edging around core vector loops, and it’s simply
unavailable in C and C++ because of the abstract memory models they define. A
compiler could do this for you automatically, but this is not yet implemented in
LLVM (and you don’t want to be tightly coupled to LLVM, anyway?) In practice, on
many systems, the small-buffer case dominates usage for these functions, so
getting the most efficient edging code is basically the only thing that matters.

1. Are you going to teach LLVM to perform these optimizations? If so, awesome,
but this is not at all a small project—you’re not just fixing an isolated perf
bug, you’re fundamentally reworking autovectorization. What about other
compilers?
2. Are you going to simply write off performance in these cases and let the
autovectorizer do what it does?
3. Will you use assembly instead purely for optimization purposes?

A bunch of other questions will probably come to me around the math library, but
I would encourage you to think very carefully about what specifications you want
to have for a libm before you start building one. All that said, I think having
more libc implementations is great, but I would be very careful to define what
design tradeoffs you’re making around these choices and to what spec(s) you plan
to conform, and why they necessitate a new libc rather than adapting an existing
one.

– Steve
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20190628/80412028/attachment.html>