From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 105746 invoked by alias); 30 Sep 2015 13:12:00 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 105732 invoked by uid 89); 30 Sep 2015 13:11:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL,BAYES_50,KAM_ASCII_DIVIDERS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Wed, 30 Sep 2015 13:11:56 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 91AAFAB9D for ; Wed, 30 Sep 2015 13:11:51 +0000 (UTC) Date: Wed, 30 Sep 2015 13:37:00 -0000 From: Richard Biener To: gcc-patches@gcc.gnu.org Subject: [PATCH][25/25] Remove GENERIC stmt combining from SCCVN Message-ID: User-Agent: Alpine 2.11 (LSU 23 2013-08-11) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-SW-Source: 2015-09/txt/msg02346.txt.bz2 This is the last patch in the series and it finally ditches the stmt combining code from SCCVN which uses GENERIC. I've been sitting on this for a while because of the "bad" interface that new mprts_hook is but I couldn't think of a better way than completely refactoring stmt folding into more C++ (and I'm not even sure how that end result would look like). So rather than pondering on this forever the following patch goes forward. Net result is that there will be hopefully no regressions (I know about a few corner cases I found with plastering the code with asserts but I do not consider them important) but progression both with regarding to compile-time / memory-use and optimization (because the new code is strictly more powerful, not relying on the has_constants heuristic). This is also the last major piece that was sitting on the match-and-simplify branch. Bootstrapped on x86_64-unknown-linux-gnu, re-testing in progress. Richard. 2015-09-30 Richard Biener * gimple-match.h (mprts_hook): Declare. * gimple-match.head.c (mprts_hook): Define. (maybe_push_res_to_seq): Use new hook. * gimple-fold.c (gimple_fold_stmt_to_constant_1): Likewise. * tree-ssa-sccvn.h (vn_ssa_aux::expr): Change to a gimple_seq. (vn_ssa_aux::has_constants): Remove. * tree-ssa-sccvn.c: Include gimple-match.h. (VN_INFO_GET): Assert we don't re-use SSA names. (vn_get_expr_for): Remove. (expr_has_constants): Likewise. (stmt_has_constants): Likewise. (simplify_binary_expression): Likewise. (simplify_unary_expression): Likewise. (vn_lookup_simplify_result): New hook. (visit_copy): Adjust. (visit_reference_op_call): Likewise. (visit_phi): Likewise. (visit_use): Likewise. (process_scc): Likewise. (init_scc_vn): Likewise. (visit_reference_op_load): Likewise. Use match-and-simplify and a gimple seq for inserted expressions. (try_to_simplify): Remove GENERIC stmt combining code. (sccvn_dom_walker::before_dom_children): Use match-and-simplify. * tree-ssa-pre.c (eliminate_insert): Adjust. (eliminate_dom_walker::before_dom_children): Likewise. Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c.orig 2015-09-30 14:49:24.613211956 +0200 --- gcc/tree-ssa-sccvn.c 2015-09-30 14:58:48.018555783 +0200 *************** along with GCC; see the file COPYING3. *** 58,63 **** --- 58,64 ---- #include "domwalk.h" #include "cgraph.h" #include "gimple-iterator.h" + #include "gimple-match.h" /* This algorithm is based on the SCC algorithm presented by Keith Cooper and L. Taylor Simpson in "SCC-Based Value numbering" *************** VN_INFO_GET (tree name) *** 401,406 **** --- 402,409 ---- { vn_ssa_aux_t newinfo; + gcc_assert (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length () + || vn_ssa_aux_table[SSA_NAME_VERSION (name)] == NULL); newinfo = XOBNEW (&vn_ssa_aux_obstack, struct vn_ssa_aux); memset (newinfo, 0, sizeof (struct vn_ssa_aux)); if (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ()) *************** VN_INFO_GET (tree name) *** 410,501 **** } - /* Get the representative expression for the SSA_NAME NAME. Returns - the representative SSA_NAME if there is no expression associated with it. */ - - tree - vn_get_expr_for (tree name) - { - vn_ssa_aux_t vn = VN_INFO (name); - gimple *def_stmt; - tree expr = NULL_TREE; - enum tree_code code; - - if (vn->valnum == VN_TOP) - return name; - - /* If the value-number is a constant it is the representative - expression. */ - if (TREE_CODE (vn->valnum) != SSA_NAME) - return vn->valnum; - - /* Get to the information of the value of this SSA_NAME. */ - vn = VN_INFO (vn->valnum); - - /* If the value-number is a constant it is the representative - expression. */ - if (TREE_CODE (vn->valnum) != SSA_NAME) - return vn->valnum; - - /* Else if we have an expression, return it. */ - if (vn->expr != NULL_TREE) - return vn->expr; - - /* Otherwise use the defining statement to build the expression. */ - def_stmt = SSA_NAME_DEF_STMT (vn->valnum); - - /* If the value number is not an assignment use it directly. */ - if (!is_gimple_assign (def_stmt)) - return vn->valnum; - - /* Note that we can valueize here because we clear the cached - simplified expressions after each optimistic iteration. */ - code = gimple_assign_rhs_code (def_stmt); - switch (TREE_CODE_CLASS (code)) - { - case tcc_reference: - if ((code == REALPART_EXPR - || code == IMAGPART_EXPR - || code == VIEW_CONVERT_EXPR) - && TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (def_stmt), - 0)) == SSA_NAME) - expr = fold_build1 (code, - gimple_expr_type (def_stmt), - vn_valueize (TREE_OPERAND - (gimple_assign_rhs1 (def_stmt), 0))); - break; - - case tcc_unary: - expr = fold_build1 (code, - gimple_expr_type (def_stmt), - vn_valueize (gimple_assign_rhs1 (def_stmt))); - break; - - case tcc_binary: - expr = fold_build2 (code, - gimple_expr_type (def_stmt), - vn_valueize (gimple_assign_rhs1 (def_stmt)), - vn_valueize (gimple_assign_rhs2 (def_stmt))); - break; - - case tcc_exceptional: - if (code == CONSTRUCTOR - && TREE_CODE - (TREE_TYPE (gimple_assign_rhs1 (def_stmt))) == VECTOR_TYPE) - expr = gimple_assign_rhs1 (def_stmt); - break; - - default:; - } - if (expr == NULL_TREE) - return vn->valnum; - - /* Cache the expression. */ - vn->expr = expr; - - return expr; - } - /* Return the vn_kind the expression computed by the stmt should be associated with. */ --- 413,418 ---- *************** vn_nary_op_lookup_stmt (gimple *stmt, vn *** 2685,2690 **** --- 2602,2619 ---- return vn_nary_op_lookup_1 (vno1, vnresult); } + /* Hook for maybe_push_res_to_seq, lookup the expression in the VN tables. */ + + static tree + vn_lookup_simplify_result (code_helper rcode, tree type, tree *ops) + { + if (!rcode.is_tree_code ()) + return NULL_TREE; + vn_nary_op_t vnresult = NULL; + return vn_nary_op_lookup_pieces (TREE_CODE_LENGTH ((tree_code) rcode), + (tree_code) rcode, type, ops, &vnresult); + } + /* Allocate a vn_nary_op_t with LENGTH operands on STACK. */ static vn_nary_op_t *************** defs_to_varying (gimple *stmt) *** 3047,3066 **** return changed; } - static bool expr_has_constants (tree expr); - /* Visit a copy between LHS and RHS, return true if the value number changed. */ static bool visit_copy (tree lhs, tree rhs) { ! /* The copy may have a more interesting constant filled expression ! (we don't, since we know our RHS is just an SSA name). */ ! VN_INFO (lhs)->has_constants = VN_INFO (rhs)->has_constants; ! VN_INFO (lhs)->expr = VN_INFO (rhs)->expr; ! ! /* And finally valueize. */ rhs = SSA_VAL (rhs); return set_ssa_val_to (lhs, rhs); --- 2976,2988 ---- return changed; } /* Visit a copy between LHS and RHS, return true if the value number changed. */ static bool visit_copy (tree lhs, tree rhs) { ! /* Valueize. */ rhs = SSA_VAL (rhs); return set_ssa_val_to (lhs, rhs); *************** visit_reference_op_call (tree lhs, gcall *** 3111,3122 **** vnresult->result = lhs; if (vnresult->result && lhs) ! { ! changed |= set_ssa_val_to (lhs, vnresult->result); ! ! if (VN_INFO (vnresult->result)->has_constants) ! VN_INFO (lhs)->has_constants = true; ! } } else { --- 3033,3039 ---- vnresult->result = lhs; if (vnresult->result && lhs) ! changed |= set_ssa_val_to (lhs, vnresult->result); } else { *************** visit_reference_op_load (tree lhs, tree *** 3172,3204 **** of VIEW_CONVERT_EXPR (result). So first simplify and lookup this expression to see if it is already available. */ ! tree val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op), result); ! if ((CONVERT_EXPR_P (val) ! || TREE_CODE (val) == VIEW_CONVERT_EXPR) ! && TREE_CODE (TREE_OPERAND (val, 0)) == SSA_NAME) ! { ! tree tem = vn_get_expr_for (TREE_OPERAND (val, 0)); ! if ((CONVERT_EXPR_P (tem) ! || TREE_CODE (tem) == VIEW_CONVERT_EXPR) ! && (tem = fold_unary_ignore_overflow (TREE_CODE (val), ! TREE_TYPE (val), tem))) ! val = tem; ! } ! result = val; ! if (!is_gimple_min_invariant (val) ! && TREE_CODE (val) != SSA_NAME) ! result = vn_nary_op_lookup (val, NULL); ! /* If the expression is not yet available, value-number lhs to ! a new SSA_NAME we create. */ ! if (!result) ! { ! result = make_temp_ssa_name (TREE_TYPE (lhs), gimple_build_nop (), ! "vntemp"); /* Initialize value-number information properly. */ VN_INFO_GET (result)->valnum = result; VN_INFO (result)->value_id = get_next_value_id (); ! VN_INFO (result)->expr = val; ! VN_INFO (result)->has_constants = expr_has_constants (val); VN_INFO (result)->needs_insertion = true; /* As all "inserted" statements are singleton SCCs, insert to the valid table. This is strictly needed to --- 3089,3126 ---- of VIEW_CONVERT_EXPR (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 *************** visit_reference_op_load (tree lhs, tree *** 3210,3241 **** if (current_info == optimistic_info) { current_info = valid_info; ! vn_nary_op_insert (val, result); current_info = optimistic_info; } else ! vn_nary_op_insert (val, 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_generic_expr (dump_file, val, 0); fprintf (dump_file, "\n"); } } } if (result) ! { ! changed = set_ssa_val_to (lhs, result); ! if (TREE_CODE (result) == SSA_NAME ! && VN_INFO (result)->has_constants) ! { ! VN_INFO (lhs)->expr = VN_INFO (result)->expr; ! VN_INFO (lhs)->has_constants = true; ! } ! } else { changed = set_ssa_val_to (lhs, lhs); --- 3132,3156 ---- 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"); } } } if (result) ! changed = set_ssa_val_to (lhs, result); else { changed = set_ssa_val_to (lhs, lhs); *************** visit_phi (gimple *phi) *** 3401,3608 **** else { vn_phi_insert (phi, PHI_RESULT (phi)); - VN_INFO (PHI_RESULT (phi))->has_constants = false; - VN_INFO (PHI_RESULT (phi))->expr = PHI_RESULT (phi); changed = set_ssa_val_to (PHI_RESULT (phi), PHI_RESULT (phi)); } return changed; } - /* Return true if EXPR contains constants. */ - - static bool - expr_has_constants (tree expr) - { - switch (TREE_CODE_CLASS (TREE_CODE (expr))) - { - case tcc_unary: - return is_gimple_min_invariant (TREE_OPERAND (expr, 0)); - - case tcc_binary: - return is_gimple_min_invariant (TREE_OPERAND (expr, 0)) - || is_gimple_min_invariant (TREE_OPERAND (expr, 1)); - /* Constants inside reference ops are rarely interesting, but - it can take a lot of looking to find them. */ - case tcc_reference: - case tcc_declaration: - return false; - default: - return is_gimple_min_invariant (expr); - } - return false; - } - - /* Return true if STMT contains constants. */ - - static bool - stmt_has_constants (gimple *stmt) - { - tree tem; - - if (gimple_code (stmt) != GIMPLE_ASSIGN) - return false; - - switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))) - { - case GIMPLE_TERNARY_RHS: - tem = gimple_assign_rhs3 (stmt); - if (TREE_CODE (tem) == SSA_NAME) - tem = SSA_VAL (tem); - if (is_gimple_min_invariant (tem)) - return true; - /* Fallthru. */ - - case GIMPLE_BINARY_RHS: - tem = gimple_assign_rhs2 (stmt); - if (TREE_CODE (tem) == SSA_NAME) - tem = SSA_VAL (tem); - if (is_gimple_min_invariant (tem)) - return true; - /* Fallthru. */ - - case GIMPLE_SINGLE_RHS: - /* Constants inside reference ops are rarely interesting, but - it can take a lot of looking to find them. */ - case GIMPLE_UNARY_RHS: - tem = gimple_assign_rhs1 (stmt); - if (TREE_CODE (tem) == SSA_NAME) - tem = SSA_VAL (tem); - return is_gimple_min_invariant (tem); - - default: - gcc_unreachable (); - } - return false; - } - - /* Simplify the binary expression RHS, and return the result if - simplified. */ - - static tree - simplify_binary_expression (gimple *stmt) - { - tree result = NULL_TREE; - tree op0 = gimple_assign_rhs1 (stmt); - tree op1 = gimple_assign_rhs2 (stmt); - enum tree_code code = gimple_assign_rhs_code (stmt); - - /* This will not catch every single case we could combine, but will - catch those with constants. The goal here is to simultaneously - combine constants between expressions, but avoid infinite - expansion of expressions during simplification. */ - op0 = vn_valueize (op0); - if (TREE_CODE (op0) == SSA_NAME - && (VN_INFO (op0)->has_constants - || TREE_CODE_CLASS (code) == tcc_comparison - || code == COMPLEX_EXPR)) - op0 = vn_get_expr_for (op0); - - op1 = vn_valueize (op1); - if (TREE_CODE (op1) == SSA_NAME - && (VN_INFO (op1)->has_constants - || code == COMPLEX_EXPR)) - op1 = vn_get_expr_for (op1); - - /* Pointer plus constant can be represented as invariant address. - Do so to allow further propatation, see also tree forwprop. */ - if (code == POINTER_PLUS_EXPR - && tree_fits_uhwi_p (op1) - && TREE_CODE (op0) == ADDR_EXPR - && is_gimple_min_invariant (op0)) - return build_invariant_address (TREE_TYPE (op0), - TREE_OPERAND (op0, 0), - tree_to_uhwi (op1)); - - /* Avoid folding if nothing changed. */ - if (op0 == gimple_assign_rhs1 (stmt) - && op1 == gimple_assign_rhs2 (stmt)) - return NULL_TREE; - - fold_defer_overflow_warnings (); - - result = fold_binary (code, gimple_expr_type (stmt), op0, op1); - if (result) - STRIP_USELESS_TYPE_CONVERSION (result); - - fold_undefer_overflow_warnings (result && valid_gimple_rhs_p (result), - stmt, 0); - - /* Make sure result is not a complex expression consisting - of operators of operators (IE (a + b) + (a + c)) - Otherwise, we will end up with unbounded expressions if - fold does anything at all. */ - if (result && valid_gimple_rhs_p (result)) - return result; - - return NULL_TREE; - } - - /* Simplify the unary expression RHS, and return the result if - simplified. */ - - static tree - simplify_unary_expression (gassign *stmt) - { - tree result = NULL_TREE; - tree orig_op0, op0 = gimple_assign_rhs1 (stmt); - enum tree_code code = gimple_assign_rhs_code (stmt); - - /* We handle some tcc_reference codes here that are all - GIMPLE_ASSIGN_SINGLE codes. */ - if (code == REALPART_EXPR - || code == IMAGPART_EXPR - || code == VIEW_CONVERT_EXPR - || code == BIT_FIELD_REF) - op0 = TREE_OPERAND (op0, 0); - - orig_op0 = op0; - op0 = vn_valueize (op0); - if (TREE_CODE (op0) == SSA_NAME) - { - if (VN_INFO (op0)->has_constants) - op0 = vn_get_expr_for (op0); - else if (CONVERT_EXPR_CODE_P (code) - || code == REALPART_EXPR - || code == IMAGPART_EXPR - || code == VIEW_CONVERT_EXPR - || code == BIT_FIELD_REF) - { - /* We want to do tree-combining on conversion-like expressions. - Make sure we feed only SSA_NAMEs or constants to fold though. */ - tree tem = vn_get_expr_for (op0); - if (UNARY_CLASS_P (tem) - || BINARY_CLASS_P (tem) - || TREE_CODE (tem) == VIEW_CONVERT_EXPR - || TREE_CODE (tem) == SSA_NAME - || TREE_CODE (tem) == CONSTRUCTOR - || is_gimple_min_invariant (tem)) - op0 = tem; - } - } - - /* Avoid folding if nothing changed, but remember the expression. */ - if (op0 == orig_op0) - return NULL_TREE; - - if (code == BIT_FIELD_REF) - { - tree rhs = gimple_assign_rhs1 (stmt); - result = fold_ternary (BIT_FIELD_REF, TREE_TYPE (rhs), - op0, TREE_OPERAND (rhs, 1), TREE_OPERAND (rhs, 2)); - } - else - result = fold_unary_ignore_overflow (code, gimple_expr_type (stmt), op0); - if (result) - { - STRIP_USELESS_TYPE_CONVERSION (result); - if (valid_gimple_rhs_p (result)) - return result; - } - - return NULL_TREE; - } - /* Try to simplify RHS using equivalences and constant folding. */ static tree --- 3316,3327 ---- *************** try_to_simplify (gassign *stmt) *** 3617,3651 **** return NULL_TREE; /* First try constant folding based on our current lattice. */ tem = gimple_fold_stmt_to_constant_1 (stmt, vn_valueize, vn_valueize); if (tem && (TREE_CODE (tem) == SSA_NAME || is_gimple_min_invariant (tem))) return tem; - /* If that didn't work try combining multiple statements. */ - switch (TREE_CODE_CLASS (code)) - { - case tcc_reference: - /* Fallthrough for some unary codes that can operate on registers. */ - if (!(code == REALPART_EXPR - || code == IMAGPART_EXPR - || code == VIEW_CONVERT_EXPR - || code == BIT_FIELD_REF)) - break; - /* We could do a little more with unary ops, if they expand - into binary ops, but it's debatable whether it is worth it. */ - case tcc_unary: - return simplify_unary_expression (stmt); - - case tcc_comparison: - case tcc_binary: - return simplify_binary_expression (stmt); - - default: - break; - } - return NULL_TREE; } --- 3336,3349 ---- return NULL_TREE; /* First try constant folding based on our current lattice. */ + mprts_hook = vn_lookup_simplify_result; tem = gimple_fold_stmt_to_constant_1 (stmt, vn_valueize, vn_valueize); + mprts_hook = NULL; if (tem && (TREE_CODE (tem) == SSA_NAME || is_gimple_min_invariant (tem))) return tem; return NULL_TREE; } *************** visit_use (tree use) *** 3703,3713 **** print_gimple_expr (dump_file, stmt, 0, 0); fprintf (dump_file, " simplified to "); print_generic_expr (dump_file, simplified, 0); ! if (TREE_CODE (lhs) == SSA_NAME) ! fprintf (dump_file, " has constants %d\n", ! expr_has_constants (simplified)); ! else ! fprintf (dump_file, "\n"); } } /* Setting value numbers to constants will occasionally --- 3401,3407 ---- print_gimple_expr (dump_file, stmt, 0, 0); fprintf (dump_file, " simplified to "); print_generic_expr (dump_file, simplified, 0); ! fprintf (dump_file, "\n"); } } /* Setting value numbers to constants will occasionally *************** visit_use (tree use) *** 3718,3725 **** && is_gimple_min_invariant (simplified) && TREE_CODE (lhs) == SSA_NAME) { - VN_INFO (lhs)->expr = simplified; - VN_INFO (lhs)->has_constants = true; changed = set_ssa_val_to (lhs, simplified); goto done; } --- 3412,3417 ---- *************** visit_use (tree use) *** 3730,3758 **** changed = visit_copy (lhs, simplified); goto done; } - else if (simplified) - { - if (TREE_CODE (lhs) == SSA_NAME) - { - VN_INFO (lhs)->has_constants = expr_has_constants (simplified); - /* We have to unshare the expression or else - valuizing may change the IL stream. */ - VN_INFO (lhs)->expr = unshare_expr (simplified); - } - } - else if (stmt_has_constants (stmt) - && TREE_CODE (lhs) == SSA_NAME) - VN_INFO (lhs)->has_constants = true; - else if (TREE_CODE (lhs) == SSA_NAME) - { - /* We reset expr and constantness here because we may - have been value numbering optimistically, and - iterating. They may become non-constant in this case, - even if they were optimistically constant. */ - - VN_INFO (lhs)->has_constants = false; - VN_INFO (lhs)->expr = NULL_TREE; - } if ((TREE_CODE (lhs) == SSA_NAME /* We can substitute SSA_NAMEs that are live over --- 3422,3427 ---- *************** visit_use (tree use) *** 3777,3783 **** || (simplified && is_gimple_min_invariant (simplified))) { - VN_INFO (lhs)->has_constants = true; if (simplified) changed = set_ssa_val_to (lhs, simplified); else --- 3446,3451 ---- *************** visit_use (tree use) *** 3840,3850 **** print_gimple_expr (dump_file, stmt, 0, 0); fprintf (dump_file, " simplified to "); print_generic_expr (dump_file, simplified, 0); ! if (TREE_CODE (lhs) == SSA_NAME) ! fprintf (dump_file, " has constants %d\n", ! expr_has_constants (simplified)); ! else ! fprintf (dump_file, "\n"); } } /* Setting value numbers to constants will occasionally --- 3508,3514 ---- print_gimple_expr (dump_file, stmt, 0, 0); fprintf (dump_file, " simplified to "); print_generic_expr (dump_file, simplified, 0); ! fprintf (dump_file, "\n"); } } /* Setting value numbers to constants will occasionally *************** visit_use (tree use) *** 3854,3861 **** if (simplified && is_gimple_min_invariant (simplified)) { - VN_INFO (lhs)->expr = simplified; - VN_INFO (lhs)->has_constants = true; changed = set_ssa_val_to (lhs, simplified); if (gimple_vdef (stmt)) changed |= set_ssa_val_to (gimple_vdef (stmt), --- 3518,3523 ---- *************** visit_use (tree use) *** 3873,3890 **** } else { - if (stmt_has_constants (stmt)) - VN_INFO (lhs)->has_constants = true; - else - { - /* We reset expr and constantness here because we may - have been value numbering optimistically, and - iterating. They may become non-constant in this case, - even if they were optimistically constant. */ - VN_INFO (lhs)->has_constants = false; - VN_INFO (lhs)->expr = NULL_TREE; - } - if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) { changed = defs_to_varying (stmt); --- 3535,3540 ---- *************** process_scc (vec scc) *** 4083,4089 **** optimistic_info->phis_pool->release (); optimistic_info->references_pool->release (); FOR_EACH_VEC_ELT (scc, i, var) ! VN_INFO (var)->expr = NULL_TREE; FOR_EACH_VEC_ELT (scc, i, var) changed |= visit_use (var); } --- 3733,3740 ---- optimistic_info->phis_pool->release (); optimistic_info->references_pool->release (); FOR_EACH_VEC_ELT (scc, i, var) ! gcc_assert (!VN_INFO (var)->needs_insertion ! && VN_INFO (var)->expr == NULL); FOR_EACH_VEC_ELT (scc, i, var) changed |= visit_use (var); } *************** init_scc_vn (void) *** 4338,4344 **** continue; VN_INFO_GET (name)->valnum = VN_TOP; ! VN_INFO (name)->expr = NULL_TREE; VN_INFO (name)->value_id = 0; if (!SSA_NAME_IS_DEFAULT_DEF (name)) --- 3989,3996 ---- continue; VN_INFO_GET (name)->valnum = VN_TOP; ! VN_INFO (name)->needs_insertion = false; ! VN_INFO (name)->expr = NULL; VN_INFO (name)->value_id = 0; if (!SSA_NAME_IS_DEFAULT_DEF (name)) *************** sccvn_dom_walker::before_dom_children (b *** 4692,4707 **** { case GIMPLE_COND: { ! tree lhs = gimple_cond_lhs (stmt); ! tree rhs = gimple_cond_rhs (stmt); ! /* Work hard in computing the condition and take into account ! the valueization of the defining stmt. */ ! if (TREE_CODE (lhs) == SSA_NAME) ! lhs = vn_get_expr_for (lhs); ! if (TREE_CODE (rhs) == SSA_NAME) ! rhs = vn_get_expr_for (rhs); ! val = fold_binary (gimple_cond_code (stmt), ! boolean_type_node, lhs, rhs); /* If that didn't simplify to a constant see if we have recorded temporary expressions from taken edges. */ if (!val || TREE_CODE (val) != INTEGER_CST) --- 4344,4353 ---- { case GIMPLE_COND: { ! val = gimple_simplify (gimple_cond_code (stmt), ! boolean_type_node, ! gimple_cond_lhs (stmt), gimple_cond_rhs (stmt), ! NULL, vn_valueize); /* If that didn't simplify to a constant see if we have recorded temporary expressions from taken edges. */ if (!val || TREE_CODE (val) != INTEGER_CST) Index: gcc/gimple-match-head.c =================================================================== *** gcc/gimple-match-head.c.orig 2015-09-30 14:49:24.613211956 +0200 --- gcc/gimple-match-head.c 2015-09-30 14:58:48.002555604 +0200 *************** maybe_build_generic_op (enum tree_code c *** 293,298 **** --- 293,300 ---- } } + tree (*mprts_hook) (code_helper, tree, tree *); + /* Push the exploded expression described by RCODE, TYPE and OPS as a statement to SEQ if necessary and return a gimple value denoting the value of the expression. If RES is not NULL *************** maybe_push_res_to_seq (code_helper rcode *** 310,315 **** --- 312,323 ---- || ((tree_code) rcode) == ADDR_EXPR) && is_gimple_val (ops[0])) return ops[0]; + if (mprts_hook) + { + tree tem = mprts_hook (rcode, type, ops); + if (tem) + return tem; + } if (!seq) return NULL_TREE; /* Play safe and do not allow abnormals to be mentioned in Index: gcc/gimple-match.h =================================================================== *** gcc/gimple-match.h.orig 2015-09-30 14:49:24.613211956 +0200 --- gcc/gimple-match.h 2015-09-30 14:58:48.002555604 +0200 *************** private: *** 40,45 **** --- 40,47 ---- int rep; }; + extern tree (*mprts_hook) (code_helper, tree, tree *); + bool gimple_simplify (gimple *, code_helper *, tree *, gimple_seq *, tree (*)(tree), tree (*)(tree)); tree maybe_push_res_to_seq (code_helper, tree, tree *, Index: gcc/tree-ssa-sccvn.h =================================================================== *** gcc/tree-ssa-sccvn.h.orig 2015-09-30 14:49:24.613211956 +0200 --- gcc/tree-ssa-sccvn.h 2015-09-30 14:58:48.018555783 +0200 *************** typedef struct vn_ssa_aux *** 165,172 **** { /* Value number. This may be an SSA name or a constant. */ tree valnum; ! /* Representative expression, if not a direct constant. */ ! tree expr; /* Unique identifier that all expressions with the same value have. */ unsigned int value_id; --- 165,172 ---- { /* Value number. This may be an SSA name or a constant. */ tree valnum; ! /* Statements to insert if needs_insertion is true. */ ! gimple_seq expr; /* Unique identifier that all expressions with the same value have. */ unsigned int value_id; *************** typedef struct vn_ssa_aux *** 177,184 **** unsigned visited : 1; unsigned on_sccstack : 1; - /* Whether the representative expression contains constants. */ - unsigned has_constants : 1; /* Whether the SSA_NAME has been value numbered already. This is only saying whether visit_use has been called on it at least once. It cannot be used to avoid visitation for SSA_NAME's --- 177,182 ---- Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c.orig 2015-09-30 14:49:23.864203487 +0200 --- gcc/tree-ssa-pre.c 2015-09-30 14:58:48.017555772 +0200 *************** eliminate_push_avail (tree op) *** 3953,3973 **** static tree eliminate_insert (gimple_stmt_iterator *gsi, tree val) { ! tree expr = vn_get_expr_for (val); ! if (!CONVERT_EXPR_P (expr) ! && TREE_CODE (expr) != VIEW_CONVERT_EXPR) return NULL_TREE; ! tree op = TREE_OPERAND (expr, 0); tree leader = TREE_CODE (op) == SSA_NAME ? eliminate_avail (op) : op; if (!leader) return NULL_TREE; ! tree res = make_temp_ssa_name (TREE_TYPE (val), NULL, "pretmp"); ! gassign *tem = gimple_build_assign (res, ! fold_build1 (TREE_CODE (expr), ! TREE_TYPE (expr), leader)); ! gsi_insert_before (gsi, tem, GSI_SAME_STMT); VN_INFO_GET (res)->valnum = val; if (TREE_CODE (leader) == SSA_NAME) --- 3953,3975 ---- static tree eliminate_insert (gimple_stmt_iterator *gsi, tree val) { ! gimple *stmt = gimple_seq_first_stmt (VN_INFO (val)->expr); ! if (!is_gimple_assign (stmt) ! || (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)) ! && gimple_assign_rhs_code (stmt) != VIEW_CONVERT_EXPR)) return NULL_TREE; ! tree op = gimple_assign_rhs1 (stmt); ! if (gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR) ! op = TREE_OPERAND (op, 0); tree leader = TREE_CODE (op) == SSA_NAME ? eliminate_avail (op) : op; if (!leader) return NULL_TREE; ! gimple_seq stmts = NULL; ! tree 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) *************** eliminate_insert (gimple_stmt_iterator * *** 3977,3983 **** if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Inserted "); ! print_gimple_stmt (dump_file, tem, 0, 0); } return res; --- 3979,3985 ---- if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Inserted "); ! print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (res), 0, 0); } return res; *************** eliminate_dom_walker::before_dom_childre *** 4101,4107 **** if (val != VN_TOP && TREE_CODE (val) == SSA_NAME && VN_INFO (val)->needs_insertion ! && VN_INFO (val)->expr != NULL_TREE && (sprime = eliminate_insert (&gsi, val)) != NULL_TREE) eliminate_push_avail (sprime); } --- 4103,4109 ---- if (val != VN_TOP && TREE_CODE (val) == SSA_NAME && VN_INFO (val)->needs_insertion ! && VN_INFO (val)->expr != NULL && (sprime = eliminate_insert (&gsi, val)) != NULL_TREE) eliminate_push_avail (sprime); } Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c.orig 2015-09-30 14:49:23.864203487 +0200 --- gcc/gimple-fold.c 2015-09-30 14:58:48.031555929 +0200 *************** gimple_fold_stmt_to_constant_1 (gimple * *** 4883,4904 **** edges if there are intermediate VARYING defs. For this reason do not follow SSA edges here even though SCCVN can technically just deal fine with that. */ ! if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize) ! && rcode.is_tree_code () ! && (TREE_CODE_LENGTH ((tree_code) rcode) == 0 ! || ((tree_code) rcode) == ADDR_EXPR) ! && is_gimple_val (ops[0])) { ! tree res = ops[0]; ! if (dump_file && dump_flags & TDF_DETAILS) { ! fprintf (dump_file, "Match-and-simplified "); ! print_gimple_expr (dump_file, stmt, 0, TDF_SLIM); ! fprintf (dump_file, " to "); ! print_generic_expr (dump_file, res, 0); ! fprintf (dump_file, "\n"); } - return res; } location_t loc = gimple_location (stmt); --- 4883,4910 ---- edges if there are intermediate VARYING defs. For this reason do not follow SSA edges here even though SCCVN can technically just deal fine with that. */ ! 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); ! if (res) { ! if (dump_file && dump_flags & TDF_DETAILS) ! { ! fprintf (dump_file, "Match-and-simplified "); ! print_gimple_expr (dump_file, stmt, 0, TDF_SLIM); ! fprintf (dump_file, " to "); ! print_generic_expr (dump_file, res, 0); ! fprintf (dump_file, "\n"); ! } ! return res; } } location_t loc = gimple_location (stmt);