@@ -813,6 +813,7 @@ struct noce_if_info
/* Estimated cost of the particular branch instruction. */
unsigned int branch_cost;
+ unsigned int rtx_edge_cost;
};
static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int);
@@ -830,6 +831,17 @@ static int noce_try_minmax (struct noce_if_info *);
static int noce_try_abs (struct noce_if_info *);
static int noce_try_sign_mask (struct noce_if_info *);
+/* This function is always called when we would expand a number of "cheap"
+ instructions. Multiply NINSNS by COSTS_N_INSNS (1) to approximate the
+ RTX cost of those cheap instructions. */
+
+inline static bool
+noce_estimate_conversion_profitable_p (struct noce_if_info *if_info,
+ unsigned int ninsns)
+{
+ return (if_info->rtx_edge_cost >= ninsns * COSTS_N_INSNS (1));
+}
+
/* Helper function for noce_try_store_flag*. */
static rtx
@@ -1279,7 +1291,8 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
&& (REG_P (XEXP (a, 0))
|| (noce_operand_ok (XEXP (a, 0))
&& ! reg_overlap_mentioned_p (if_info->x, XEXP (a, 0))))
- && if_info->branch_cost >= 2)
+ /* We need one instruction, the ADD of the store flag. */
+ && noce_estimate_conversion_profitable_p (if_info, 1))
{
common = XEXP (a, 0);
a = XEXP (a, 1);
@@ -1352,22 +1365,32 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
else
gcc_unreachable ();
}
+ /* Is this (cond) ? 2^n : 0? */
else if (ifalse == 0 && exact_log2 (itrue) >= 0
&& (STORE_FLAG_VALUE == 1
- || if_info->branch_cost >= 2))
+ /* We need ASHIFT, IOR. */
+ || noce_estimate_conversion_profitable_p (if_info, 2)))
normalize = 1;
+ /* Is this (cond) ? 0 : 2^n? */
else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse
- && (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2))
+ && (STORE_FLAG_VALUE == 1
+ /* We need ASHIFT, IOR. */
+ || noce_estimate_conversion_profitable_p (if_info, 2)))
{
normalize = 1;
reversep = true;
}
+ /* Is this (cond) ? -1 : x? */
else if (itrue == -1
&& (STORE_FLAG_VALUE == -1
- || if_info->branch_cost >= 2))
+ /* Just an IOR. */
+ || noce_estimate_conversion_profitable_p (if_info, 1)))
normalize = -1;
+ /* Is this (cond) ? x : -1? */
else if (ifalse == -1 && can_reverse
- && (STORE_FLAG_VALUE == -1 || if_info->branch_cost >= 2))
+ && (STORE_FLAG_VALUE == -1
+ /* Just an IOR. */
+ || noce_estimate_conversion_profitable_p (if_info, 1)))
{
normalize = -1;
reversep = true;
@@ -1519,8 +1542,8 @@ noce_try_addcc (struct noce_if_info *if_info)
}
/* If that fails, construct conditional increment or decrement using
- setcc. */
- if (if_info->branch_cost >= 2
+ setcc. We'd only need an ADD/SUB for this. */
+ if (noce_estimate_conversion_profitable_p (if_info, 1)
&& (XEXP (if_info->a, 1) == const1_rtx
|| XEXP (if_info->a, 1) == constm1_rtx))
{
@@ -1575,7 +1598,9 @@ noce_try_store_flag_mask (struct noce_if_info *if_info)
return FALSE;
reversep = 0;
- if ((if_info->branch_cost >= 2
+
+ /* Two insns, AND, NEG. */
+ if ((noce_estimate_conversion_profitable_p (if_info, 2)
|| STORE_FLAG_VALUE == -1)
&& ((if_info->a == const0_rtx
&& rtx_equal_p (if_info->b, if_info->x))
@@ -1778,8 +1803,11 @@ noce_try_cmove (struct noce_if_info *if_info)
approach. */
else if (!targetm.have_conditional_execution ()
&& CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b)
- && ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1)
- || if_info->branch_cost >= 3))
+ /* If STORE_FLAG_VALUE is -1, we need SUB, AND, PLUS. */
+ && ((noce_estimate_conversion_profitable_p (if_info, 3)
+ && STORE_FLAG_VALUE == -1)
+ /* Otherwise, we need NEG, SUB, AND, PLUS. */
+ || noce_estimate_conversion_profitable_p (if_info, 4)))
{
machine_mode mode = GET_MODE (if_info->x);
HOST_WIDE_INT ifalse = INTVAL (if_info->a);
@@ -2031,7 +2059,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
if (cse_not_expected
&& MEM_P (a) && MEM_P (b)
&& MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b)
- && if_info->branch_cost >= 5)
+ && noce_estimate_conversion_profitable_p (if_info, 5))
{
machine_mode address_mode = get_address_mode (a);
@@ -3967,6 +3995,9 @@ noce_find_if_block (basic_block test_bb, edge then_edge, edge else_edge,
if_info.then_else_reversed = then_else_reversed;
if_info.branch_cost = BRANCH_COST (optimize_bb_for_speed_p (test_bb),
predictable_edge_p (then_edge));
+ if_info.rtx_edge_cost
+ = targetm.rtx_branch_cost (optimize_bb_for_speed_p (test_bb),
+ predictable_edge_p (then_edge));
/* Do the real work. */