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]
Other format: [Raw text]

Re: RFC: subreg fixing (extract_bit_field or simplify_subreg)


On Mon, Nov 01, 2004 at 09:57:11AM -0800, Richard Henderson wrote:
> On Fri, Oct 29, 2004 at 08:22:09PM -0400, Aldy Hernandez wrote:
> > extract_bit_field should be smart enough to do the above magic into a DI, 
> > then copy it into the target (DF).
> 
> Yes.

Wooo aaah!

This is what I whipped up.  It is untested, except on my few testcases.
I wanted to get your input first.

I also fixed convert_move to handle the stupid cases.  I was getting
tired of making subregs by hand for obvious cases.

I added a note/question regarding the clobber, which I believe is unecessary,
as I don't see flow deleting my subreg moves.  Was this clobber to kludge
over some old flow inability, or did I miss something?

Anywhoo... all pretty obvious.  Fixes my problem.  No longer creates
invalid subregs.

Aldy

	* expr.c (convert_move): Handle mixed float mode moves.

	* expmed.c (extract_bit_field): Do not create invalid subregs of
	floats.

Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.737
diff -c -p -r1.737 expr.c
*** expr.c	28 Oct 2004 03:53:31 -0000	1.737
--- expr.c	3 Nov 2004 22:20:25 -0000
*************** init_expr (void)
*** 317,322 ****
--- 317,326 ----
  
  /* Copy data from FROM to TO, where the machine modes are not the same.
     Both modes may be integer, or both may be floating.
+ 
+    If one mode is an integer and another is a floating point, both
+    must be the same size.
+ 
     UNSIGNEDP should be nonzero if FROM is an unsigned type.
     This causes zero-extension instead of sign-extension.  */
  
*************** convert_move (rtx to, rtx from, int unsi
*** 334,341 ****
    enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
  			      : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
  
! 
!   gcc_assert (to_real == from_real);
  
    /* If the source and destination are already the same, then there's
       nothing to do.  */
--- 338,349 ----
    enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
  			      : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
  
!   if (to_real != from_real)
!     {
!       gcc_assert (GET_MODE_SIZE (to_mode) == GET_MODE_SIZE (from_mode));
!       emit_move_insn (to, gen_rtx_SUBREG (to_mode, from, 0));
!       return;
!     }
  
    /* If the source and destination are already the same, then there's
       nothing to do.  */
Index: expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.200
diff -c -p -r1.200 expmed.c
*** expmed.c	21 Oct 2004 10:51:00 -0000	1.200
--- expmed.c	3 Nov 2004 22:20:28 -0000
*************** extract_bit_field (rtx str_rtx, unsigned
*** 1267,1279 ****
  
        unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
        unsigned int i;
  
        if (target == 0 || !REG_P (target))
  	target = gen_reg_rtx (mode);
  
!       /* Indicate for flow that the entire target reg is being set.  */
        emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
  
        for (i = 0; i < nwords; i++)
  	{
  	  /* If I is 0, use the low-order word in both field and target;
--- 1267,1292 ----
  
        unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
        unsigned int i;
+       rtx new_target;
  
        if (target == 0 || !REG_P (target))
  	target = gen_reg_rtx (mode);
  
!       /* Indicate to flow that the entire target reg is being set.  */
        emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
  
+       /* Make sure we do all word manipulations on an integer, thus
+ 	 avoiding creating invalid subregs of floats.  */
+       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ 	{
+ 	  new_target = gen_reg_rtx (int_mode_for_mode (mode));
+ 	  /* ?? Isn't flow smart enough to see that we use the entire
+ 	     register without handholding?  I don't think this clobber
+ 	     (or the one above) is needed any longer.  */
+ 	  emit_insn (gen_rtx_CLOBBER (VOIDmode, new_target));
+ 	}
+       else
+ 	new_target = target;
        for (i = 0; i < nwords; i++)
  	{
  	  /* If I is 0, use the low-order word in both field and target;
*************** extract_bit_field (rtx str_rtx, unsigned
*** 1288,1294 ****
  				     ? MAX (0, ((int) bitsize - ((int) i + 1)
  						* (int) BITS_PER_WORD))
  				     : (int) i * BITS_PER_WORD);
! 	  rtx target_part = operand_subword (target, wordnum, 1, VOIDmode);
  	  rtx result_part
  	    = extract_bit_field (op0, MIN (BITS_PER_WORD,
  					   bitsize - i * BITS_PER_WORD),
--- 1301,1307 ----
  				     ? MAX (0, ((int) bitsize - ((int) i + 1)
  						* (int) BITS_PER_WORD))
  				     : (int) i * BITS_PER_WORD);
! 	  rtx target_part = operand_subword (new_target, wordnum, 1, VOIDmode);
  	  rtx result_part
  	    = extract_bit_field (op0, MIN (BITS_PER_WORD,
  					   bitsize - i * BITS_PER_WORD),
*************** extract_bit_field (rtx str_rtx, unsigned
*** 1300,1305 ****
--- 1313,1320 ----
  	  if (result_part != target_part)
  	    emit_move_insn (target_part, result_part);
  	}
+       if (new_target != target)
+ 	convert_move (target, new_target, 0);
  
        if (unsignedp)
  	{


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