Hi Jeff

Thanks for the review!

> So you can't just raise BRANCH_COST to fix this? That's the traditional
> big hammer solution.

Thank you for the suggestion. You're right that raising BRANCH_COST 
sufficiently makes this case if-convert. My concern is that changing it 
globally also affects other expansion and RTL profitability decisions, rather 
than just this particular noce transformation.

Current threshold
I compared the current TARGET_MAX_NOCE_IFCVT_SEQ_COST implementations:
/* Generic default.  */
return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (3);
/* i386.  */
return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (2);
/* RISC-V.  */
return COSTS_N_INSNS (BRANCH_COST (true, predictable_p));

With BRANCH_COST == 4, these correspond to thresholds of 48, 32 and 16. This 
made the current RISC-V threshold appear relatively conservative, particularly 
when Zicond is available.

Increasing it globally may therefore generate more branchless code in unrelated 
places, including cases where the branch is actually predicted well by the 
hardware.
Instead, I was considering restricting the adjustment to the RISC-V noce 
threshold:

unsigned int factor = 1;
if (!predictable_p && TARGET_ZICOND)
  factor = tune_param->noce_ifcvt_unpredictable_cost_factor;
return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (factor);

The factor defaults to 1. A larger value is selected only by a particular tune, 
and only for an unpredictable edge when Zicond is available. Predictable edges 
and targets without Zicond retain the existing threshold.

> It might also help if you passed along a testcase. I've found many of
> the failure to if-convert problems are due to inefficiencies in the
> sequences we generate; we can often get if-conversion to fire by
> generating better generic sequences and fixing costing goofs elsewhere.

The case is in spec_qsort from 505.mcf_r. It occurs after med3 and its 
comparator have both been inlined into spec_qsort. The relevant call is:
pn = med3 (pn - 2 * d, pn - d, pn, cmp);
After inlining, the same ID condition controls three pointer selections. RTL 
if-conversion initially costs the candidate sequence at 48 cost units, 
equivalent to 12 instructions. A maximum cost of 47 does not trigger the 
conversion, while 48 does.
After later RTL optimization, the final sequence is reduced to:
1 slt
6 czero
3 add
This is 10 instructions, or 40 cost units. It appears that redundant condition 
calculations included in the initial candidate are removed by later passes.
The two preceding abs_cost comparisons remain branches. Only the final ID 
tie-breaker and the three dependent pointer selections are converted.

Best regards,
Wang Jue

Reply via email to