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

           Summary: Reload doesn't handle subreg properly
           Product: gcc
           Version: 4.6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: hjl.to...@gmail.com


Given input:

(plus:SI (subreg:SI (plus:DI (reg/f:DI 7 sp)
            (const_int 16 [0x10])) 0)
    (const_int -1 [0xffffffffffffffff]))

reloads tries to add

(subreg:SI (plus:DI (reg/f:DI 7 sp)
        (const_int 16 [0x10])) 0)

to

(reg:SI 1 dx)

This code:

 /* How to do this reload can get quite tricky.  Normally, we are being
     asked to reload a simple operand, such as a MEM, a constant, or a pseudo
     register that didn't get a hard register.  In that case we can just
     call emit_move_insn.

     We can also be asked to reload a PLUS that adds a register or a MEM to
     another register, constant or MEM.  This can occur during frame pointer
     elimination and while reloading addresses.  This case is handled by
     trying to emit a single insn to perform the add.  If it is not valid,
     we use a two insn sequence.

     Or we can be asked to reload an unary operand that was a fragment of
     an addressing mode, into a register.  If it isn't recognized as-is,
     we try making the unop operand and the reload-register the same:
     (set reg:X (unop:X expr:Y))
     -> (set reg:Y expr:Y) (set reg:X (unop:X reg:Y)).

     Finally, we could be called to handle an 'o' constraint by putting
     an address into a register.  In that case, we first try to do this
     with a named pattern of "reload_load_address".  If no such pattern
     exists, we just emit a SET insn and hope for the best (it will normally
     be valid on machines that use 'o').

     This entire process is made complex because reload will never
     process the insns we generate here and so we must ensure that
     they will fit their constraints and also by the fact that parts of
     IN might be being reloaded separately and replaced with spill registers.
     Because of this, we are, in some sense, just guessing the right approach
     here.  The one listed above seems to work.

     ??? At some point, this whole thing needs to be rethought.  */

  if (GET_CODE (in) == PLUS
      && (REG_P (XEXP (in, 0))
          || GET_CODE (XEXP (in, 0)) == SUBREG
          || MEM_P (XEXP (in, 0)))
      && (REG_P (XEXP (in, 1))
          || GET_CODE (XEXP (in, 1)) == SUBREG
          || CONSTANT_P (XEXP (in, 1))
          || MEM_P (XEXP (in, 1))))

doesn't check if XEXP (in, 0/1) is a SUBREG of REG.

Reply via email to