The estimate on target_clobbered_registers based on the call_used arrays is not correct. This is the worst case heuristics on the estimate on target_clobbered_registers. This disables many of the loop Invariant code motion opportunities in presence of call. Instead of considering the spill cost we consider only the target_reg_cost aggressively.
With this change with old logic used in regs_used gave the following gains. diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -373,15 +373,23 @@ estimate_reg_pressure_cost (unsigned n_new, unsigned n_old, bool speed, /* If there is a call in the loop body, the call-clobbered registers are not available for loop invariants. */ + if (call_p) available_regs = available_regs - target_clobbered_regs; - + /* If we have enough registers, we should use them and not restrict the transformations unnecessarily. */ if (regs_needed + target_res_regs <= available_regs) return 0; - if (regs_needed <= available_regs) + /* Estimation of target_clobbered register is based on the call_used + arrays which is not the right estimate for the clobbered register + used in called function. Instead of considering the spill cost we + consider only the reg_cost aggressively. */ + + if ((regs_needed <= available_regs) + || (call_p && (regs_needed <= + (available_regs + target_clobbered_regs)))) /* If we are close to running out of registers, try to preserve them. */ cost = target_reg_cost [speed] * n_new; SPEC CPU 2000 INT benchmarks (Geomean Score without the above change vs Geomean score with the above change = 3745.193 vs vs 3752.717) SPEC INT CPU 2000 benchmarks. (Geomean Score without the above change vs Geomean score with the above change = 4741.825 vs 4792.085) Thanks & Regards Ajit