Find a file
Jakub Jelinek fbb569315a libgcc: Fix up _BitInt division [PR113604]
The following testcase ends up with SIGFPE in __divmodbitint4.
The problem is a thinko in my attempt to implement Knuth's algorithm.

The algorithm does (where b is 65536, i.e. one larger than what
fits in their unsigned short word):
        // Compute estimate qhat of q[j].
        qhat = (un[j+n]*b + un[j+n-1])/vn[n-1];
        rhat = (un[j+n]*b + un[j+n-1]) - qhat*vn[n-1];
      again:
        if (qhat >= b || qhat*vn[n-2] > b*rhat + un[j+n-2])
        { qhat = qhat - 1;
          rhat = rhat + vn[n-1];
          if (rhat < b) goto again;
        }
The problem is that it uses a double-word / word -> double-word
division (and modulo), while all we have is udiv_qrnnd unless
we'd want to do further library calls, and udiv_qrnnd is a
double-word / word -> word division and modulo.
Now, as the algorithm description says, it can produce at most
word bits + 1 bit quotient.  And I believe that actually the
highest qhat the original algorithm can produce is
(1 << word_bits) + 1.  The algorithm performs earlier canonicalization
where both the divisor and dividend are shifted left such that divisor
has msb set.  If it has msb set already before, no shifting occurs but
we start with added 0 limb, so in the first uv1:uv0 double-word uv1
is 0 and so we can't get too high qhat, if shifting occurs, the first
limb of dividend is shifted right by UWtype bits - shift count into
a new limb, so again in the first iteration in the uv1:uv0 double-word
uv1 doesn't have msb set while vv1 does and qhat has to fit into word.
In the following iterations, previous iteration should guarantee that
the previous quotient digit is correct.  Even if the divisor was the
maximal possible vv1:all_ones_in_all_lower_limbs, if the old uv0:lower_limbs
would be larger or equal to the divisor, the previous quotient digit
would increase and another divisor would be subtracted, which I think
implies that in the next iteration in uv1:uv0 double-word uv1 <= vv1,
but uv0 could be up to all ones, e.g. in case of all lower limbs
of divisor being all ones and at least one dividend limb below uv0
being not all ones.  So, we can e.g. for 64-bit UWtype see
uv1:uv0 / vv1 0x8000000000000000UL:0xffffffffffffffffUL / 0x8000000000000000UL
or 0xffffffffffffffffUL:0xffffffffffffffffUL / 0xffffffffffffffffUL
In all these cases (when uv1 == vv1 && uv0 >= uv1), qhat is
0x10000000000000001UL, i.e. 2 more than fits into UWtype result,
if uv1 == vv1 && uv0 < uv1 it would be 0x10000000000000000UL, i.e.
1 more than fits into UWtype result.
Because we only have udiv_qrnnd which can't deal with those too large
cases (SIGFPEs or otherwise invokes undefined behavior on those), I've
tried to handle the uv1 >= vv1 case separately, but for one thing
I thought it would be at most 1 larger than what fits, and for two
have actually subtracted vv1:vv1 from uv1:uv0 instead of subtracting
0:vv1 from uv1:uv0.
For the uv1 < vv1 case, the implementation already performs roughly
what the algorithm does.
Now, let's see what happens with the two possible extra cases in
the original algorithm.
If uv1 == vv1 && uv0 < uv1, qhat above would be b, so we take
if (qhat >= b, decrement qhat by 1 (it becomes b - 1), add
vn[n-1] aka vv1 to rhat and goto again if rhat < b (but because
qhat already fits we can goto to the again label in the uv1 < vv1
code).  rhat in this case is uv0 and rhat + vv1 can but doesn't
have to overflow, say for uv0 42UL and vv1 0x8000000000000000UL
it will not (and so we should goto again), while for uv0
0x8000000000000000UL and vv1 0x8000000000000001UL it will (and
we shouldn't goto again).
If uv1 == vv1 && uv0 >= uv1, qhat above would be b + 1, so we
take if (qhat >= b, decrement qhat by 1 (it becomes b), add
vn[n-1] aka vv1 to rhat. But because vv1 has msb set and
rhat in this case is uv0 - vv1, the rhat + vv1 addition
certainly doesn't overflow, because (uv0 - vv1) + vv1 is uv0,
so in the algorithm we goto again, again take if (qhat >= b and
decrement qhat so it finally becomes b - 1, and add vn[n-1]
aka vv1 to rhat again.  But this time I believe it must always
overflow, simply because we added (uv0 - vv1) + vv1 + vv1 and
vv1 has msb set, so already vv1 + vv1 must overflow.  And
because it overflowed, it will not goto again.
So, I believe the following patch implements this correctly, by
subtracting vv1 from uv1:uv0 double-word once, then comparing
again if uv1 >= vv1.  If that is true, subtract vv1 from uv1:uv0
again and add 2 * vv1 to rhat, no __builtin_add_overflow is needed
as we know it always overflowed and so won't goto again.
If after the first subtraction uv1 < vv1, use __builtin_add_overflow
when adding vv1 to rhat, because it can but doesn't have to overflow.

I've added an extra testcase which tests the behavior of all the changed
cases, so it has a case where uv1:uv0 / vv1 is 1:1, where it is
1:0 and rhat + vv1 overflows and where it is 1:0 and rhat + vv1 does not
overflow, and includes tests also from Zdenek's other failing tests.

2024-02-02  Jakub Jelinek  <jakub@redhat.com>

	PR libgcc/113604
	* libgcc2.c (__divmodbitint4): If uv1 >= vv1, subtract
	vv1 from uv1:uv0 once or twice as needed, rather than
	subtracting vv1:vv1.

	* gcc.dg/torture/bitint-53.c: New test.
	* gcc.dg/torture/bitint-55.c: New test.
2024-02-02 22:14:33 +01:00
.github Minor formatting fix for newly-added file from previous commit 2023-11-01 19:28:56 -04:00
c++tools Update copyright years. 2024-01-03 12:19:35 +01:00
config Daily bump. 2024-01-12 00:17:54 +00:00
contrib Daily bump. 2024-01-12 00:17:54 +00:00
fixincludes Daily bump. 2023-11-23 00:18:14 +00:00
gcc libgcc: Fix up _BitInt division [PR113604] 2024-02-02 22:14:33 +01:00
gnattools Update Copyright year in ChangeLog files 2024-01-03 11:35:18 +01:00
gotools Daily bump. 2023-11-04 00:16:45 +00:00
include Daily bump. 2024-01-14 00:17:47 +00:00
INSTALL
libada Update copyright years. 2024-01-03 12:19:35 +01:00
libatomic Daily bump. 2024-01-29 00:18:44 +00:00
libbacktrace Update copyright years. 2024-01-05 08:54:28 +01:00
libcc1 Daily bump. 2024-01-10 00:18:30 +00:00
libcody Update Copyright year in ChangeLog files 2024-01-03 11:35:18 +01:00
libcpp Daily bump. 2024-02-02 00:18:18 +00:00
libdecnumber Update copyright years. 2024-01-03 12:19:35 +01:00
libffi Daily bump. 2023-10-27 00:17:12 +00:00
libgcc libgcc: Fix up _BitInt division [PR113604] 2024-02-02 22:14:33 +01:00
libgfortran Daily bump. 2024-01-16 00:18:46 +00:00
libgm2 Daily bump. 2024-01-19 00:18:21 +00:00
libgo libgo: update configure.ac to upstream GCC 2023-11-30 13:23:53 -08:00
libgomp Daily bump. 2024-02-02 00:18:18 +00:00
libgrust Daily bump. 2024-01-17 00:21:29 +00:00
libiberty Daily bump. 2024-01-14 00:17:47 +00:00
libitm Daily bump. 2024-01-04 00:18:45 +00:00
libobjc Update copyright years. 2024-01-03 12:19:35 +01:00
libphobos testsuite, libphobos: Update link flags [PR112864]. 2024-02-02 09:01:57 +00:00
libquadmath Daily bump. 2024-01-04 00:18:45 +00:00
libsanitizer libsanitizer: Sync fixes for asan interceptors from upstream 2024-01-31 14:49:21 +00:00
libssp Update copyright years. 2024-01-03 12:19:35 +01:00
libstdc++-v3 libstdc++: Make std::function deduction guide support explicit object functions [PR113335] 2024-02-02 13:54:02 +00:00
libvtv Update copyright years. 2024-01-03 12:19:35 +01:00
lto-plugin Update copyright years. 2024-01-03 12:19:35 +01:00
maintainer-scripts Daily bump. 2023-11-14 12:23:39 +00:00
zlib Daily bump. 2023-10-23 00:16:43 +00:00
.dir-locals.el
.gitattributes
.gitignore *: add modern gettext 2023-11-14 00:47:11 +01:00
ABOUT-NLS
ar-lib
ChangeLog Daily bump. 2024-01-30 00:18:41 +00:00
ChangeLog.jit
ChangeLog.tree-ssa
compile
config-ml.in LoongArch: Reimplement multilib build option handling. 2023-09-15 10:42:12 +08:00
config.guess
config.rpath
config.sub
configure build: Add libgrust as compilation modules 2023-12-14 13:58:57 +01:00
configure.ac build: Add libgrust as compilation modules 2023-12-14 13:58:57 +01:00
COPYING
COPYING.LIB
COPYING.RUNTIME
COPYING3
COPYING3.LIB
depcomp
install-sh
libtool-ldflags
libtool.m4 Build: fix error in fixinclude configure 2023-11-22 11:54:33 +01:00
ltgcc.m4
ltmain.sh
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
MAINTAINERS MAINTAINERS: Update my e-mail address. 2024-02-01 22:28:42 -07:00
Makefile.def gccrs: Fix missing build dependency 2024-01-16 16:23:02 +01:00
Makefile.in gccrs: Fix missing build dependency 2024-01-16 16:23:02 +01:00
Makefile.tpl Pass GUILE down to subdirectories 2024-01-09 08:02:31 -07:00
missing
mkdep
mkinstalldirs
move-if-change
multilib.am
README
SECURITY.txt SECURITY.txt: Drop "exploitable" in reference to hardening issues 2024-01-09 10:49:01 -05:00
symlink-tree
test-driver
ylwrap

This directory contains the GNU Compiler Collection (GCC).

The GNU Compiler Collection is free software.  See the files whose
names start with COPYING for copying permission.  The manuals, and
some of the runtime libraries, are under different terms; see the
individual source files for details.

The directory INSTALL contains copies of the installation information
as HTML and plain text.  The source of this information is
gcc/doc/install.texi.  The installation information includes details
of what is included in the GCC sources and what files GCC installs.

See the file gcc/doc/gcc.texi (together with other files that it
includes) for usage and porting information.  An online readable
version of the manual is in the files gcc/doc/gcc.info*.

See http://gcc.gnu.org/bugs/ for how to report bugs usefully.

Copyright years on GCC source files may be listed using range
notation, e.g., 1987-2012, indicating that every year in the range,
inclusive, is a copyrightable year that could otherwise be listed
individually.