From: Kyrylo Tkachov <[email protected]>
noce_process_if_block estimates the cost of the branch it wants to remove
twice: once for the multiple-set candidate and once for the single-set path.
Both compute the same thing on top of the same base cost, namely the
branch-probability-weighted average of the two arms when optimising for speed
and their sum when optimising for size, but the two are written out
separately.
Move the formula into noce_original_region_cost and call it from both sites.
The local holding the base cost is renamed from old_cost to base_cost, which
describes what it holds, and the speed test both estimates need is hoisted to
sit beside it rather than being asked for twice. The estimates are unchanged,
so this is no functional change.
gcc/ChangeLog:
* ifcvt.cc (noce_original_region_cost): New function.
(noce_process_if_block): Use it for the multiple-set and the
single-set estimate. Rename old_cost to base_cost and compute
speed_p once.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/ifcvt.cc | 64 ++++++++++++++++++++++++++++++----------------------
1 file changed, 37 insertions(+), 27 deletions(-)
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index f0dcc13f786..9528f5f9a55 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -4819,6 +4819,25 @@ average_cost (unsigned then_cost, unsigned else_cost,
edge e)
+ e->probability.apply ((gcov_type) then_cost - else_cost);
}
+/* Return the estimated cost of the original, un-converted if-region described
+ by IF_INFO whose THEN and ELSE arms cost THEN_COST and ELSE_COST. BASE_COST
+ already accounts for the branch, and any compare, that the conversion
+ removes. When optimizing for speed (SPEED_P) only one arm runs, so charge
+ the branch-probability-weighted average of the two. When optimizing for
+ size both arms are emitted, so sum them. */
+
+static unsigned
+noce_original_region_cost (const noce_if_info *if_info, bool speed_p,
+ unsigned base_cost, unsigned then_cost,
+ unsigned else_cost)
+{
+ if (speed_p)
+ return base_cost + average_cost (then_cost, else_cost,
+ find_edge (if_info->test_bb,
+ if_info->then_bb));
+ return base_cost + then_cost + else_cost;
+}
+
/* Target-capability requirements for a noce transform. The dispatcher in
noce_process_if_block skips a transform whose requirements are not met by
the current target, so the transforms themselves need not re-check. */
@@ -4895,13 +4914,15 @@ noce_process_if_block (struct noce_if_info *if_info)
arms.
??? For future expansion, further expand the "multiple X" rules. */
- /* First look for multiple SETS.
- The original costs already include costs for the jump insn as well
- as for a CC comparison if there is any.
- If a target re-uses the existing CC comparison we keep track of that
- and add the costs before default noce_conversion_profitable_p. */
+ /* The base cost recorded so far covers the branch, and any compare, that
+ if-conversion removes. Each candidate path below derives its estimate
+ from this base plus the cost of the arms it folds in. If a target
+ re-uses the existing CC comparison, noce_convert_multiple_sets accounts
+ for that against the base before it calls
+ noce_conversion_profitable_p. */
+ unsigned base_cost = if_info->original_cost;
+ bool speed_p = optimize_bb_for_speed_p (test_bb);
- unsigned old_cost = if_info->original_cost;
unsigned ms_then_cost = 0, ms_else_cost = 0;
unsigned ms_then_insn_count = 0, ms_else_insn_count = 0;
bool ms_then_has_non_simple_src, ms_else_has_non_simple_src;
@@ -4947,21 +4968,13 @@ noce_process_if_block (struct noce_if_info *if_info)
if (multiple_sets_p)
{
/* The original code runs the comparison and one arm. Estimate that cost
- (for a diamond weight the two arms by their probabilities) and let
- noce_convert_multiple_sets convert only if the conditional moves come
- out cheaper. */
- unsigned potential_cost = old_cost + ms_then_cost;
- if (ms_if_info.else_bb)
- {
- if (optimize_bb_for_speed_p (test_bb))
- potential_cost
- = old_cost + average_cost (ms_then_cost, ms_else_cost,
- find_edge (test_bb,
- ms_if_info.then_bb));
- else
- potential_cost = old_cost + ms_then_cost + ms_else_cost;
- }
- ms_if_info.original_cost = potential_cost;
+ and let noce_convert_multiple_sets convert only if the conditional
+ moves come out cheaper. */
+ ms_if_info.original_cost
+ = ms_if_info.else_bb
+ ? noce_original_region_cost (&ms_if_info, speed_p, base_cost,
+ ms_then_cost, ms_else_cost)
+ : base_cost + ms_then_cost;
if (noce_convert_multiple_sets (&ms_if_info))
{
if (dump_file && ms_if_info.transform_name)
@@ -4971,7 +4984,6 @@ noce_process_if_block (struct noce_if_info *if_info)
}
}
- bool speed_p = optimize_bb_for_speed_p (test_bb);
unsigned int then_cost = 0, else_cost = 0;
if (!bb_valid_for_noce_process_p (then_bb, cond, &then_cost,
&if_info->then_simple))
@@ -4982,11 +4994,9 @@ noce_process_if_block (struct noce_if_info *if_info)
&if_info->else_simple))
return false;
- if (speed_p)
- if_info->original_cost += average_cost (then_cost, else_cost,
- find_edge (test_bb, then_bb));
- else
- if_info->original_cost += then_cost + else_cost;
+ if_info->original_cost
+ = noce_original_region_cost (if_info, speed_p, base_cost, then_cost,
+ else_cost);
insn_a = last_active_insn (then_bb, false);
set_a = single_set (insn_a);
--
2.50.1 (Apple Git-155)