This is the mail archive of the gcc-patches@gcc.gnu.org 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?

FX


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


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]