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