https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82274

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
internal-fn.c implements here whatever we have written in libgcc2.c for
__mulvti3 (for 64-bit arches) or __mulvdi3 (for 32-bit arches).
And it seems this is (hopefully the only) incorrectly handled special case.
That routine first handles the case where both operands are within range of
sign-extended half-sized integers (never overflows), then when one of them is
and the other is arbitrary (or vice versa, mul is commutative) - this one needs
2 multiplications and sometimes overflows, sometimes doesn't, then when both of
them are within the range of max signed half type + 1 to max unsigned half
type, then when one of them is in that range and other is in range of minus
(max unsigned half type + 1) to (min signed half type - 1) and finally when
both are of the latter kind (everything else is always overflow).
That last case is:
                  if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1)
                    {
                      DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
                                    * (UDWtype) (UWtype) vv.s.low};

                      ww.s.high -= uu.s.low;
                      ww.s.high -= vv.s.low;
                      if (__builtin_expect (ww.s.high >= 0, 1))
                        return ww.ll;
                    }
If both uu.s.low == vv.s.low == 0, then we return 0 even when there is
overflow.
Wonder if ww.s.high >= 0 && ww.ll wouldn't be sufficient.

Reply via email to