https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77289

Peter Bergner <bergner at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |vmakarov at gcc dot gnu.org

--- Comment #4 from Peter Bergner <bergner at gcc dot gnu.org> ---
Adding Vlad since there are IRA and LRA questions.


(In reply to Segher Boessenkool from comment #2)
> It already goes wrong at IRA:
> 
[snip]
> 
> (define_insn "*movsf_update1"
>   [(set (match_operand:SF 3 "gpc_reg_operand" "=f,f")
>         (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
>                          (match_operand:SI 2 "reg_or_short_operand" "r,I"))))
>    (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
>         (plus:SI (match_dup 1) (match_dup 2)))]
> 
> so operand 1 is not the same as operand 0.

I'm not sure if IRA is supposed to always assign operand 1 the same register as
operand 0 here, or whether that is reload/LRA's job.  Vlad?

I will say that with -mno-lra, reload handles the above just fine, by noticing
that the two operands do not have the same register and forces a reload that
fixes things up.

The same does not happen in LRA, even though it does check.  What happens is
that lra-constraints.c:process_alt_operands() (line #1991) which does the
checking, uses operands_match_p()/get_hard_regno() to check if the two operands
are the same.  Before get_hard_regno() returns its hardreg #, it passes it to
get_final_hard_regno(), which in turn passes it to
lra_get_elimination_hard_regno().  In the case above, reg 208 has been assigned
r31, but lra_get_elimination_hard_regno(31) returns r1 since r31 can be
eliminated to r1 normally.  Since r1 was returned for operand 0 instead of r31,
it looks like our insn satisfies its constraints by having operand 0 and
operand 1 being assigned to the same register, so we don't modify it.  However,
later when LRA calls check_rtl/extract_constrain_insn, they doesn't recognize
r31 and r1 as being the same, so it throws an ICE.

In the case above, I'm not sure we can eliminate r31 in favor of r1, since this
is a load with update insn and I don't think we can use r1 as the address reg,
since the update would clobber the stack pointer.  If I add the following hack:

Index: lra-constraints.c
===================================================================
--- lra-constraints.c   (revision 239609)
+++ lra-constraints.c   (working copy)
@@ -2010,8 +2010,10 @@ process_alt_operands (int only_alternati
                       this alternative may be rejected when it is
                       actually desirable.)  */
                    match_p = false;
-                   if (operands_match_p (*curr_id->operand_loc[nop],
-                                         *curr_id->operand_loc[m], m_hregno))
+                   if (m_hregno != STACK_POINTER_REGNUM
+                       && operands_match_p (*curr_id->operand_loc[nop],
+                                            *curr_id->operand_loc[m],
+                                            m_hregno))
                      {
                        /* We should reject matching of an early
                           clobber operand if the matching operand is

...then it passes and generates the same code reload does.

Vlad, should we be disallowing matching of eliminable registers here or just
special ones like stack pointers and maybe others?  If so, I guess we could add
a strict param to get_hard_regno() and get_final_hard_regno() that doesn't
allow eliminable registers by not calling lra_get_elimination_hard_regno() when
strict.  Thoughts?

Reply via email to