/* Returns cost of operation CODE, according to WEIGHTS */
static int
-estimate_operator_cost (enum tree_code code, eni_weights *weights)
+estimate_operator_cost (enum tree_code code, eni_weights *weights,
+ tree op1 ATTRIBUTE_UNUSED, tree op2)
{
switch (code)
{
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
case RDIV_EXPR:
- return weights->div_mod_cost;
+ if (TREE_CODE (op2) != INTEGER_CST)
+ return weights->div_mod_cost;
+ return 1;
default:
/* We expect a copy assignment with no operator. */
unsigned cost, i;
enum gimple_code code = gimple_code (stmt);
tree lhs;
+ tree rhs;
switch (code)
{
of moving something into "a", which we compute using the function
estimate_move_cost. */
lhs = gimple_assign_lhs (stmt);
+ rhs = gimple_assign_rhs1 (stmt);
+
+ /* EH magic stuff is most probably going to be optimized out.
+ We rarely really need to save EH info for unwinding
+ nested exceptions. */
+ if (TREE_CODE (lhs) == FILTER_EXPR
+ || TREE_CODE (lhs) == EXC_PTR_EXPR
+ || TREE_CODE (rhs) == FILTER_EXPR
+ || TREE_CODE (rhs) == EXC_PTR_EXPR)
+ return 0;
if (is_gimple_reg (lhs))
cost = 0;
else
cost = estimate_move_cost (TREE_TYPE (lhs));
- cost += estimate_operator_cost (gimple_assign_rhs_code (stmt), weights);
+ if (!is_gimple_reg (rhs) && !is_gimple_min_invariant (rhs))
+ cost += estimate_move_cost (TREE_TYPE (rhs));
+
+ cost += estimate_operator_cost (gimple_assign_rhs_code (stmt), weights,
+ gimple_assign_rhs1 (stmt),
+ get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
+ == GIMPLE_BINARY_RHS
+ ? gimple_assign_rhs2 (stmt) : NULL);
break;
case GIMPLE_COND:
- cost = 1 + estimate_operator_cost (gimple_cond_code (stmt), weights);
+ cost = 1 + estimate_operator_cost (gimple_cond_code (stmt), weights,
+ gimple_op (stmt, 0),
+ gimple_op (stmt, 1));
break;
case GIMPLE_SWITCH:
TODO: once the switch expansion logic is sufficiently separated, we can
do better job on estimating cost of the switch. */
- cost = gimple_switch_num_labels (stmt) * 2;
+ if (weights->time_based)
+ cost = floor_log2 (gimple_switch_num_labels (stmt)) * 2;
+ else
+ cost = gimple_switch_num_labels (stmt) * 2;
break;
case GIMPLE_CALL:
case BUILT_IN_CONSTANT_P:
return 0;
case BUILT_IN_EXPECT:
- cost = 0;
- break;
+ return 0;
/* Prefetch instruction is not expensive. */
case BUILT_IN_PREFETCH:
if (decl)
funtype = TREE_TYPE (decl);
+ if (!VOID_TYPE_P (TREE_TYPE (funtype)))
+ cost += estimate_move_cost (TREE_TYPE (funtype));
/* Our cost must be kept in sync with
cgraph_estimate_size_after_inlining that does use function
declaration to figure out the arguments. */
eni_inlining_weights.target_builtin_call_cost = 1;
eni_inlining_weights.div_mod_cost = 10;
eni_inlining_weights.omp_cost = 40;
+ eni_inlining_weights.time_based = true;
eni_size_weights.call_cost = 1;
eni_size_weights.target_builtin_call_cost = 1;
eni_size_weights.div_mod_cost = 1;
eni_size_weights.omp_cost = 40;
+ eni_size_weights.time_based = false;
/* Estimating time for call is difficult, since we have no idea what the
called function does. In the current uses of eni_time_weights,
eni_time_weights.target_builtin_call_cost = 10;
eni_time_weights.div_mod_cost = 10;
eni_time_weights.omp_cost = 40;
+ eni_time_weights.time_based = true;
}
/* Estimate the number of instructions in a gimple_seq. */