IRA issue with shuffle copies...
Vladimir Makarov
vmakarov@redhat.com
Tue Jan 10 18:01:00 GMT 2012
On 01/07/2012 12:24 AM, Peter Bergner wrote:
> Hi Vlad,
>
> While debugging a slightly modified version of the test case in PR16458:
>
> int
> foo (unsigned int a, unsigned int b)
> {
> if (a == b) return 1;
> if (a> b) return 2;
> if (a< b) return 3;
> if (a != b) return 4;
> return 0;
> }
>
> I noticed a couple of ugly code gen warts which I tracked back to IRA.
> Namely, compiling the above with -O2 -m32 on powerpc64-linux, I'm seeing:
>
> li 9,3
> mr 3,9
> blr
> and:
> li 9,1
> mr 3,9
> blr
>
> If we look at the rtl just before IRA, we have the following:
>
> BB2:
> (set (reg/v:SI 122 [ a ]) (reg:SI 3 3 [ a ])) REG_DEAD (reg:SI 3 3 [ a ])
> (set (reg/v:SI 123 [ b ]) (reg:SI 4 4 [ b ])) REG_DEAD (reg:SI 4 4 [ b ])
> (set (reg:CC 124) (compare:CC (reg/v:SI 122 [ a ]) (reg/v:SI 123 [ b ])))
> (if_then_else (eq (reg:CC 124) (const_int 0 [0]))
> goto BB6;
>
> BB3:
> (set (reg:CCUNS 125) (compare:CCUNS (reg/v:SI 122 [ a ]) (reg/v:SI 123 [ b ]))) REG_DEAD (reg/v:SI 123 [ b ])
> REG_DEAD (reg/v:SI 122 [ a ])
> (set (reg:SI 120 [ D.1379 ]) (const_int 2 [0x2]))
> (if_then_else (gtu (reg:CC 124) (const_int 0 [0]))
> goto BB8;
>
> BB4:
> (if_then_else (geu (reg:CC 124) (const_int 0 [0]))
> goto BB7;
>
> BB5:
> (set (reg:SI 120 [ D.1379 ]) (const_int 3 [0x3]))
> goto BB8;
>
> BB6:
> (set (reg:SI 120 [ D.1379 ]) (const_int 1 [0x1]))
> goto BB8;
>
> BB7:
> (set (reg:SI 120 [ D.1379 ]) (const_int 4 [0x4]))
>
> BB8:
> (set (reg/i:SI 3 3) (reg:SI 120 [ D.1379 ])) REG_DEAD (reg:SI 120 [ D.1379 ])
> (use (reg/i:SI 3 3))
> return
>
> When we start coloring the allocnos, we get the following:
>
> Pass 1 for finding pseudo/allocno costs
>
> r125: preferred CR_REGS, ...
> r124: preferred CR_REGS, ...
> r123: preferred GENERAL_REGS, ...
> r122: preferred GENERAL_REGS, ...
> r120: preferred GENERAL_REGS, ...
>
> ...
>
> Popping a3(r122,l0) -- assign reg 3
> Popping a2(r123,l0) -- assign reg 4
> Popping a0(r120,l0) -- assign reg 9
> Popping a4(r124,l0) -- assign reg 75
> Popping a1(r125,l0) -- assign reg 3
> Assigning 75 to a1r125
>
> This looks a little startling, since we're initially assigning r125 to r3,
> even though it's preferred class is CR_REGS before improve_allocation()
> saves us and reassigns r125 to r75 (a real CR reg). The reason r125
> ends up initially in r3 is that we detect a "shuffle" copy during the
> set of r125, because r122 (and r123) dies in the insn r125 is defined in.
> This ends up preferencing the costs for r125, such that it wants r3.
> This in turn via ALLOCNO_UPDATED_HARD_REG_COSTS() increases the cost
> of assigning r120 to r3, such that r120 ends up with r9 instead, when
> we really really want it to get r3.
>
Thanks for the analysis, Peter.
> Your comments about the "shuffle" copies seem to infer that they're being
> used to try and help insns with two operand contraints, but in the case
> above, they're over preferencing things. As an experiment, I disabled all
> shuffle copies and the code gen for the test case above is much improved.
>
> Do we really need or want to create shuffle copies for insns that do not
> have a two operand constraint?
Yes, I think so. As I remember I did some benchmarking and it gave some
"order" in hard register assignments and improved code slightly (at
least for SPEC2000) even for 3-ops insn architectures.
> If not, do you know how we can test for that?
> If you think we do need that for non two operand contraint insns, can we
> at least disable creating shuffle copies for allocnos that have different
> preferred classes, since they're probably not going to be assigned the
> same hard reg?
I guess we could try this and it might work.
> Ala:
>
> Index: ira-conflicts.c
> ===================================================================
> --- ira-conflicts.c (revision 182936)
> +++ ira-conflicts.c (working copy)
> @@ -397,6 +397,11 @@ process_regs_for_copy (rtx reg1, rtx reg
> enum machine_mode mode;
> ira_copy_t cp;
>
> + if (!constraint_p
> +&& reg_preferred_class (REGNO (reg1))
> + != reg_preferred_class (REGNO (reg2)))
> + return false;
> +
> gcc_assert (REG_SUBREG_P (reg1)&& REG_SUBREG_P (reg2));
> only_regs_p = REG_P (reg1)&& REG_P (reg2);
> reg1 = go_through_subreg (reg1,&offset1);
>
>
> Your thoughts?
>
>
Your patch might work. But we need to test it for major 2-ops
architecture x86/x86-64 and 3-ops ppc (I believe SPEC2000 would be ok
for this).
More information about the Gcc
mailing list