This fixes PR67889. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard. 2015-10-09 Richard Biener <rguent...@suse.de> PR tree-optimization/67891 * gimple-match.h (gimple_simplified_result_is_gimple_val): New helper. (gimple_resimplify1): Declare. (gimple_resimplify2): Likewise. (gimple_resimplify3): Likewise. * gimple-match-head.c (gimple_resimplify1): Export. (gimple_resimplify2): Likewise. (gimple_resimplify3): Likewise. (maybe_push_res_to_seq): Use gimple_simplified_result_is_gimple_val. * gimple-fold.c (gimple_fold_stmt_to_constant_1): Likewise. * tree-ssa-sccvn.c (visit_reference_op_load): Use gimple_resimplify1 to avoid creating stmts without VN info. * gcc.dg/tree-ssa/pr67891.c: New testcase. Index: gcc/gimple-match.h =================================================================== *** gcc/gimple-match.h (revision 228594) --- gcc/gimple-match.h (working copy) *************** private: *** 40,49 **** --- 40,67 ---- int rep; }; + /* Return whether OPS[0] with CODE is a non-expression result and + a gimple value. */ + + inline bool + gimple_simplified_result_is_gimple_val (code_helper code, tree *ops) + { + return (code.is_tree_code () + && (TREE_CODE_LENGTH ((tree_code) code) == 0 + || ((tree_code) code) == ADDR_EXPR) + && is_gimple_val (ops[0])); + } + extern tree (*mprts_hook) (code_helper, tree, tree *); bool gimple_simplify (gimple *, code_helper *, tree *, gimple_seq *, tree (*)(tree), tree (*)(tree)); + bool gimple_resimplify1 (gimple_seq *, code_helper *, tree, tree *, + tree (*)(tree)); + bool gimple_resimplify2 (gimple_seq *, code_helper *, tree, tree *, + tree (*)(tree)); + bool gimple_resimplify3 (gimple_seq *, code_helper *, tree, tree *, + tree (*)(tree)); tree maybe_push_res_to_seq (code_helper, tree, tree *, gimple_seq *, tree res = NULL_TREE); void maybe_build_generic_op (enum tree_code, tree, tree *, tree, tree); Index: gcc/gimple-match-head.c =================================================================== *** gcc/gimple-match-head.c (revision 228594) --- gcc/gimple-match-head.c (working copy) *************** constant_for_folding (tree t) *** 83,89 **** *RES_CODE and *RES_OPS with a simplified and/or canonicalized result and returns whether any change was made. */ ! static bool gimple_resimplify1 (gimple_seq *seq, code_helper *res_code, tree type, tree *res_ops, tree (*valueize)(tree)) --- 83,89 ---- *RES_CODE and *RES_OPS with a simplified and/or canonicalized result and returns whether any change was made. */ ! bool gimple_resimplify1 (gimple_seq *seq, code_helper *res_code, tree type, tree *res_ops, tree (*valueize)(tree)) *************** gimple_resimplify1 (gimple_seq *seq, *** 139,145 **** *RES_CODE and *RES_OPS with a simplified and/or canonicalized result and returns whether any change was made. */ ! static bool gimple_resimplify2 (gimple_seq *seq, code_helper *res_code, tree type, tree *res_ops, tree (*valueize)(tree)) --- 139,145 ---- *RES_CODE and *RES_OPS with a simplified and/or canonicalized result and returns whether any change was made. */ ! bool gimple_resimplify2 (gimple_seq *seq, code_helper *res_code, tree type, tree *res_ops, tree (*valueize)(tree)) *************** gimple_resimplify2 (gimple_seq *seq, *** 208,214 **** *RES_CODE and *RES_OPS with a simplified and/or canonicalized result and returns whether any change was made. */ ! static bool gimple_resimplify3 (gimple_seq *seq, code_helper *res_code, tree type, tree *res_ops, tree (*valueize)(tree)) --- 208,214 ---- *RES_CODE and *RES_OPS with a simplified and/or canonicalized result and returns whether any change was made. */ ! bool gimple_resimplify3 (gimple_seq *seq, code_helper *res_code, tree type, tree *res_ops, tree (*valueize)(tree)) *************** maybe_push_res_to_seq (code_helper rcode *** 308,316 **** if (rcode.is_tree_code ()) { if (!res ! && (TREE_CODE_LENGTH ((tree_code) rcode) == 0 ! || ((tree_code) rcode) == ADDR_EXPR) ! && is_gimple_val (ops[0])) return ops[0]; if (mprts_hook) { --- 308,314 ---- if (rcode.is_tree_code ()) { if (!res ! && gimple_simplified_result_is_gimple_val (rcode, ops)) return ops[0]; if (mprts_hook) { Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c (revision 228594) --- gcc/gimple-fold.c (working copy) *************** gimple_fold_stmt_to_constant_1 (gimple * *** 4926,4935 **** if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize)) { tree res = NULL_TREE; ! if (rcode.is_tree_code () ! && (TREE_CODE_LENGTH ((tree_code) rcode) == 0 ! || ((tree_code) rcode) == ADDR_EXPR) ! && is_gimple_val (ops[0])) res = ops[0]; else if (mprts_hook) res = mprts_hook (rcode, gimple_expr_type (stmt), ops); --- 4932,4938 ---- if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize)) { tree res = NULL_TREE; ! if (gimple_simplified_result_is_gimple_val (rcode, ops)) res = ops[0]; else if (mprts_hook) res = mprts_hook (rcode, gimple_expr_type (stmt), ops); Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 228594) --- gcc/tree-ssa-sccvn.c (working copy) *************** visit_reference_op_load (tree lhs, tree *** 3043,3080 **** of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result). So first simplify and lookup this expression to see if it is already available. */ - gimple_seq stmts = NULL; mprts_hook = vn_lookup_simplify_result; ! tree val = gimple_simplify (VIEW_CONVERT_EXPR, TREE_TYPE (op), ! result, &stmts, vn_valueize); mprts_hook = NULL; ! if (!val) { ! val = vn_nary_op_lookup_pieces (1, VIEW_CONVERT_EXPR, ! TREE_TYPE (op), &result, NULL); if (!val) { ! val = make_ssa_name (TREE_TYPE (op)); ! gimple *new_stmt = gimple_build_assign (val, VIEW_CONVERT_EXPR, ! build1 (VIEW_CONVERT_EXPR, ! TREE_TYPE (op), ! result)); ! gimple_seq_add_stmt_without_update (&stmts, new_stmt); } } ! if (gimple_seq_empty_p (stmts)) ! /* The expression is already available. */ ! result = val; ! else { - gcc_assert (gimple_seq_singleton_p (stmts)); /* The expression is not yet available, value-number lhs to the new SSA_NAME we created. */ - result = val; /* Initialize value-number information properly. */ VN_INFO_GET (result)->valnum = result; VN_INFO (result)->value_id = get_next_value_id (); ! VN_INFO (result)->expr = stmts; VN_INFO (result)->needs_insertion = true; /* As all "inserted" statements are singleton SCCs, insert to the valid table. This is strictly needed to --- 3089,3129 ---- of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result). So first simplify and lookup this expression to see if it is already available. */ mprts_hook = vn_lookup_simplify_result; ! code_helper rcode = VIEW_CONVERT_EXPR; ! tree ops[3] = { result }; ! bool res = gimple_resimplify1 (NULL, &rcode, TREE_TYPE (op), ops, ! vn_valueize); mprts_hook = NULL; ! gimple *new_stmt = NULL; ! if (res ! && gimple_simplified_result_is_gimple_val (rcode, ops)) ! /* The expression is already available. */ ! result = ops[0]; ! else { ! tree val = vn_lookup_simplify_result (rcode, TREE_TYPE (op), ops); if (!val) { ! gimple_seq stmts = NULL; ! result = maybe_push_res_to_seq (rcode, TREE_TYPE (op), ops, ! &stmts); ! gcc_assert (result && gimple_seq_singleton_p (stmts)); ! new_stmt = gimple_seq_first_stmt (stmts); } + else + /* The expression is already available. */ + result = val; } ! if (new_stmt) { /* The expression is not yet available, value-number lhs to the new SSA_NAME we created. */ /* Initialize value-number information properly. */ VN_INFO_GET (result)->valnum = result; VN_INFO (result)->value_id = get_next_value_id (); ! gimple_seq_add_stmt_without_update (&VN_INFO (result)->expr, ! new_stmt); VN_INFO (result)->needs_insertion = true; /* As all "inserted" statements are singleton SCCs, insert to the valid table. This is strictly needed to *************** visit_reference_op_load (tree lhs, tree *** 3086,3103 **** if (current_info == optimistic_info) { current_info = valid_info; ! vn_nary_op_insert_stmt (gimple_seq_first_stmt (stmts), result); current_info = optimistic_info; } else ! vn_nary_op_insert_stmt (gimple_seq_first_stmt (stmts), result); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Inserting name "); print_generic_expr (dump_file, result, 0); fprintf (dump_file, " for expression "); ! print_gimple_expr (dump_file, gimple_seq_first_stmt (stmts), ! 0, TDF_SLIM); fprintf (dump_file, "\n"); } } --- 3135,3151 ---- if (current_info == optimistic_info) { current_info = valid_info; ! vn_nary_op_insert_stmt (new_stmt, result); current_info = optimistic_info; } else ! vn_nary_op_insert_stmt (new_stmt, result); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Inserting name "); print_generic_expr (dump_file, result, 0); fprintf (dump_file, " for expression "); ! print_gimple_expr (dump_file, new_stmt, 0, TDF_SLIM); fprintf (dump_file, "\n"); } } Index: gcc/testsuite/gcc.dg/tree-ssa/pr67891.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/pr67891.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/pr67891.c (working copy) *************** *** 0 **** --- 1,17 ---- + /* { dg-do compile } */ + /* { dg-options "-O -fdump-tree-fre1" } */ + + unsigned int a, *b; + unsigned short c; + int d; + + void + fn1 () + { + b = &d; + *b = c = a; + *b = d; + } + + /* We should remove all loads but that from a. */ + /* { dg-final { scan-tree-dump-not "= \[dbc\];" "fre1" } } */