https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68465
Bug ID: 68465 Summary: pass_lim doesn't detect identical loop entry conditions Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: vries at gcc dot gnu.org Target Milestone: --- Consider testcase test.c: ... int a; int *p = &a; int foo (int n) { for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) *p += j + i; return a; } ... Compiled like this: ... $ gcc -O2 -S -fdump-tree-all-details test.c -fno-tree-pre -fno-tree-dominator-opts ... Before pass_lim, we have: ... foo (int n) { int j; int i; int * p.0_7; int _9; int _10; int _11; int _15; <bb 2>: if (n_6(D) > 0) goto <bb 7>; else goto <bb 8>; <bb 7>: goto <bb 5>; <bb 11>: <bb 5>: outer loop header # i_21 = PHI <i_14(11), 0(7)> if (n_6(D) > 0) goto <bb 13>; else goto <bb 14>; <bb 14>: goto <bb 4>; <bb 13>: goto <bb 3>; <bb 9>: inner loop latch <bb 3>: inner loop header # j_22 = PHI <j_13(9), 0(13)> p.0_7 = p; _9 = *p.0_7; _10 = i_21 + j_22; _11 = _9 + _10; *p.0_7 = _11; j_13 = j_22 + 1; if (n_6(D) > j_13) goto <bb 9>; else goto <bb 10>; <bb 10>: <bb 4>: outer loop latch i_14 = i_21 + 1; if (n_6(D) > i_14) goto <bb 11>; else goto <bb 12>; <bb 12>: goto <bb 6>; <bb 8>: <bb 6>: _15 = a; return _15; } ... The store motion in pass_lim manages to hoist the store out of the inner loop, but not the outer loop. When doing store_motion_loop for the outer loop, can_sm_ref_p fails here: ... if ((tree_could_trap_p (ref->mem.ref) || (DECL_P (base) && TREE_READONLY (base))) && !ref_always_accessed_p (loop, ref, true)) return false; ... because tree_could_trap_p (ref->mem.ref) is true, and ref_always_accessed_p (loop, ref, true) is false. The fact that if you enter the first loop, you enter the second loop (because they have identical loop entry conditions) is not taken into account.