From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25089 invoked by alias); 28 Apr 2011 11:16:26 -0000 Received: (qmail 25077 invoked by uid 22791); 28 Apr 2011 11:16:25 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 28 Apr 2011 11:16:07 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 7CE039AC846; Thu, 28 Apr 2011 13:16:04 +0200 (CEST) Date: Thu, 28 Apr 2011 12:42:00 -0000 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: Propagate will_be_nonconstant in ipa-analysis Message-ID: <20110428111604.GC1199@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) 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 X-SW-Source: 2011-04/txt/msg02210.txt.bz2 Hi, tthis patch makes inliner to handle nested expressions when trying to figure out what will be constant after inlining. This is done by simple propagation across SSA names. We can't really handle PHIs well, since we know name will be constant, but we don't know what, so this is a lot weakter than SCCP, should be enough for cases inliner is interested in. We would get better results running this in DFS order, but at the momemnt we don't have any funcition computing it when cfun is not set. I will do that incrementally. Bootstrapped/regtested x86_64-linux, will commit it later today. Honza * ipa-inline-analysis.c (will_be_nonconstant_predicate): Take nonconstant_names array. (estimate_function_body_sizes): Build nonconstant_names array; handle BUILT_IN_CONSTANT_P. Index: ipa-inline-analysis.c =================================================================== *** ipa-inline-analysis.c (revision 173042) --- ipa-inline-analysis.c (working copy) *************** edge_execution_predicate (struct ipa_nod *** 931,940 **** gimple_cond_rhs (last)); } static struct predicate will_be_nonconstant_predicate (struct ipa_node_params *info, struct inline_summary *summary, ! gimple stmt) { struct predicate p = true_predicate (); ssa_op_iter iter; --- 931,953 ---- gimple_cond_rhs (last)); } + + /* We keep info about constantness of SSA names. */ + + typedef struct predicate predicate_t; + DEF_VEC_O (predicate_t); + DEF_VEC_ALLOC_O (predicate_t, heap); + + + /* Return predicate specifying when the STMT might have result that is not a compile + time constant. */ + static struct predicate will_be_nonconstant_predicate (struct ipa_node_params *info, struct inline_summary *summary, ! gimple stmt, ! VEC (predicate_t, heap) *nonconstant_names) ! { struct predicate p = true_predicate (); ssa_op_iter iter; *************** will_be_nonconstant_predicate (struct ip *** 949,955 **** && gimple_code (stmt) != GIMPLE_SWITCH) return p; ! /* Stores and loads will stay anyway. */ if (gimple_vuse (stmt)) return p; --- 962,969 ---- && gimple_code (stmt) != GIMPLE_SWITCH) return p; ! /* Stores and loads will stay anyway. ! TODO: Constant memory accesses could be handled here, too. */ if (gimple_vuse (stmt)) return p; *************** will_be_nonconstant_predicate (struct ip *** 957,977 **** adding conditionals. */ FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) { ! /* TODO: handle nested expressions and constant ! array accesses. */ ! if (TREE_CODE (use) != SSA_NAME ! || !SSA_NAME_IS_DEFAULT_DEF (use) ! || ipa_get_param_decl_index (info, SSA_NAME_VAR (use)) < 0) return p; } op_non_const = false_predicate (); FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) { ! p = add_condition (summary, ! ipa_get_param_decl_index (info, SSA_NAME_VAR (use)), ! IS_NOT_CONSTANT, NULL); op_non_const = or_predicates (&p, &op_non_const); } return op_non_const; } --- 971,1006 ---- adding conditionals. */ FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) { ! if (TREE_CODE (use) != SSA_NAME) return p; + /* For arguments we can build a condition. */ + if (SSA_NAME_IS_DEFAULT_DEF (use) + && ipa_get_param_decl_index (info, SSA_NAME_VAR (use)) >= 0) + continue; + /* If we know when operand is constant, + we still can say something useful. */ + if (!true_predicate_p (VEC_index (predicate_t, nonconstant_names, + SSA_NAME_VERSION (use)))) + continue; + return p; } op_non_const = false_predicate (); FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) { ! if (SSA_NAME_IS_DEFAULT_DEF (use) ! && ipa_get_param_decl_index (info, SSA_NAME_VAR (use)) >= 0) ! p = add_condition (summary, ! ipa_get_param_decl_index (info, SSA_NAME_VAR (use)), ! IS_NOT_CONSTANT, NULL); ! else ! p = *VEC_index (predicate_t, nonconstant_names, ! SSA_NAME_VERSION (use)); op_non_const = or_predicates (&p, &op_non_const); } + if (gimple_code (stmt) == GIMPLE_ASSIGN + && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME) + VEC_replace (predicate_t, nonconstant_names, + SSA_NAME_VERSION (gimple_assign_lhs (stmt)), &op_non_const); return op_non_const; } *************** estimate_function_body_sizes (struct cgr *** 994,1002 **** int freq; struct inline_summary *info = inline_summary (node); struct predicate bb_predicate; ! struct ipa_node_params *parms_info; ! parms_info = ipa_node_params_vector && !early ? IPA_NODE_REF (node) : NULL; info->conds = 0; info->entry = 0; --- 1023,1037 ---- int freq; struct inline_summary *info = inline_summary (node); struct predicate bb_predicate; ! struct ipa_node_params *parms_info = NULL; ! VEC (predicate_t, heap) *nonconstant_names = NULL; ! if (ipa_node_params_vector && !early && optimize) ! { ! parms_info = IPA_NODE_REF (node); ! VEC_safe_grow_cleared (predicate_t, heap, nonconstant_names, ! VEC_length (tree, SSANAMES (my_function))); ! } info->conds = 0; info->entry = 0; *************** estimate_function_body_sizes (struct cgr *** 1014,1020 **** bb_predicate = not_inlined_predicate (); account_size_time (info, 2 * INLINE_SIZE_SCALE, 0, &bb_predicate); - gcc_assert (my_function && my_function->cfg); FOR_EACH_BB_FN (bb, my_function) { --- 1049,1054 ---- *************** estimate_function_body_sizes (struct cgr *** 1063,1068 **** --- 1097,1115 ---- struct cgraph_edge *edge = cgraph_edge (node, stmt); struct inline_edge_summary *es = inline_edge_summary (edge); + /* Special case: results of BUILT_IN_CONSTANT_P will be always + resolved as constant. We however don't want to optimize + out the cgraph edges. */ + if (nonconstant_names + && gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P) + && gimple_call_lhs (stmt) + && TREE_CODE (gimple_call_lhs (stmt)) == SSA_NAME) + { + struct predicate false_p = false_predicate (); + VEC_replace (predicate_t, nonconstant_names, + SSA_NAME_VERSION (gimple_call_lhs (stmt)), &false_p); + } + es->call_stmt_size = this_size; es->call_stmt_time = this_time; es->loop_depth = bb->loop_depth; *************** estimate_function_body_sizes (struct cgr *** 1098,1104 **** if (parms_info) { will_be_nonconstant ! = will_be_nonconstant_predicate (parms_info, info, stmt); p = and_predicates (&bb_predicate, &will_be_nonconstant); } else --- 1145,1152 ---- if (parms_info) { will_be_nonconstant ! = will_be_nonconstant_predicate (parms_info, info, ! stmt, nonconstant_names); p = and_predicates (&bb_predicate, &will_be_nonconstant); } else *************** estimate_function_body_sizes (struct cgr *** 1131,1136 **** --- 1179,1185 ---- time = MAX_TIME; inline_summary (node)->self_time = time; inline_summary (node)->self_size = size; + VEC_free (predicate_t, heap, nonconstant_names); if (dump_file) { fprintf (dump_file, "\n");