This backports a piece of 2012-09-24 Richard Guenther <rguent...@suse.de>
* tree-ssa-pre.c (bitmap_find_leader, create_expression_by_pieces, find_or_generate_expression): Remove dominating stmt argument. (find_leader_in_sets, phi_translate_1, bitmap_find_leader, create_component_ref_by_pieces_1, create_component_ref_by_pieces, do_regular_insertion, do_partial_partial_insertion): Adjust. (compute_avail): Do not set uids. to the 4.7 branch. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the branch (and the testcase added to 4.8, 4.9 and trunk). Richard. 2014-05-06 Richard Biener <rguent...@suse.de> PR tree-optimization/57864 * tree-ssa-pre.c (phi_translate_1): Backport NAME case simplification from mainline. Do not lookup the VN value-number here. * gcc.dg/torture/pr57864.c: New testcase. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 210104) --- gcc/tree-ssa-pre.c (working copy) *************** phi_translate_1 (pre_expr expr, bitmap_s *** 1756,1794 **** case NAME: { - gimple phi = NULL; - edge e; - gimple def_stmt; tree name = PRE_EXPR_NAME (expr); ! ! def_stmt = SSA_NAME_DEF_STMT (name); if (gimple_code (def_stmt) == GIMPLE_PHI && gimple_bb (def_stmt) == phiblock) - phi = def_stmt; - else - return expr; - - e = find_edge (pred, gimple_bb (phi)); - if (e) { ! tree def = PHI_ARG_DEF (phi, e->dest_idx); ! pre_expr newexpr; ! ! if (TREE_CODE (def) == SSA_NAME) ! def = VN_INFO (def)->valnum; /* Handle constant. */ if (is_gimple_min_invariant (def)) return get_or_alloc_expr_for_constant (def); ! if (TREE_CODE (def) == SSA_NAME && ssa_undefined_value_p (def)) ! return NULL; ! ! newexpr = get_or_alloc_expr_for_name (def); ! return newexpr; } } - return expr; default: gcc_unreachable (); --- 1756,1781 ---- case NAME: { tree name = PRE_EXPR_NAME (expr); ! gimple def_stmt = SSA_NAME_DEF_STMT (name); ! /* If the SSA name is defined by a PHI node in this block, ! translate it. */ if (gimple_code (def_stmt) == GIMPLE_PHI && gimple_bb (def_stmt) == phiblock) { ! edge e = find_edge (pred, gimple_bb (def_stmt)); ! tree def = PHI_ARG_DEF (def_stmt, e->dest_idx); /* Handle constant. */ if (is_gimple_min_invariant (def)) return get_or_alloc_expr_for_constant (def); ! return get_or_alloc_expr_for_name (def); } + /* Otherwise return it unchanged - it will get cleaned if its + value is not available in PREDs AVAIL_OUT set of expressions. */ + return expr; } default: gcc_unreachable (); Index: gcc/testsuite/gcc.dg/torture/pr57864.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr57864.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr57864.c (working copy) *************** *** 0 **** --- 1,37 ---- + /* { dg-do compile } */ + + union U { + double val; + union U *ptr; + }; + + union U *d; + double a; + int b; + int c; + + static void fn1(union U *p1, int p2, _Bool p3) + { + union U *e; + + if (p2 == 0) + a = ((union U*)((unsigned long)p1 & ~1))->val; + + if (b) { + e = p1; + } else if (c) { + e = ((union U*)((unsigned long)p1 & ~1))->ptr; + d = e; + } else { + e = 0; + d = ((union U*)0)->ptr; + } + + fn1 (e, 0, 0); + fn1 (0, 0, p3); + } + + void fn2 (void) + { + fn1 (0, 0, 0); + }