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

--- Comment #1 from liu zhenyu <lzy20000419 at outlook dot com> ---
Created attachment 65982
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65982&action=edit
testcase

I think this comes from r16 commit 952e145796da ("phiprop: Allow non-trapping
loads to be proped back into the loop", PR60183). Before it, phiprop only
replaced loads in blocks that post-dominate the PHI. Now it skips that check
when no PHI argument could trap.

gcc/tree-ssa-phiprop.cc (trunk), propagate_with_phi:

418           if (TREE_CODE (arg) == ADDR_EXPR)
419             {
420               tree decl = TREE_OPERAND (arg, 0);
421               if (!canpossible_trap)
422                 canpossible_trap = tree_could_trap_p (decl);
423             }
...
499           if ((canpossible_trap || aggregate)
500               && !dominated_by_p (CDI_POST_DOMINATORS,
501                                   bb, gimple_bb (use_stmt)))
502             delay = true;

tree_could_trap_p (decl) only asks whether the decl itself can be missing, for
example a weak symbol. It does not look at the load that will be inserted on
the edge, MEM_REF <int> (&ch, 0), which is 4 bytes from a 1-byte object. The
same happens with an in-bounds ARRAY_REF argument like &buf[3] and a 4-byte
load:


char buf[4] = { 1, 2, 3, 4 };
int iv = 7;
__attribute__((noipa)) int f (int c, int d)
{
  char *p = c ? &buf[3] : (char *) &iv;
  if (d)
    { int v; __builtin_memcpy (&v, p, sizeof v); return v; }
  return 0;
}
int main (void) { volatile int c = 1, d = 0; return f (c, d); }
(14.2 doesn't have this code. It always requires post-dominance.)

Suggested fix: do the trap check per use, on the reference that will actually
be inserted. For example, use tree_could_trap_p (build2 (MEM_REF, TREE_TYPE
(rhs), arg, TREE_OPERAND (rhs, 1))), which compares the access extent with
DECL_SIZE. I haven't built or tested this fix.

Reply via email to