Age | Commit message (Collapse) | Author | Files | Lines |
|
The following patch fixes
FAIL: gcc.dg/dfp/bitint-1.c (test for excess errors)
FAIL: gcc.dg/dfp/bitint-2.c (test for excess errors)
FAIL: gcc.dg/dfp/bitint-3.c (test for excess errors)
FAIL: gcc.dg/dfp/bitint-4.c (test for excess errors)
FAIL: gcc.dg/dfp/bitint-5.c (test for excess errors)
FAIL: gcc.dg/dfp/bitint-6.c (test for excess errors)
FAIL: gcc.dg/dfp/bitint-8.c (test for excess errors)
FAIL: gcc.dg/dfp/int128-1.c (test for excess errors)
FAIL: gcc.dg/dfp/int128-2.c (test for excess errors)
FAIL: gcc.dg/dfp/int128-4.c (test for excess errors)
on s390x-linux (with the 3 not yet posted patches).
The patch does multiple things:
1) the routines were written for the DFP BID (binary integer decimal)
format which is used on all arches but powerpc*/s390* (those use
DPD - densely packed decimal format); as most of the code is actually
the same for both BID and DPD formats, I haven't copied the sources
+ slightly modified them, but added the DPD support directly, + renaming
of the exported symbols from __bid_* prefixed to __dpd_* prefixed that
GCC expects on the DPD targets
2) while testing that I've found some big-endian issues in the existing
support
3) testing also revealed that in some cases __builtin_clzll (~msb) was
called with msb set to all ones, so invoking UB; apparently on aarch64
and x86 we were lucky and got some value that happened to work well,
but that wasn't the case on s390x
For 1), the patch uses two ~ 2KB tables to speed up the decoding/encoding.
I haven't found such tables in what is added into libgcc.a, though they
are in libdecnumber/bid/bid2dpd_dpd2bid.h, but there they are just huge
and next to other huge tables - there is d2b which is like __dpd_d2bbitint
in the patch but it uses 64-bit entries rather than 16-bit, then there is
d2b2 with 64-bit entries like in d2b all multiplied by 1000, then d2b3
similarly multiplied by 1000000, then d2b4 similarly multiplied by
1000000000, then d2b5 similarly multiplied by 1000000000000ULL and
d2b6 similarly multipled by 1000000000000000ULL. Arguably it can
save some of the multiplications, but on the other side accesses memory
which is unlikely in the caches, and the 2048 bytes in the patch vs.
24 times more for d2b is IMHO significant.
For b2d, libdecnumber/bid/bid2dpd_dpd2bid.h has again b2d table like
__dpd_b2dbitint in the patch, except that it has 64-bit entries rather
than 16-bit (this time 1000 entries), but then has b2d2 which has the
same entries shifted left by 10, then b2d3 shifted left by 20, b2d4 shifted
left by 30 and b2d5 shifted left by 40. I can understand for d2b paying
memory cost to speed up multiplications, but don't understand paying
extra 4 * 8 * 1000 bytes (+ 6 * 1000 bytes for b2d not using ushort)
just to avoid shifts.
2025-05-27 Jakub Jelinek <jakub@redhat.com>
* config/t-softfp (softfp_bid_list): Don't guard with
$(enable_decimal_float) == bid.
* soft-fp/bitint.h (__bid_pow10bitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_pow10bitint.
(__dpd_d2bbitint, __dpd_b2dbitint): Declare.
* soft-fp/bitintpow10.c (__dpd_d2bbitint, __dpd_b2dbitint): New
variables.
* soft-fp/fixsdbitint.c (__bid_fixsdbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixsdbitint.
Add DPD support. Fix big-endian support.
* soft-fp/fixddbitint.c (__bid_fixddbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixddbitint.
Add DPD support. Fix big-endian support.
* soft-fp/fixtdbitint.c (__bid_fixtdbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixtdbitint.
Add DPD support. Fix big-endian support.
* soft-fp/fixsdti.c (__bid_fixsdbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixsdbitint.
(__bid_fixsdti): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine to
__dpd_fixsdti.
* soft-fp/fixddti.c (__bid_fixddbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixddbitint.
(__bid_fixddti): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine to
__dpd_fixddti.
* soft-fp/fixtdti.c (__bid_fixtdbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixtdbitint.
(__bid_fixtdti): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine to
__dpd_fixtdti.
* soft-fp/fixunssdti.c (__bid_fixsdbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixsdbitint.
(__bid_fixunssdti): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine
to __dpd_fixunssdti.
* soft-fp/fixunsddti.c (__bid_fixddbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixddbitint.
(__bid_fixunsddti): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine
to __dpd_fixunsddti.
* soft-fp/fixunstdti.c (__bid_fixtdbitint): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_fixtdbitint.
(__bid_fixunstdti): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine
to __dpd_fixunstdti.
* soft-fp/floatbitintsd.c (__bid_floatbitintsd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitintsd.
Add DPD support. Avoid calling __builtin_clzll with 0 argument. Fix
big-endian support.
* soft-fp/floatbitintdd.c (__bid_floatbitintdd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitintdd.
Add DPD support. Avoid calling __builtin_clzll with 0 argument. Fix
big-endian support.
* soft-fp/floatbitinttd.c (__bid_floatbitinttd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitinttd.
Add DPD support. Avoid calling __builtin_clzll with 0 argument. Fix
big-endian support.
* soft-fp/floattisd.c (__bid_floatbitintsd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitintsd.
(__bid_floattisd): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine to
__dpd_floattisd.
* soft-fp/floattidd.c (__bid_floatbitintdd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitintdd.
(__bid_floattidd): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine to
__dpd_floattidd.
* soft-fp/floattitd.c (__bid_floatbitinttd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitinttd.
(__bid_floattitd): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine to
__dpd_floattitd.
* soft-fp/floatuntisd.c (__bid_floatbitintsd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitintsd.
(__bid_floatuntisd): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine
to __dpd_floatuntisd.
* soft-fp/floatuntidd.c (__bid_floatbitintdd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitintdd.
(__bid_floatuntidd): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine
to __dpd_floatuntidd.
* soft-fp/floatuntitd.c (__bid_floatbitinttd): For
!defined(ENABLE_DECIMAL_BID_FORMAT) redefine to __dpd_floatbitinttd.
(__bid_floatuntitd): For !defined(ENABLE_DECIMAL_BID_FORMAT) redefine
to __dpd_floatuntitd.
|
|
The big-endian _BitInt support in libgcc was written without any
testing and so I haven't discovered I've made one mistake in it
(in multiple places).
The bitint_reduce_prec function attempts to optimize inputs
which have some larger precision but at runtime they are found
to need smaller number of limbs.
For little-endian that is handled just by returning smaller
precision (or negative precision for signed), but for
big-endian we need to adjust the passed in limb pointer so that
when it returns smaller precision the argument still contains
the least significant limbs for the returned precision.
2025-05-20 Jakub Jelinek <jakub@redhat.com>
* libgcc2.c (bitint_reduce_prec): For big endian
__LIBGCC_BITINT_ORDER__ use ++*p and --*p instead of
++p and --p.
* soft-fp/bitint.h (bitint_reduce_prec): Likewise.
|
|
As I wrote earlier, I was seeing
FAIL: gcc.dg/torture/bitint-24.c -O0 execution test
FAIL: gcc.dg/torture/bitint-24.c -O2 execution test
with the ia32 _BitInt enablement patch on i686-linux. I thought
floatbitintxf.c was miscompiled with -O2 -march=i686 -mtune=generic, but it
turned out to be UB in it.
If a signed _BitInt to be converted to binary floating point has
(after sign extension from possible partial limb to full limb) one or
more most significant limbs equal to all ones and then in the limb below
(the most significant non-~(UBILtype)0 limb) has the most significant limb
cleared, like for 32-bit limbs
0x81582c05U, 0x0a8b01e4U, 0xc1b8b18fU, 0x2aac2a08U, -1U, -1U
then bitint_reduce_prec can't reduce it to that 0x2aac2a08U limb, so
msb is all ones and precision is negative (so it reduced precision from
161 to 192 bits down to 160 bits, in theory could go as low as 129 bits
but that wouldn't change anything on the following behavior).
But still iprec is negative, -160 here.
For that case (i.e. where we are dealing with an negative input), the
code was using 65 - __builtin_clzll (~msb) to compute how many relevant
bits we have from the msb. Unfortunately that invokes UB for msb all ones.
The right number of relevant bits in that case is 1 though (like for
-2 it is 2 and -4 or -3 3 as already computed) - all we care about from that
is that the most significant bit is set (i.e. the number is negative) and
the bits below that should be supplied from the limbs below.
So, the following patch fixes it by special casing it not to invoke UB.
For msb 0 we already have a special case from before (but that is also
different because msb 0 implies the whole number is 0 given the way
bitint_reduce_prec works - even if we have limbs like ..., 0x80000000U, 0U
the reduction can skip the most significant limb and msb then would be
the one below it), so if iprec > 0, we already don't call __builtin_clzll
on 0.
2024-02-13 Jakub Jelinek <jakub@redhat.com>
* soft-fp/bitint.h (FP_FROM_BITINT): If iprec < 0 and msb is all ones,
just set n to 1 instead of using __builtin_clzll (~msb).
|
|
As discussed on IRC, the following patch uses may_alias attribute, so that
on targets like aarch64 where abi_limb_mode != limb_mode the library
accesses the limbs (half limbs of the ABI) in the arrays with conservative
alias set.
2024-01-12 Jakub Jelinek <jakub@redhat.com>
* libgcc2.h (UBILtype): New typedef with may_alias attribute.
(__mulbitint3, __divmodbitint4): Use UBILtype * instead of
UWtype * and const UBILtype * instead of const UWtype *.
* libgcc2.c (bitint_reduce_prec, bitint_mul_1, bitint_addmul_1,
__mulbitint3, bitint_negate, bitint_submul_1, __divmodbitint4):
Likewise.
* soft-fp/bitint.h (UBILtype): Change define into a typedef with
may_alias attribute.
|
|
On Mon, Aug 21, 2023 at 05:32:04PM +0000, Joseph Myers wrote:
> I think the libgcc functions (i.e. those exported by libgcc, to which
> references are generated by the compiler) need documenting in libgcc.texi.
> Internal functions or macros in the libgcc patch need appropriate comments
> specifying their semantics; especially FP_TO_BITINT and FP_FROM_BITINT
> which have a lot of arguments and no comments saying what the semantics of
> the macros and their arguments are supposed to me.
Here is an incremental patch which does that.
2023-09-06 Jakub Jelinek <jakub@redhat.com>
PR c/102989
gcc/
* doc/libgcc.texi (Bit-precise integer arithmetic functions):
Document general rules for _BitInt support library functions
and document __mulbitint3 and __divmodbitint4.
(Conversion functions): Document __fix{s,d,x,t}fbitint,
__floatbitint{s,d,x,t,h,b}f, __bid_fix{s,d,t}dbitint and
__bid_floatbitint{s,d,t}d.
libgcc/
* libgcc2.c (bitint_negate): Add function comment.
* soft-fp/bitint.h (bitint_negate): Add function comment.
(FP_TO_BITINT, FP_FROM_BITINT): Add comment explaining the macros.
|
|
This patch adds the library helpers for multiplication, division + modulo
and casts from and to floating point (both binary and decimal).
As described in the intro, the first step is try to reduce further the
passed in precision by skipping over most significant limbs with just zeros
or sign bit copies. For multiplication and division I've implemented
a simple algorithm, using something smarter like Karatsuba or Toom N-Way
might be faster for very large _BitInts (which we don't support right now
anyway), but could mean more code in libgcc, which maybe isn't what people
are willing to accept.
For the to/from floating point conversions the patch uses soft-fp, because
it already has tons of handy macros which can be used for that. In theory
it could be implemented using {,unsigned} long long or {,unsigned} __int128
to/from floating point conversions with some frexp before/after, but at that
point we already need to force it into integer registers and analyze it
anyway. Plus, for 32-bit arches there is no __int128 that could be used
for XF/TF mode stuff.
I know that soft-fp is owned by glibc and I think the op-common.h change
should be propagated there, but the bitint stuff is really GCC specific
and IMHO doesn't belong into the glibc copy.
2023-09-06 Jakub Jelinek <jakub@redhat.com>
PR c/102989
libgcc/
* config/aarch64/t-softfp (softfp_extras): Use += rather than :=.
* config/i386/64/t-softfp (softfp_extras): Likewise.
* config/i386/libgcc-glibc.ver (GCC_14.0.0): Export _BitInt support
routines.
* config/i386/t-softfp (softfp_extras): Add fixxfbitint and
bf, hf and xf mode floatbitint.
(CFLAGS-floatbitintbf.c, CFLAGS-floatbitinthf.c): Add -msse2.
* config/riscv/t-softfp32 (softfp_extras): Use += rather than :=.
* config/rs6000/t-e500v1-fp (softfp_extras): Likewise.
* config/rs6000/t-e500v2-fp (softfp_extras): Likewise.
* config/t-softfp (softfp_floatbitint_funcs): New.
(softfp_bid_list): New.
(softfp_func_list): Add sf and df mode from and to _BitInt libcalls.
(softfp_bid_file_list): New.
(LIB2ADD_ST): Add $(softfp_bid_file_list).
* config/t-softfp-sfdftf (softfp_extras): Add fixtfbitint and
floatbitinttf.
* config/t-softfp-tf (softfp_extras): Likewise.
* libgcc2.c (bitint_reduce_prec): New inline function.
(BITINT_INC, BITINT_END): Define.
(bitint_mul_1, bitint_addmul_1): New helper functions.
(__mulbitint3): New function.
(bitint_negate, bitint_submul_1): New helper functions.
(__divmodbitint4): New function.
* libgcc2.h (LIBGCC2_UNITS_PER_WORD): When building _BitInt support
libcalls, redefine depending on __LIBGCC_BITINT_LIMB_WIDTH__.
(__mulbitint3, __divmodbitint4): Declare.
* libgcc-std.ver.in (GCC_14.0.0): Export _BitInt support routines.
* Makefile.in (lib2funcs): Add _mulbitint3.
(LIB2_DIVMOD_FUNCS): Add _divmodbitint4.
* soft-fp/bitint.h: New file.
* soft-fp/fixdfbitint.c: New file.
* soft-fp/fixsfbitint.c: New file.
* soft-fp/fixtfbitint.c: New file.
* soft-fp/fixxfbitint.c: New file.
* soft-fp/floatbitintbf.c: New file.
* soft-fp/floatbitintdf.c: New file.
* soft-fp/floatbitinthf.c: New file.
* soft-fp/floatbitintsf.c: New file.
* soft-fp/floatbitinttf.c: New file.
* soft-fp/floatbitintxf.c: New file.
* soft-fp/op-common.h (_FP_FROM_INT): Add support for rsize up to
4 * _FP_W_TYPE_SIZE rather than just 2 * _FP_W_TYPE_SIZE.
* soft-fp/bitintpow10.c: New file.
* soft-fp/fixsdbitint.c: New file.
* soft-fp/fixddbitint.c: New file.
* soft-fp/fixtdbitint.c: New file.
* soft-fp/floatbitintsd.c: New file.
* soft-fp/floatbitintdd.c: New file.
* soft-fp/floatbitinttd.c: New file.
|