This fixes the case where we only late during insertion are able to simplify an expression (when we re-instantiated range-info on all SSA names). We can't do anything here but give up since we'd end up with a SSA name with two values which for sure will eventually end up confusing elimination.
Hopefully for GCC 8 I can fix all this by re-writing SCCVN to RPO style iteration. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2017-03-02 Richard Biener <rguent...@suse.de> PR tree-optimization/79777 * tree-ssa-pre.c (eliminate_insert): Give up if we simplify the to insert expression to sth existing. * gcc.dg/torture/pr79777.c: New testcase. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 245803) --- gcc/tree-ssa-pre.c (working copy) *************** eliminate_insert (gimple_stmt_iterator * *** 4133,4143 **** else res = gimple_build (&stmts, gimple_assign_rhs_code (stmt), TREE_TYPE (val), leader); ! gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); ! VN_INFO_GET (res)->valnum = val; ! if (TREE_CODE (leader) == SSA_NAME) ! gimple_set_plf (SSA_NAME_DEF_STMT (leader), NECESSARY, true); pre_stats.insertions++; if (dump_file && (dump_flags & TDF_DETAILS)) --- 4133,4174 ---- else res = gimple_build (&stmts, gimple_assign_rhs_code (stmt), TREE_TYPE (val), leader); ! if (TREE_CODE (res) != SSA_NAME ! || SSA_NAME_IS_DEFAULT_DEF (res) ! || gimple_bb (SSA_NAME_DEF_STMT (res))) ! { ! gimple_seq_discard (stmts); ! /* During propagation we have to treat SSA info conservatively ! and thus we can end up simplifying the inserted expression ! at elimination time to sth not defined in stmts. */ ! /* But then this is a redundancy we failed to detect. Which means ! res now has two values. That doesn't play well with how ! we track availability here, so give up. */ ! if (dump_file && (dump_flags & TDF_DETAILS)) ! { ! if (TREE_CODE (res) == SSA_NAME) ! res = eliminate_avail (res); ! if (res) ! { ! fprintf (dump_file, "Failed to insert expression for value "); ! print_generic_expr (dump_file, val, 0); ! fprintf (dump_file, " which is really fully redundant to "); ! print_generic_expr (dump_file, res, 0); ! fprintf (dump_file, "\n"); ! } ! } ! ! return NULL_TREE; ! } ! else ! { ! gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); ! VN_INFO_GET (res)->valnum = val; ! ! if (TREE_CODE (leader) == SSA_NAME) ! gimple_set_plf (SSA_NAME_DEF_STMT (leader), NECESSARY, true); ! } pre_stats.insertions++; if (dump_file && (dump_flags & TDF_DETAILS)) Index: gcc/testsuite/gcc.dg/torture/pr79777.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr79777.c (nonexistent) --- gcc/testsuite/gcc.dg/torture/pr79777.c (working copy) *************** *** 0 **** --- 1,38 ---- + /* { dg-do compile } */ + + typedef unsigned short __u16; + typedef unsigned int __u32; + typedef unsigned char u8; + typedef unsigned int u32; + typedef __u16 __le16; + typedef __u32 __le32; + typedef u32 secno; + struct bplus_internal_node { + __le32 file_secno; + __le32 down; + }; + struct bplus_header { + u8 n_used_nodes; + __le16 first_free; + union { + struct bplus_internal_node internal[0]; + } + u; + }; + + __u16 __fswab16(__u16 val); + __u32 __fswab32(__u32 val); + void hpfs_ea_remove (__u32); + + void hpfs_truncate_btree(secno f, int fno, unsigned secs, struct bplus_header *btree) + { + int i, j; + for (i = 0; i < btree->n_used_nodes; i++) + if ((__builtin_constant_p((__u32)(( __u32)(__le32)(btree->u.internal[i].file_secno))) ? ((__u32)( (((__u32)(( __u32)(__le32)(btree->u.internal[i].file_secno)) & (__u32)0x000000ffUL) << 24) | (((__u32)(( __u32)(__le32)(btree->u.internal[i].file_secno)) & (__u32)0x0000ff00UL) << 8) | (((__u32)(( __u32)(__le32)(btree->u.internal[i].file_secno)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(( __u32)(__le32)(btree->u.internal[i].file_secno)) & (__u32)0xff000000UL) >> 24))) : __fswab32(( __u32)(__le32)(btree->u.internal[i].file_secno))) >= secs) goto f; + return; + f: + for (j = i + 1; j < btree->n_used_nodes; j++) + hpfs_ea_remove((__builtin_constant_p((__u32)(( __u32)(__le32)(btree->u.internal[j].down))) ? ((__u32)( (((__u32)(( __u32)(__le32)(btree->u.internal[j].down)) & (__u32)0x000000ffUL) << 24) | (((__u32)(( __u32)(__le32)(btree->u.internal[j].down)) & (__u32)0x0000ff00UL) << 8) | (((__u32)(( __u32)(__le32)(btree->u.internal[j].down)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(( __u32)(__le32)(btree->u.internal[j].down)) & (__u32)0xff000000UL) >> 24))) : __fswab32(( __u32)(__le32)(btree->u.internal[j].down)))); + btree->n_used_nodes = i + 1; + btree->first_free = (( __le16)(__builtin_constant_p((__u16)((8 + 8 * btree->n_used_nodes))) ? ((__u16)( (((__u16)((8 + 8 * btree->n_used_nodes)) & (__u16)0x00ffU) << 8) | (((__u16)((8 + 8 * btree->n_used_nodes)) & (__u16)0xff00U) >> 8))) : __fswab16((8 + 8 * btree->n_used_nodes)))); + }