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

            Bug ID: 122104
           Summary: Incorrect range after widening_mul
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kristerw at gcc dot gnu.org
  Target Milestone: ---

The widening_mul pass makes the following function more UB when compiled for
x86_64 with -O2 or higher:

int
f21 (int x)
{
  int r = (unsigned) x * 35;
  return x && ((unsigned) r / x) != 35U;
}


The IR before the widening_mul pass looks like

int f21 (int x)
{
  unsigned int x.0_1;
  unsigned int _2;
  unsigned int _3;
  int iftmp.1_4;
  _Bool _7;
  int _8;

  <bb 2> :
  if (x_5(D) != 0)
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 3> :
  x.0_1 = (unsigned int) x_5(D);
  _2 = x.0_1 * 35;
  _3 = _2 / x.0_1;
  _7 = _3 != 35;
  _8 = (int) _7;

  <bb 4> :
  # iftmp.1_4 = PHI <_8(3), 0(2)>
  return iftmp.1_4;
}

where x.0_1 has a range:
  x.0_1 = [irange] unsigned int [1, +INF]


The widening_mul pass changes the code to

int f21 (int x)
{
  unsigned int x.0_1;
  unsigned int _2;
  _Bool _7;
  int _8;
  __complex__ unsigned int _9;
  unsigned int _10;

  <bb 2> :
  x.0_1 = (unsigned int) x_5(D);
  _9 = .MUL_OVERFLOW (x.0_1, 35);
  _2 = REALPART_EXPR <_9>;
  _10 = IMAGPART_EXPR <_9>;
  _7 = _10 != 0;
  _8 = (int) _7;
  return _8;
}

where x.0_1 keeps the range:
  x.0_1 = [irange] unsigned int [1, +INF]
which is incorrect now when the if-statement has been removed.

Reply via email to