This is the mail archive of the gcc-patches@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]

Re: 980424-0.f



The basic problem is we have something like this:

(insn 21 19 23 (set (reg:DI 24)
        (const_int 0)) 84 {movdi+1} (nil)
    (expr_list:REG_EQUIV (const_int 0)
        (nil)))

[ ... ]

(insn 26 24 27 (parallel[             
            (set (cc0)
                (compare:CCFPEQ (subreg:SF (reg:DI 23) 1)
                    (subreg:SF (reg:DI 24) 1)))
            (clobber (scratch:HI))
        ] ) 35 {cmpxf-1} (nil)
    (expr_list:REG_DEAD (reg:DI 23)
        (expr_list:REG_DEAD (reg:DI 24)
            (expr_list:REG_UNUSED (scratch:HI)
                (nil)))))



We substitute (const_int 0) for the (subreg:SF (reg:DI 24) 1).

A CONST_INT is not allowed for that particular operand, so we end
up trying to reload it into an fp register.  So we end up with stuff
like this after reload:

(insn 72 69 26 (set (reg:SF 9 %st(1))
        (const_int 0)) -1 (nil)
    (nil))

;; Start of basic block 1, registers live: 6 [bp] 7 [sp] 22 23 24
(insn:HI 26 72 27 (parallel[
            (set (cc0)
                (compare:CCFPEQ (reg:SF 8 %st(0))
                    (reg:SF 9 %st(1))))
            (clobber (reg:HI 0 %ax))
        ] ) 35 {cmpxf-1} (nil)
    (expr_list:REG_DEAD (mem:DI (plus:SI (reg:SI 6 %ebp)
                (const_int -12)))
        (expr_list:REG_DEAD (reg:DI 24)
            (expr_list:REG_UNUSED (reg:HI 0 %ax)
                (nil)))))

There is no pattern which patches insn 72.  This is the first sign of trouble
eventually leading on the abort in reg-stack.c.


The substitution of (const_int 0) into insn 26 happens due to this code
in find_reloads:



      /* Check for SUBREG containing a REG that's equivalent to a constant.
         If the constant has a known value, truncate it right now.
         Similarly if we are extracting a single-word of a multi-word
         constant.  If the constant is symbolic, allow it to be substituted
         normally.  push_reload will strip the subreg later.  If the
         constant is VOIDmode, abort because we will lose the mode of
         the register (this should never happen because one of the cases
         above should handle it).  */

      register int regno = REGNO (SUBREG_REG (x));
      rtx tem;

      if (subreg_lowpart_p (x)
          && regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
          && reg_equiv_constant[regno] != 0
          && (tem = gen_lowpart_common (GET_MODE (x),
                                        reg_equiv_constant[regno])) != 0)
        return tem;

      if (GET_MODE_BITSIZE (GET_MODE (x)) == BITS_PER_WORD
          && regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
          && reg_equiv_constant[regno] != 0
          && (tem = operand_subword (reg_equiv_constant[regno],
                                     SUBREG_WORD (x), 0,
                                     GET_MODE (SUBREG_REG (x)))) != 0)
        return tem;

Specifically the second if conditional is true (we're not replacing the
lowpart).

Since the mode of SUBREG_REG (x) is an integer mode, operand_subword returns
(const_int 0).  If instead we returned a (const_double) we'd be OK.

In fact, that's exactly what happens if we're dealing with the lowpart --
the value is returned according to the mode of x, not SUBREG_REG (x).

It seems to me that we can "tem = gen_lowpart_common (GET_MODE (x), tem)"
in the true arm of the second if and return the resulting "tem".

ie, we've used operand_subword to extract the word we wanted, but
the representation of the word isn't necessarily what we needed.

So we use gen_lowpart_common to convert the result of operand_subword
into something useful.

Note that after this change, we *might* be able to delete the first 
if conditional.  I haven't actually tried it to see what would happen.

Thoughts?

	* reload.c (find_reloads_toplev): Use gen_lowpart common to convert
	between constant representations when we have (SUBREG (REG)) with
	REG equivalent to a constant.

[ Not real happy with the ChangeLog entry... :( ]

/puke/*** reload.c	Tue Jun  2 01:58:51 1998
--- reload.c.SAVE	Tue Jun  2 02:05:00 1998
*************** find_reloads_toplev (x, opnum, type, ind
*** 4289,4295 ****
  	  && (tem = operand_subword (reg_equiv_constant[regno],
  				     SUBREG_WORD (x), 0,
  				     GET_MODE (SUBREG_REG (x)))) != 0)
! 	return tem;
  
        /* If the SUBREG is wider than a word, the above test will fail.
  	 For example, we might have a SImode SUBREG of a DImode SUBREG_REG
--- 4289,4306 ----
  	  && (tem = operand_subword (reg_equiv_constant[regno],
  				     SUBREG_WORD (x), 0,
  				     GET_MODE (SUBREG_REG (x)))) != 0)
! 	{
! 	  /* TEM is now a word sized constant for the bits from X that
! 	     we wanted.  However, TEM may be the wrong representation.
! 
! 	     Use gen_lowpart_common to convert a CONST_INT into a
! 	     CONST_DOUBLE and vice versa as needed according to by the mode
! 	     of the SUBREG.  */
! 	  tem = gen_lowpart_common (GET_MODE (x), tem);
! 	  if (!tem)
! 	    abort ();
! 	  return tem;
! 	}
  
        /* If the SUBREG is wider than a word, the above test will fail.
  	 For example, we might have a SImode SUBREG of a DImode SUBREG_REG



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