Hi, On Fri, Jul 12 2019, Feng Xue OS wrote: > Current IPA-cp only generates cost-evaluating predicate for conditional > statement like > "if (param cmp const_val)", it is too simple and conservative. This patch > generalizes the > process to handle the form as T(param), a mathematical transformation on the > function > parameter, in which the parameter occurs once, and other operands are > constant value.
thanks for working on this. I cannot approve this, but I have had a brief look and have the following comments: > > ---- > diff --git a/gcc/ChangeLog b/gcc/ChangeLog > index 3d92250b520..0110446e09e 100644 > --- a/gcc/ChangeLog > +++ b/gcc/ChangeLog > @@ -1,3 +1,25 @@ > +2019-07-12 Feng Xue <f...@os.amperecomputing.com> > + > + PR ipa/91088 > + * ipa-predicat.h (struct expr_eval_op): New struct. > + (expr_eval_ops): New typedef. > + (struct condition): Add param_ops member. > + (add_condition): Add param_ops parameter. > + * ipa-predicat.c (expr_eval_ops_equal_p): New function. > + (predicate::add_clause): Add param_ops comparison. > + (dump_condition): Add debug dump for param_ops. > + (remap_after_inlining): Add param_ops argument to call to > + add_condition. > + (add_condition): Add parameter param_ops. > + * ipa-fnsummary.c (evaluate_conditions_for_known_args): Fold > + parameter expressions using param_ops. > + (decompose_param_expr): New function. > + (set_cond_stmt_execution_predicate): Use call to decompose_param_expr > + to replace call to unmodified_parm_or_parm_agg_item. > + (set_switch_stmt_execution_predicate): Likewise. > + (inline_read_section): Read param_ops from summary stream. > + (ipa_fn_summary_write): Write param_ops to summary stream. > + (It's a bad idea to make ChangeLog entries part of the patch, it won't apply to anyone, not even to you nowadays. ) > 2019-07-11 Sunil K Pandey <sunil.k.pan...@intel.com> > > PR target/90980 > diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c > index 09986211a1d..faf8bd39090 100644 > --- a/gcc/ipa-fnsummary.c > +++ b/gcc/ipa-fnsummary.c > @@ -301,9 +301,9 @@ set_hint_predicate (predicate **p, predicate > new_predicate) > } > > > -/* Compute what conditions may or may not hold given invormation about > +/* Compute what conditions may or may not hold given information about > parameters. RET_CLAUSE returns truths that may hold in a specialized > copy, > - whie RET_NONSPEC_CLAUSE returns truths that may hold in an nonspecialized > + while RET_NONSPEC_CLAUSE returns truths that may hold in an nonspecialized > copy when called in a given context. It is a bitmask of conditions. Bit > 0 means that condition is known to be false, while bit 1 means that > condition > may or may not be true. These differs - for example NOT_INLINED condition > @@ -336,6 +336,8 @@ evaluate_conditions_for_known_args (struct cgraph_node > *node, > { > tree val; > tree res; > + int j; > + struct expr_eval_op *op; > > /* We allow call stmt to have fewer arguments than the callee function > (especially for K&R style programs). So bound check here (we assume > @@ -399,7 +401,18 @@ evaluate_conditions_for_known_args (struct cgraph_node > *node, > continue; > } > > - val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (c->val), val); > + for (j = 0; vec_safe_iterate (c->param_ops, j, &op); j++) > + { > + if (!op->val) > + val = fold_unary (op->code, op->type, val); > + else if (op->val_is_rhs) > + val = fold_binary_to_constant (op->code, op->type, val, op->val); > + else > + val = fold_binary_to_constant (op->code, op->type, op->val, val); > + if (!val) > + break; > + } > + > res = val > ? fold_binary_to_constant (c->code, boolean_type_node, val, c->val) > : NULL; > @@ -1177,6 +1190,105 @@ eliminated_by_inlining_prob (ipa_func_body_info *fbi, > gimple *stmt) > } > } > > +/* Flatten a tree expression on parameter into a set of sequential > operations. > + we only handle expression that is a mathematical transformation on the > + parameter, and in the expression, parameter occurs only once, and other > + operands are IPA invariant. */ I understand describing these things is difficult, but flatten is strange way to describe what the function does. What about somthing like the following? Analyze EXPR if it represents a series of simple operations performed on a function parameter and return true if so. FBI, STMT, INDEX_P, SIZE_P and AGGPOS have the same meaning like in unmodified_parm_or_parm_agg_item. Operations on the parameter are recorded to PARAM_OPS_P if it is not NULL. > + > +static bool > +decompose_param_expr (struct ipa_func_body_info *fbi, > + gimple *stmt, tree expr, > + int *index_p, HOST_WIDE_INT *size_p, > + struct agg_position_info *aggpos, > + expr_eval_ops *param_ops_p) > +{ > + if (param_ops_p) > + *param_ops_p = NULL; > + > + while (true) > + { > + gimple_rhs_class rhs_class; > + expr_eval_op eval_op; > + > + if (unmodified_parm_or_parm_agg_item (fbi, stmt, expr, index_p, > + size_p, aggpos)) > + { > + if (param_ops_p) > + { > + /* Find use of parameter, add a convert operation to describe > + result type, which may not be same as parameter type. */ > + eval_op.val_is_rhs = false; > + eval_op.val = NULL_TREE; > + eval_op.code = VIEW_CONVERT_EXPR; > + eval_op.type = TREE_TYPE (expr); > + > + vec_safe_insert (*param_ops_p, 0, eval_op); If we get here in the first iteration of the loop, could we not insert anything into the vector and handle such cases in evaluate_conditions_for_known_args like we do today (well, with fold_convert might be better)? It could save quite some memory and it is important to try keep the memory footprint down in IPA summaries. Also, I think you want a parameter to limit the maximum length of param_ops_p, at some point someone will come with some crazy machine-generated code that will create huge vectors. Thanks, Martin