This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[fortran,patch] Fix LEADZ/TRAILZ

The current implementation of LEADZ/TRAILZ has the following bugs:

1. Simplification of LEADZ for negative arguments is wrong (it should always give 0)

2. When calling leadz or trailz on a type smaller than "int", we should cast to the unsigned type of the same size before casting to "unsigned int"; that is, for example, we should do:
__builtin_clz ((unsigned int) (unsigned short) short_value)
instead of
__builtin_clz ((unsigned int) short_value)
Otherwise, for negative values, we get wrong results.

3. In the translation of these intrisics, kinds <= 4 yield a call to __builtin_clz(), kind = 8 calls __builtin_clzl() and kind = 16 calls __builtin_clzll(). This is wrong, as there is no such hard-wired correspondance of integer kinds and C types. In particular, on x86_64, integer(kind=16) is larger than "long long int", and thus no builtin is available!

The attached patch solves all these issues, by 1. special-casing negatives args in LEADZ simplification; 2. performing the correct double cast; 3. choosing the right builtin based on type size, and call adequate new library functions (_gfortran_clz128 / _gfortran_ctz128).

Bootstrapped and regtested on x86_64-linux, comes with testcases. OK to commit?


PS: could the reviewer (or another maintainer) please double check that I've done the correct modification to libgfortran/

Attachment: leadz_trailz.ChangeLog
Description: Binary data

Attachment: leadz_trailz.diff
Description: Binary data

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]