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

            Bug ID: 90231
           Summary: ivopts causes <optimized away> iterator in the loop
           Product: gcc
           Version: 8.3.1
            Status: UNCONFIRMED
          Keywords: wrong-debug
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
                CC: aoliva at gcc dot gnu.org, jakub at gcc dot gnu.org,
                    rguenth at gcc dot gnu.org, rsandifo at gcc dot gnu.org,
                    unassigned at gcc dot gnu.org
        Depends on: 90197
  Target Milestone: ---

+++ This bug was initially created as a clone of Bug #90197 +++

In the PR90197 testcase with -g -O2 ivopts results in bad debug info quality,
at least on x86_64-linux.

__attribute__((noipa))
void
test (unsigned int *dst, unsigned int base, int count)
{
  for (int i = 0; i < count; ++i, base += 15)
    dst[i] = base;
}

int
main (void)
{
  unsigned int dst[100];
  test (dst, 0x4000, 100);
}

Before ivopts pass, the IL is:
  <bb 5> [local count: 105119324]:

  <bb 3> [local count: 955630224]:
  # base_17 = PHI <base_7(D)(5), base_13(6)>
  # i_18 = PHI <0(5), i_12(6)>
  # DEBUG i => i_18
  # DEBUG base => base_17
  # DEBUG BEGIN_STMT
  _1 = (long unsigned int) i_18;
  _2 = _1 * 4;
  _3 = dst_10(D) + _2;
  *_3 = base_17;
  # DEBUG BEGIN_STMT
  i_12 = i_18 + 1;
  # DEBUG i => i_12
  base_13 = base_17 + 15;
  # DEBUG base => base_13
  # DEBUG i => i_12
  # DEBUG base => base_13
  # DEBUG BEGIN_STMT
  if (count_9(D) > i_12)
    goto <bb 6>; [89.00%]
  else
    goto <bb 4>; [11.00%]

  <bb 6> [local count: 850510900]:
  goto <bb 3>; [100.00%]
The IVOPTS pass keeps the base IV and replaces the i IV with a different one:
  <bb 5> [local count: 105119324]:
  ivtmp.11_5 = (unsigned long) dst_10(D);
  _16 = (unsigned int) count_9(D);
  _15 = _16 * 15;
  _14 = base_7(D) + _15;

  <bb 3> [local count: 955630224]:
  # base_17 = PHI <base_7(D)(5), base_13(6)>
  # ivtmp.11_20 = PHI <ivtmp.11_5(5), ivtmp.11_6(6)>
  # DEBUG i => NULL
  # DEBUG base => base_17
  # DEBUG BEGIN_STMT
  _4 = (void *) ivtmp.11_20;
  MEM[base: _4, offset: 0B] = base_17;
  # DEBUG BEGIN_STMT
  # DEBUG D#1 => NULL
  # DEBUG i => D#1
  base_13 = base_17 + 15;
  # DEBUG base => base_13
  # DEBUG i => D#1
  # DEBUG base => base_13
  # DEBUG BEGIN_STMT
  ivtmp.11_6 = ivtmp.11_20 + 4;
  if (base_13 != _14)
    goto <bb 6>; [89.00%]
  else
    goto <bb 4>; [11.00%]

  <bb 6> [local count: 850510900]:
  goto <bb 3>; [100.00%]

The problem is that i => NULL and D#1 => NULL; while we don't have any register
holding the i value at runtime through iterations of the loop, I would hope
that ivopts pass has enough information on how to express one IV from another
IV and should be able to emit that information in a form of debug stmts into
the IL.  In this case, I guess it can either say that the i at the beginning of
the loop is either (int) ((ivtmp.11_20 - (unsigned long) dst_10(D)) / 4), or
(int) ((base_17 - base_7(D)) / 15).  Even if those dst_10(D) or base_7(D)
aren't really used later in the function (that is the case of both in this
function), those can be still live in some register (e.g. count argument is
live in a register) or memory and even if it doesn't, in some cases it could be
expressed through DW_OP_entry_value (the callers sets those up in this
testcase).
It could be as simple as replacing the debug uses of i_18 (the IV that is going
away) with a debug temp decl, either
  # DEBUG D#2 = ivtmp.11_20 - ivtmp.11_5
  # DEBUG D#3 = D#2 / 4
  # DEBUG i => D#3
or similar and let the normal debug handling code do the rest when ivtmp.11_5
is no longer needed or optimized away etc.
I guess one needs to properly think if the to be removed IV is actually
properly expressible through some other IV, in the ivtmp case when that one is
64-bit and the IV is 32-bit and division just by 4 that is clearly the case, in
other cases we could use assumption that signed integer overflow is UB etc.


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90197
[Bug 90197] [8/9 Regression] Cannot step through simple loop at -O -g

Reply via email to