@@ -820,6 +820,14 @@ struct noce_if_info
/* Estimated cost of the particular branch instruction. */
unsigned int branch_cost;
+
+ /* For if-convert transformations, the legacy way to decide whether
+ the transformation should be applied is a comparison of a magic
+ number against BRANCH_COST. Ultimately, this should go away, but
+ to avoid regressing targets this field encodes that number so the
+ profitability analysis can remain unchanged. */
+ unsigned int magic_number;
+
};
static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int);
@@ -836,6 +844,19 @@ static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx_insn **);
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 *);
+static bool noce_is_profitable_p (rtx_insn *, struct noce_if_info *);
+
+/* Given SEQ, which is a sequence we might want to generate after
+ if-conversion, and a basic-block structure in IF_INFO which represents
+ the code generation before if-conversion, return TRUE if this would
+ be a profitable transformation. */
+
+static bool
+noce_is_profitable_p (rtx_insn *seq ATTRIBUTE_UNUSED,
+ struct noce_if_info *if_info)
+{
+ return (if_info->branch_cost >= if_info->magic_number);
+}
/* Helper function for noce_try_store_flag*. */
@@ -1192,8 +1213,13 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
HOST_WIDE_INT itrue, ifalse, diff, tmp;
int normalize;
bool can_reverse;
+ bool no_cost_model = false;
machine_mode mode = GET_MODE (if_info->x);;
rtx common = NULL_RTX;
+ /* ??? There are paths through this function from which no cost function
+ is checked before conversion. Maintain that behaviour by setting
+ the magic number used by noce_is_profitable_p to zero. */
+ if_info->magic_number = 0;
rtx a = if_info->a;
rtx b = if_info->b;
@@ -1204,9 +1230,9 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
&& CONST_INT_P (XEXP (a, 1))
&& CONST_INT_P (XEXP (b, 1))
&& rtx_equal_p (XEXP (a, 0), XEXP (b, 0))
- && noce_operand_ok (XEXP (a, 0))
- && if_info->branch_cost >= 2)
+ && noce_operand_ok (XEXP (a, 0)))
{
+ if_info->magic_number = 2;
common = XEXP (a, 0);
a = XEXP (a, 1);
b = XEXP (b, 1);
@@ -1278,23 +1304,33 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
else
gcc_unreachable ();
}
- else if (ifalse == 0 && exact_log2 (itrue) >= 0
- && (STORE_FLAG_VALUE == 1
- || if_info->branch_cost >= 2))
- normalize = 1;
- else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse
- && (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2))
+ else if (ifalse == 0 && exact_log2 (itrue) >= 0)
{
+ if_info->magic_number = 2;
+ if (STORE_FLAG_VALUE == 1)
+ no_cost_model = true;
+ normalize = 1;
+ }
+ else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse)
+ {
+ if_info->magic_number = 2;
+ if (STORE_FLAG_VALUE == 1)
+ no_cost_model = true;
normalize = 1;
reversep = true;
}
- else if (itrue == -1
- && (STORE_FLAG_VALUE == -1
- || if_info->branch_cost >= 2))
- normalize = -1;
- else if (ifalse == -1 && can_reverse
- && (STORE_FLAG_VALUE == -1 || if_info->branch_cost >= 2))
+ else if (itrue == -1)
{
+ if_info->magic_number = 2;
+ if (STORE_FLAG_VALUE == -1)
+ no_cost_model = true;
+ normalize = -1;
+ }
+ else if (ifalse == -1 && can_reverse)
+ {
+ if_info->magic_number = 2;
+ if (STORE_FLAG_VALUE == -1)
+ no_cost_model = true;
normalize = -1;
reversep = true;
}
@@ -1385,6 +1421,10 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
if (!seq)
return FALSE;
+ /* Check if this is actually beneficial. */
+ if (!no_cost_model && !noce_is_profitable_p (seq, if_info))
+ return FALSE;
+
emit_insn_before_setloc (seq, if_info->jump,
INSN_LOCATION (if_info->insn_a));
return TRUE;
@@ -1446,8 +1486,7 @@ 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
- && (XEXP (if_info->a, 1) == const1_rtx
+ if ((XEXP (if_info->a, 1) == const1_rtx
|| XEXP (if_info->a, 1) == constm1_rtx))
{
start_sequence ();
@@ -1477,6 +1516,11 @@ noce_try_addcc (struct noce_if_info *if_info)
if (!seq)
return FALSE;
+ /* Check if this is actually beneficial. */
+ if_info->magic_number = 2;
+ if (!noce_is_profitable_p (seq, if_info))
+ return FALSE;
+
emit_insn_before_setloc (seq, if_info->jump,
INSN_LOCATION (if_info->insn_a));
return TRUE;
@@ -1501,15 +1545,14 @@ noce_try_store_flag_mask (struct noce_if_info *if_info)
return FALSE;
reversep = 0;
- if ((if_info->branch_cost >= 2
- || STORE_FLAG_VALUE == -1)
- && ((if_info->a == const0_rtx
+
+ if ((if_info->a == const0_rtx
&& rtx_equal_p (if_info->b, if_info->x))
|| ((reversep = (reversed_comparison_code (if_info->cond,
if_info->jump)
!= UNKNOWN))
&& if_info->b == const0_rtx
- && rtx_equal_p (if_info->a, if_info->x))))
+ && rtx_equal_p (if_info->a, if_info->x)))
{
start_sequence ();
target = noce_emit_store_flag (if_info,
@@ -1523,7 +1566,7 @@ noce_try_store_flag_mask (struct noce_if_info *if_info)
if (target)
{
- int old_cost, new_cost, insn_cost;
+ int new_cost, old_cost;
int speed_p;
if (target != if_info->x)
@@ -1533,12 +1576,26 @@ noce_try_store_flag_mask (struct noce_if_info *if_info)
if (!seq)
return FALSE;
+ /* The previous costing code here calculated everything in the
+ rtx_cost base, and compared it against
+ COSTS_N_INSNS (if_info->branch_cost). As we don't want to
+ multiply branch cost, instead divide through by
+ COSTS_N_INSNS (1) to get our magic_number. We also need to
+ take account of a possible magic_number of 2 which should
+ be applied if STORE_FLAG_VALUE != -1. */
speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (if_info->insn_a));
- insn_cost = insn_rtx_cost (PATTERN (if_info->insn_a), speed_p);
- old_cost = COSTS_N_INSNS (if_info->branch_cost) + insn_cost;
+ old_cost = insn_rtx_cost (PATTERN (if_info->insn_a), speed_p);
new_cost = seq_cost (seq, speed_p);
+ if_info->magic_number = (new_cost - old_cost);
+ if_info->magic_number
+ = (if_info->magic_number / COSTS_N_INSNS (1))
+ + ((if_info->magic_number % COSTS_N_INSNS (1)) ? 1 : 0);
- if (new_cost > old_cost)
+ if_info->magic_number
+ = MAX (((STORE_FLAG_VALUE != -1) ? 2 : 0),
+ (if_info->magic_number));
+
+ if (!noce_is_profitable_p (seq, if_info))
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
@@ -1703,9 +1760,7 @@ noce_try_cmove (struct noce_if_info *if_info)
we don't know about, so give them a chance before trying this
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))
+ && CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b))
{
machine_mode mode = GET_MODE (if_info->x);
HOST_WIDE_INT ifalse = INTVAL (if_info->a);
@@ -1744,6 +1799,12 @@ noce_try_cmove (struct noce_if_info *if_info)
if (!seq)
return FALSE;
+ /* Check if this is actually beneficial. */
+ if_info->magic_number = STORE_FLAG_VALUE == -1
+ ? 2 : 3;
+ if (!noce_is_profitable_p (seq, if_info))
+ return FALSE;
+
emit_insn_before_setloc (seq, if_info->jump,
INSN_LOCATION (if_info->insn_a));
return TRUE;
@@ -1930,7 +1991,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
conditional on their addresses followed by a load. Don't do this
early because it'll screw alias analysis. Note that we've
already checked for no side effects. */
- /* ??? FIXME: Magic number 5. */
+ /* ??? FIXME: Magic number 5. We cost this here rather than through
+ noce_is_profitable_p as the fallback cases below can produce viable
+ transformations in the case where (if_info->branch_cost < 5). */
if (cse_not_expected
&& MEM_P (a) && MEM_P (b)
&& MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b)
@@ -1973,10 +2036,12 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
else
else_cost = 0;
- /* We're going to execute one of the basic blocks anyway, so
- bail out if the most expensive of the two blocks is unacceptable. */
- if (MAX (then_cost, else_cost) > COSTS_N_INSNS (if_info->branch_cost))
- return FALSE;
+ /* We want the most expensive of the above, divided through by
+ COSTS_N_INSNS (1). */
+ if_info->magic_number = MAX (then_cost, else_cost);
+ if_info->magic_number
+ = (if_info->magic_number / COSTS_N_INSNS (1))
+ + ((if_info->magic_number % COSTS_N_INSNS (1)) ? 1 : 0);
/* Possibly rearrange operands to make things come out more natural. */
if (reversed_comparison_code (if_info->cond, if_info->jump) != UNKNOWN)
@@ -2115,6 +2180,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
if (!ifcvt_seq)
return FALSE;
+ if (!noce_is_profitable_p (ifcvt_seq, if_info))
+ return FALSE;
+
emit_insn_before_setloc (ifcvt_seq, if_info->jump,
INSN_LOCATION (if_info->insn_a));
return TRUE;
@@ -2571,7 +2639,12 @@ noce_try_sign_mask (struct noce_if_info *if_info)
non-zero (T) value and if INSN_B was taken from TEST_BB, or there was no
INSN_B which can happen for e.g. conditional stores to memory. For the
cost computation use the block TEST_BB where the evaluation will end up
- after the transformation. */
+ after the transformation.
+ ??? The underlying calculation is a natural fit for the long term
+ direction of noce_is_profitable_p, but there is no way to transform
+ this cost calculation in to a comparison against branch_cost. When
+ noce_is_profitable_p becomes a proper cost calulcation, this logic
+ should be cleaned up. */
t_unconditional =
(t == if_info->b
&& (if_info->insn_b == NULL_RTX