------- Comment #1 from uweigand at gcc dot gnu dot org  2010-06-29 16:56 
-------
I agree, this looks like a longstanding bug in
rs6000_legitimize_reload_address.

What happens here is that find_reloads is called on this insn:

(insn 15 8 18 2 pr44707.c:13 (asm_operands/v ("/* %0 %1 %2 %3 %4 */") ("") 0 [
            (mem/s/c:SI (symbol_ref:SI ("v") [flags 0xc0] <var_decl 0xf6f90fc0
v>) [3 v.a+0 S4 A32])
            (mem/c/i:SI (symbol_ref:SI ("w") [flags 0xc4] <var_decl 0xf6f91020
w>) [3 w+0 S4 A32])
            (mem/s/c:SI (const:SI (plus:SI (symbol_ref:SI ("v") [flags 0xc0]
<var_decl 0xf6f90fc0 v>)
                        (const_int 4 [0x4]))) [3 v.b+0 S4 A32])
            (mem/s/c:SI (const:SI (plus:SI (symbol_ref:SI ("v") [flags 0xc0]
<var_decl 0xf6f90fc0 v>)
                        (const_int 8 [0x8]))) [3 v.c+0 S4 A32])
            (mem/s/c:SI (const:SI (plus:SI (symbol_ref:SI ("v") [flags 0xc0]
<var_decl 0xf6f90fc0 v>)
                        (const_int 12 [0xc]))) [3 v.d+0 S4 A32])
        ]
         [
            (asm_input:SI ("nro") (null):0)
            (asm_input:SI ("nro") (null):0)
            (asm_input:SI ("nro") (null):0)
            (asm_input:SI ("nro") (null):0)
            (asm_input:SI ("nro") (null):0)
        ]
         [] pr44707.c:14) -1 (nil))

rs6000_find_reloads_address notices that it can rewrite
  (symbol_ref:SI "v")
to
  (lo_sum:SI (high:SI (symbol_ref:SI "v")) (symbol_ref:SI "v"))
(and place a reload on the (high:SI) subexpression) and does so.  This change
remains in the insn, and when in the next iteration find_reloads is called
again, the insn now looks like:

(insn 15 8 18 2 pr44707.c:13 (asm_operands/v ("/* %0 %1 %2 %3 %4 */") ("") 0 [
            (mem/s/c:SI (lo_sum:SI (high:SI (symbol_ref:SI ("v") [flags 0xc0]
<var_decl 0xf6f90fc0 v>))
                    (symbol_ref:SI ("v") [flags 0xc0] <var_decl 0xf6f90fc0 v>))
[3 v.a+0 S4 A32])
            (mem/c/i:SI (lo_sum:SI (high:SI (symbol_ref:SI ("w") [flags 0xc4]
<var_decl 0xf6f91020 w>))
                    (symbol_ref:SI ("w") [flags 0xc4] <var_decl 0xf6f91020 w>))
[3 w+0 S4 A32])
            (mem/s/c:SI (const:SI (plus:SI (symbol_ref:SI ("v") [flags 0xc0]
<var_decl 0xf6f90fc0 v>)
                        (const_int 4 [0x4]))) [3 v.b+0 S4 A32])
            (mem/s/c:SI (const:SI (plus:SI (symbol_ref:SI ("v") [flags 0xc0]
<var_decl 0xf6f90fc0 v>)
                        (const_int 8 [0x8]))) [3 v.c+0 S4 A32])
            (mem/s/c:SI (const:SI (plus:SI (symbol_ref:SI ("v") [flags 0xc0]
<var_decl 0xf6f90fc0 v>)
                        (const_int 12 [0xc]))) [3 v.d+0 S4 A32])
        ]
         [
            (asm_input:SI ("nro") (null):0)
            (asm_input:SI ("nro") (null):0)
            (asm_input:SI ("nro") (null):0)
            (asm_input:SI ("nro") (null):0)
            (asm_input:SI ("nro") (null):0)
        ]
         [] pr44707.c:14) -1 (nil))

However, this expression is now no longer recognized by
rs6000_legitimize_reload_address, and therefore no reload on (high:SI) is
pushed.

Thus, when the reload is finally processed, a reload insn like this is
generated:

(insn 26 8 27 2 pr44707.c:13 (set (reg:SI 10 10)
        (lo_sum:SI (high:SI (symbol_ref:SI ("v") [flags 0xc0] <var_decl
0xf6f90fc0 v>))
            (symbol_ref:SI ("v") [flags 0xc0] <var_decl 0xf6f90fc0 v>))) -1
(nil))

As this does not actually correspond to any valid pattern, an assertion is
triggered.

The underlying problem is that with the current reload setup, an implementation
of LEGITIMATE_RELOAD_ADDRESS must always recognize expressions it has itself
generated in an earlier call.  And indeed, that's what a comment in
rs6000_legitimize_reload_address says:

static rtx
rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
                                  int opnum, int type,
                                  int ind_levels ATTRIBUTE_UNUSED, int *win)
{
  bool reg_offset_p = reg_offset_addressing_ok_p (mode);

  /* We must recognize output that we have already generated ourselves.  */
  if (GET_CODE (x) == PLUS
      && GET_CODE (XEXP (x, 0)) == PLUS
      && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
      && GET_CODE (XEXP (x, 1)) == CONST_INT)


However, this recognizes only certain types of such output, and in particular
not the one that shows up in this test case.

It seems to me that simply extending rs6000_legitimate_reload_address to handle
this case as well should fix the bug.


-- 

uweigand at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
     Ever Confirmed|0                           |1
   Last reconfirmed|0000-00-00 00:00:00         |2010-06-29 16:56:47
               date|                            |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44707

Reply via email to