IRA observation/question

Vladimir Makarov vmakarov@redhat.com
Tue May 17 16:08:00 GMT 2011


On 05/16/2011 05:00 PM, Pat Haugen wrote:
> I'm seeing some odd behavior in ira for PowerPC, starting with the big 
> ira merge best I can tell (r171649).
>
> void foo(float *f1, float*f2) {
>   *f1 = *f2;
> }
>
> If I compile with gcc -S -m64 -O3 -mcpu=power7 and look at the ira 
> dump, I see that the pseudo used to copy the data, r120, is spilled. 
> Reload comes along and fixes up this simple example so we end up with 
> just a load/store for the copy, but spilling when we have plenty of 
> available registers is obviously wrong.
>
> Portion of the ira dump:
>
>
> Pass 0 for finding pseudo/allocno costs
>
>
>   r120 costs: BASE_REGS:0 GENERAL_REGS:0 FLOAT_REGS:0 VSX_REGS:2000000 
> NON_SPECIAL_REGS:16000 LINK_REGS:4000 CTR_REGS:4000 
> LINK_OR_CTR_REGS:4000 SPECIAL_REGS:4000 SPEC_OR_GEN_REGS:4000 
> NON_FLOAT_REGS:2000000 ALL_REGS:2000000 MEM:8000
>
>
> Pass 1 for finding pseudo/allocno costs
>
>     r122: preferred ALL_REGS, alternative NO_REGS, allocno ALL_REGS
>     r121: preferred ALL_REGS, alternative NO_REGS, allocno ALL_REGS
>     r120: preferred SPEC_OR_GEN_REGS, alternative NO_REGS, allocno 
> SPEC_OR_GEN_REGS
>     r119: preferred ALL_REGS, alternative NO_REGS, allocno ALL_REGS
>     r118: preferred ALL_REGS, alternative NO_REGS, allocno ALL_REGS
>     r117: preferred ALL_REGS, alternative NO_REGS, allocno ALL_REGS
>     r116: preferred ALL_REGS, alternative NO_REGS, allocno ALL_REGS
>     r115: preferred ALL_REGS, alternative NO_REGS, allocno ALL_REGS
>     r114: preferred ALL_REGS, alternative NO_REGS, allocno ALL_REGS
>
>   r120 costs: VSX_REGS:2000000 NON_SPECIAL_REGS:16000 LINK_REGS:4000 
> CTR_REGS:4000 LINK_OR_CTR_REGS:4000 SPECIAL_REGS:4000 
> SPEC_OR_GEN_REGS:4000 NON_FLOAT_REGS:2000000 ALL_REGS:2000000 MEM:8000
>
> Building IRA IR
> starting the processing of deferred insns
> ending the processing of deferred insns
> df_analyze called
> init_insns for 120: (insn_list:REG_DEP_TRUE 8 (nil))
>
> Pass 1 for finding pseudo/allocno costs
>
>     r120: preferred NO_REGS, alternative NO_REGS, allocno NO_REGS
>     a0 (r120,l0) best NO_REGS, allocno NO_REGS
>
>   a0(r120,l0) costs: FLOAT_REGS:16000,16000 VSX_REGS:2000000,2000000 
> NON_SPECIAL_REGS:16000,16000 SPEC_OR_GEN_REGS:4000,4000 
> NON_FLOAT_REGS:2000000,2000000 ALL_REGS:2000000,2000000 MEM:0,0
>
> ...
>
> **** Allocnos coloring:
>
>
>   Loop 0 (parent -1, header bb0, depth 0)
>     bbs: 2
>     all: 0r120
>     modified regnos: 120
>     border:
>     Pressure: NON_FLOAT_REGS=2
>     Hard reg set forest:
>       0:( 0 3-12 14-63 65 66 68-72 74 75 77-108)@0
>       Spill a0(r120,l0)
> Disposition:
>     0:r120 l0   mem
>
>
> Things start to go wrong during the first pass of 
> find_costs_and_classes, while walking the list of cost_classes to find 
> the best. If two classes have the same cost (such as GENERAL_REGS and 
> FLOAT_REGS in this example) the following portion of code grabs a 
> union of them.
>
>               else if (i_costs[k] == best_cost)
>                 best = ira_reg_class_subunion[best][rclass];
>
> In this case that class is NON_SPECIAL_REGS, which has a cost greater 
> than both due to the fact that move cost for GPR<->FPR needs to go 
> through memory, and may_move_[in|out]_cost use maximal cost when 
> computing cost such as NON_SPECIAL<->[GENERAL|FLOAT].  Picking 
> NON_SPECIAL for the best class during the first iteration then affects 
> subsequent iterations until it's decided that memory is best.
>
> The following change fixes the problem by not updating the best_cost 
> if the union has a greater cost. Is this the correct approach or is 
> there more to it than this?
>
Thanks for pointing this out, Pat.  Your patch could fix this particular 
problem but using GENERAL_REGS only is wrong.  The final allocno class 
should be NON_SPECIAL_REGS.  I will search for a better solution.  
Unfortunately, such changes in the code should be benchmarked on a few 
major targets.  So it will take some time (a weak or two) to fix the 
problem.
> ===================================================================
> --- gcc/ira-costs.c     (revision 173392)
> +++ gcc/ira-costs.c     (working copy)
> @@ -1697,7 +1697,14 @@ find_costs_and_classes (FILE *dump_file)
>                   best = (enum reg_class) rclass;
>                 }
>               else if (i_costs[k] == best_cost)
> -               best = ira_reg_class_subunion[best][rclass];
> +               {
> +                 enum reg_class temp_class;
> +                 temp_class = ira_reg_class_subunion[best][rclass];
> +                 if (cost_classes_ptr->index[temp_class] != -1
> + && i_costs[cost_classes_ptr->index[temp_class]]
> + <= best_cost)
> +                   best = temp_class;
> +               }
>               if (pass == flag_expensive_optimizations
> && i_costs[k] < i_mem_cost
> && (reg_class_size[reg_class_subunion[alt_class][rclass]]
>
>
>  One thing I did notice with this change is that we'll now pick 
> GENERAL_REGS as best on the first pass, which then causes FLOAT_REGS 
> to be expensive on subsequent passes. Seems like for this example 
> where GENERAL/FLOAT are equally best, one would be the preferred class 
> and the other would be the alternative class. But the same thing 
> happens with compilers prior to the ira merge mentioned above, so 
> guessing it's a separate issue.
>
Yes, it is a separate issue.  Setting up right alternative/preferred 
class is necessary mainly for correct work of reload which for some 
reasons is very sensitive to this.  The alternative/preferred class is 
not used for IRA itself.



More information about the Gcc mailing list