This fixes the PR. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard. 2016-09-20 Richard Biener <rguent...@suse.de> PR tree-optimization/77646 * tree-ssa-sccvn.c (visit_reference_op_call): Always value-number a VDEF. * gcc.dg/torture/pr77646.c: New testcase. Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 240255) --- gcc/tree-ssa-sccvn.c (working copy) *************** visit_reference_op_call (tree lhs, gcall *** 3470,3475 **** --- 3577,3586 ---- { if (vnresult->result_vdef && vdef) changed |= set_ssa_val_to (vdef, vnresult->result_vdef); + else if (vdef) + /* If the call was discovered to be pure or const reflect + that as far as possible. */ + changed |= set_ssa_val_to (vdef, vuse_ssa_val (gimple_vuse (stmt))); if (!vnresult->result && lhs) vnresult->result = lhs; Index: gcc/testsuite/gcc.dg/torture/pr77646.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr77646.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr77646.c (working copy) *************** *** 0 **** --- 1,21 ---- + /* { dg-do compile } */ + + struct e { + int (*f)(); + void (*g)(); + } * c; + int a; + void *h(); + typedef struct { struct e j; } k; + int l() { return a; } + const struct e b = {l}; + void m() + { + k *d = h(); + d->j = b; + c = (struct e *)d; + struct e *i = c; + if (i->f(c)) + while (i->f(c)) + i->g(); + }