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]

subreg validation, part 5


Two problems fixed here:

  (1) The gen_rtx_SUBREG call there in the first hunk could generate
      illegal stuff.  Fortunately, simplify_gen_subreg already knows
      all about simplifying subregs.  If it returns NULL, then we
      know that what we're asking for isn't possible.

  (2) The CONCAT stuff in the last hunk fixes some uses of complex
      numbers on 64-bit targets.  I seem to recall there's some test
      that will now XPASS, but I've forgotten which.  I'll remove the
      XFAIL later.

      As described, the problem is that gen_imagpart is requires to
      return a value that can be written, and we can't take a highpart
      subreg of (subreg:SC (reg:DI x) 0), so we wound up aborting.

      Splitting this value now, while we know we have an rvalue,
      makes everyone later in the expansion phase happy.


r~


        * expmed.c (extract_bit_field): Use simplify_gen_subreg instead of
        hard-coding avoiding calls to gen_rtx_SUBREG.  Split complex return
        modes to CONCAT.

Index: expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.207
diff -c -p -d -r1.207 expmed.c
*** expmed.c	17 Nov 2004 22:29:29 -0000	1.207
--- expmed.c	23 Nov 2004 23:22:39 -0000
*************** extract_bit_field (rtx str_rtx, unsigned
*** 1233,1254 ****
      {
        if (mode1 != GET_MODE (op0))
  	{
! 	  if (GET_CODE (op0) == SUBREG)
  	    {
! 	      if (GET_MODE (SUBREG_REG (op0)) == mode1
! 		  || GET_MODE_CLASS (mode1) == MODE_INT
! 		  || GET_MODE_CLASS (mode1) == MODE_PARTIAL_INT)
! 		op0 = SUBREG_REG (op0);
! 	      else
! 		/* Else we've got some float mode source being extracted into
! 		   a different float mode destination -- this combination of
! 		   subregs results in Severe Tire Damage.  */
  		goto no_subreg_mode_swap;
  	    }
- 	  if (REG_P (op0))
- 	    op0 = gen_rtx_SUBREG (mode1, op0, byte_offset);
- 	  else
- 	    op0 = adjust_address (op0, mode1, offset);
  	}
        if (mode1 != mode)
  	return convert_to_mode (tmode, op0, unsignedp);
--- 1233,1248 ----
      {
        if (mode1 != GET_MODE (op0))
  	{
! 	  if (MEM_P (op0))
! 	    op0 = adjust_address (op0, mode1, offset);
! 	  else
  	    {
! 	      rtx sub = simplify_gen_subreg (mode1, op0, GET_MODE (op0),
! 					     byte_offset);
! 	      if (sub == NULL)
  		goto no_subreg_mode_swap;
+ 	      op0 = sub;
  	    }
  	}
        if (mode1 != mode)
  	return convert_to_mode (tmode, op0, unsignedp);
*************** extract_bit_field (rtx str_rtx, unsigned
*** 1628,1646 ****
      return spec_target;
    if (GET_MODE (target) != tmode && GET_MODE (target) != mode)
      {
!       /* If the target mode is floating-point, first convert to the
! 	 integer mode of that size and then access it as a floating-point
! 	 value via a SUBREG.  */
!       if (GET_MODE_CLASS (tmode) != MODE_INT
! 	  && GET_MODE_CLASS (tmode) != MODE_PARTIAL_INT)
  	{
  	  target = convert_to_mode (mode_for_size (GET_MODE_BITSIZE (tmode),
  						   MODE_INT, 0),
  				    target, unsignedp);
  	  return gen_lowpart (tmode, target);
  	}
!       else
! 	return convert_to_mode (tmode, target, unsignedp);
      }
    return target;
  }
--- 1622,1662 ----
      return spec_target;
    if (GET_MODE (target) != tmode && GET_MODE (target) != mode)
      {
!       /* If the target mode is complex, then extract the two scalar elements
! 	 from the value now.  Creating (subreg:SC (reg:DI) 0), as we would do
! 	 with the clause below, will cause gen_realpart or gen_imagpart to
! 	 fail, since those functions must return lvalues.  */
!       if (COMPLEX_MODE_P (tmode))
  	{
+ 	  rtx realpart, imagpart;
+ 	  enum machine_mode itmode = GET_MODE_INNER (tmode);
+ 
  	  target = convert_to_mode (mode_for_size (GET_MODE_BITSIZE (tmode),
  						   MODE_INT, 0),
  				    target, unsignedp);
+ 
+ 	  realpart = extract_bit_field (target, GET_MODE_BITSIZE (itmode), 0,
+ 					unsignedp, NULL, itmode, itmode);
+ 	  imagpart = extract_bit_field (target, GET_MODE_BITSIZE (itmode),
+ 					GET_MODE_BITSIZE (itmode), unsignedp,
+ 					NULL, itmode, itmode);
+ 
+ 	  return gen_rtx_CONCAT (tmode, realpart, imagpart);
+ 	}
+ 
+       /* If the target mode is not a scalar integral, first convert to the
+ 	 integer mode of that size and then access it as a floating-point
+ 	 value via a SUBREG.  */
+       if (!SCALAR_INT_MODE_P (tmode))
+ 	{
+ 	  enum machine_mode smode
+ 	    = mode_for_size (GET_MODE_BITSIZE (tmode), MODE_INT, 0);
+ 	  target = convert_to_mode (smode, target, unsignedp);
+ 	  target = force_reg (smode, target);
  	  return gen_lowpart (tmode, target);
  	}
! 
!       return convert_to_mode (tmode, target, unsignedp);
      }
    return target;
  }


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