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

            Bug ID: 128515
           Summary: [14/15/16/17 Regression] wrong code at -O2:
                    subtract-with-borrow on a 33-bit unsigned type becomes
                    .USUBC and is not reduced to 33 bits since r14-3541
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jeffchen006 at gmail dot com
  Target Milestone: ---
            Target: x86_64-pc-linux-gnu

Test 1 (bit-fields):

int printf(const char *, ...);

struct S { unsigned long long a : 33, b : 33; };
struct S x = { 0, 0 }, y = { 1, 0 };

int main(void)
{
  __typeof(x.a + 0) r0 = x.a - y.a;
  __typeof(x.a + 0) c = r0 > x.a;
  __typeof(x.a + 0) r1 = x.b - y.b - c;
  printf("%llx %llx\n", (unsigned long long)r0, (unsigned long long)r1);
  return 0;
}

Test 2 (_BitInt):

int printf(const char *, ...);

typedef unsigned _BitInt(33) T;
T a0 = 0, a1 = 0, b0 = 1, b1 = 0;

int main(void)
{
  T r0 = a0 - b0;
  T c = r0 > a0;
  T r1 = a1 - b1 - c;
  printf("%llx %llx\n", (unsigned long long)r0, (unsigned long long)r1);
  return 0;
}

$ gcc -O0 t.c && ./a.out
1ffffffff 1ffffffff
$ gcc -O2 t.c && ./a.out
ffffffffffffffff ffffffffffffffff

Both tests give this output.
Expected 1ffffffff: 0 - 1 in a 33-bit unsigned type is 0x1ffffffff.

Cause: widening_mul makes .USUBC from the subtract-with-borrow chain.
match_uaddc_usubc (tree-ssa-math-opts.cc) does not check that the type has the
precision of its mode. The DImode usubc5 pattern is used, and the result is
never reduced to 33 bits. Add-with-carry (.UADDC) has the same problem.

Since GCC 14: test 1 is correct on 13.4 and wrong on 14.3, 15.2, 16.2 and
trunk. First bad commit: r14-3541-ga7aec76a74d (improved uaddc/usubc pattern
matching, PR111209).


UBSan and ASan are clean at -O0.
gcc version 17.0.0 20261029 (experimental), r17-5747-g85867b0c935,
x86_64-pc-linux-gnu

Reply via email to