Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Tue, 27 Aug 2013 10:21:59 -0400
From: Rich Felker <dalias@...ifal.cx>
To: musl@...ts.openwall.com
Subject: Re: Optimized C memset

On Tue, Aug 27, 2013 at 11:50:40AM +0200, Jens Gustedt wrote:
> Am Dienstag, den 27.08.2013, 05:17 -0400 schrieb Rich Felker:
> > So far, my experience is that compilers which advertise themseleves as
> > "GNU C" compilers have all the semantic features of GCC 3 at the very
> > least. Is this an invalid assumption?
> 
> for gcc versions less than 4, probably, I don't remember an exception
> for that. For version in the 4, there are several such examples.

I just checked and confirmed that cparser/libfirm and pcc both support
the may_alias attribute. I would assume clang does.

> > > To make this easier to maintain, I'd suggest to introduce a special
> > > feature test macro, something like __has_may_alias__, and have that
> > > set at the beginning of the file in a section that is clearly
> > > dedicated to compile time feature detection. Other compilers may have
> > > different syntax for such a feature (a _Pragma comes in mind) and may
> > > be detected quite differently than by gcc version numbering.
> > 
> > Where would you suggest it be added? The result of the check is only
> > used in one place, so I don't see how
> 
> 
> I'd wouldn't have an #else case to the detection but do
> 
> #ifndef may_alias
> # if 100*__GNUC__+__GNUC_MINOR__ >= 302
> #  define may_alias __attribute__((__may_alias__))
> # endif
> #endif
> 
> #ifdef may_alias
> # define __has_may_alias__
> #else
> # define may_alias
> #endif
> 
> This is not much more complicated than what you have and makes it easy
> to add other cases, without having to maintain the __has_may_alias__
> feature macro itself.

At this point, __has_may_alias__ is not used for anything. So I fail
to see how the above is any different from what I wrote in the source
file.

> > If on the other hand you're suggesting that I should be more
> > conservative and check not just for __GNUC__, but also for the
> > availability of __may_alias__, in the actual code body (rather than
> > just the typedefs), then it may make more sense.
> 
> yes, I thought in these lines. that code should be handled well by any
> modern compiler that you can convince to not playing games with
> aliasing, here. So the fact that you tested it with gcc-like compilers
> is merely an artefact.

If you're saying testing __has_may_alias__ rather than __GNUC__ buys
us more portability, I don't see a reason to believe this. A
hypothetical non-GNUC compiler might need an actual pointer variable
(rather than cast through a pointer type with may_alias on it) to
avoid the aliasing violation, or it might require a special attribute
on the function indicating that the whole function has immunity from
the aliasing rules, or any number of other possibilities.

The general approach in musl to these sort of things (compiler and
machine dependency) is not to design around some hypothetical abstract
level of generality, but to be general to all known existing targets,
and adapt to increase generality only when needed. (And, whenever
possible, have a 100% portable fallback that relies on nothing
compiler- or machine-specific.) The logic for accessing the libc
struct in src/internal/libc.h is the best example of this approach.

I guess what I'm saying is that I don't want more complex ifdeffery to
support optimizations on some hypothetical non-GCC compiler that does
may_alias in a way different from GCC, unless such a compiler actually
exists, since any "solution" we try to make now to the problem of
additional generality might not even solve the problem if/when such a
compiler exists.

> > > Such specific feature test macros is the way that clang goes, and from
> > > my experience this is much easier to maintain and to understand when
> > > you stumble on such #ifdef'ed code. You not only know that this needs
> > > a special version of a compiler, but also for what reason.
> > 
> > Oh, I agree it's much cleaner. Sadly, though, GCC doesn't seem to give
> > us that information...
> 
> yes, for gcc you'd always have to detect features in the way you are
> doing it know. But I'd think that feature detection should be
> separated from the use of the features. The uses might be spread over
> several places, but the detection should be done in one well
> detectable spot in the source code.

The trade-off is between some duplication of the logic for which
version of the code can be used, and added barrier to reading the
code. One of the things I think our users like about musl versus glibc
is that, for the vast majority of the code, you can fully determine
what it's doing without reading other implementation-specific files
that define magic macros for things you might not understand -- and
that you can take the code and drop it into another project without
having to find all the implementation-internal headers it depends on.

If something needs to be changed about the logic for may_alias, a
simple grep -r will find all the source files it's in and makes it
easy to change several occurrences. So I tend to think preserving
readability and ease of reuse are more important than avoiding
duplication, but if others agree with you, I wouldn't be entirely
opposed to adding a "string_impl.h" or similar header with some shared
preprocessor logic for all of the string functions that might be doing
sketchy things with aliasing and alignment. I'd appreciate comments on
this matter from others on which way we should go.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.