This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Non-representable subregs of subword pseudoregs


Hello,

I've run into a surprising (to me) behavior of the reload pass: it apparently 
doesn't know how to reload non-representable subregs of subword pseudoregs.
For example on SPARC64:

(insn 22 21 23 1 (set (reg:SI 109 [ D.1130 ])
        (subreg:SI (reg:DI 126) 0)) 51 {*movsi_insn} (nil)
    (nil))

leads to

Reloads for insn # 22
Reload 0: reload_in (SI) = (reg:SI 1 %g1)
	GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 1), can't combine
	reload_in_reg: (subreg:SI (reg:DI 1 %g1 [126]) 0)
	reload_reg_rtx: (reg:SI 5 %g5)

(insn 61 21 22 1 (set (reg:SI 5 %g5)
        (reg:SI 1 %g1)) 51 {*movsi_insn} (nil)
    (nil))

(insn 22 61 23 1 (set (reg:SI 4 %g4 [orig:109 D.1130 ] [109])
        (reg:SI 5 %g5)) 51 {*movsi_insn} (nil)
    (nil))

which is of course wrong since the target is big-endian.


A reload is scheduled because find_reload correctly diagnoses that the subreg 
is not representable:

	  while (GET_CODE (operand) == SUBREG)
	    {
	      /* Offset only matters when operand is a REG and
		 it is a hard reg.  This is because it is passed
		 to reg_fits_class_p if it is a REG and all pseudos
		 return 0 from that function.  */
	      if (REG_P (SUBREG_REG (operand))
		  && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
		{
		  if (!subreg_offset_representable_p
			(REGNO (SUBREG_REG (operand)),
			 GET_MODE (SUBREG_REG (operand)),
			 SUBREG_BYTE (operand),
			 GET_MODE (operand)))
		     force_reload = 1;

However, reload_inner_reg_of_subreg returns false for it (for 2 reasons: it's 
an input reload and the function only looks at output reloads, and subregs of 
subword regs are rejected) so push_reload silently turns the invalid subreg 
into the low part:

  /* If IN is a SUBREG of a hard register, make a new REG.  This
     simplifies some of the cases below.  */

  if (in != 0 && GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))
      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
      && ! dont_remove_subreg)
    in = gen_rtx_REG (GET_MODE (in), subreg_regno (in));


Is this a known limitation of the reload pass or am I missing anything else?
[Jan, I've CCed you because you devised subreg_offset_representable_p.]


The non-representable subreg is created by emit_move_insn_1 when it is invoked 
on pseudo regs and CONCATs with complex modes.  Note that it already has a 
special provision in order not to create non-representable subregs of hard 
regs:

	  /* If this is a complex value with each part being smaller than a
	     word, the usual calling sequence will likely pack the pieces into
	     a single register.  Unfortunately, SUBREG of hard registers only
	     deals in terms of words, so we have a problem converting input
	     arguments to the CONCAT of two registers that is used elsewhere
	     for complex values.  If this is before reload, we can copy it into
	     memory and reload.  FIXME, we should see about using extract and
	     insert on integer registers, but complex short and complex char
	     variables should be rarely used.  */
	  if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
	      && (reload_in_progress | reload_completed) == 0)
	    {
	      int packed_dest_p
		= (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
	      int packed_src_p
		= (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);

	      if (packed_dest_p || packed_src_p)

but it doesn't apply here because we are dealing with pseudo regs.


How is this supposed to work?  Is it simply illegal to create non-lowpart 
subregs of subword pseudo regs?

Thanks in advance.

-- 
Eric Botcazou


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]