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]

[PATCH] Numerous simplify_gen_relational related clean-ups.


The following patch contains numerous tweaks to the way the RTL
simplification machinery handles comparison operations.  Central to
this is the need to maintain two modes; the first the mode of the
result and the second the mode that the comparison is performed in.

Historically, GCC has been fairly lax about the distinction. For
example, simplify_gen_relational wasn't guaranteed to return a
result with the same "mode" as specified by its' MODE argument!
Similarly, many transformations always used the same value for
both.

However in trying to track down the source PR bootstrap/12269,
I wanted to rule out a comparison mode mismatch as a potential
cause of the failure.  Unfortunately, these clean-ups don't cure
that ia64 bootstrap failure, but they have been fully tested
without problems on IA-32.


The following patch has been tested on i686-pc-linux-gnu with a
complete "make bootstrap", all languages except treelang, and
regression tested with a top-level "make -k check" with no new
failures.

Ok for mainline?


2003-09-14  Roger Sayle  <roger@eyesopen.com>

	* simplify-rtx.c (simplify_gen_relational): Allow the cmp_mode
	argument to be VOIDmode, taking the mode of the comparison from
	the operands.  Only call simplify_relational_operation if we
	know the mode of the comparison.  Honor FLOAT_STORE_FLAG_VALUE
	if comparison has a floating point result.  Ensure that the
	result is always an RTX of the specified machine mode.
	(simplify_replace_rtx): Simplify call to simplify_gen_relational.
	(simplify_unary_operation): Ensure the correct mode and cmp_mode
	are always passed to simplify_gen_relational.  Simplify NOT of
	comparison operator in any mode, not just BImode.
	(simplify_ternary_operation): Correct tests on the return value
	of simplify_relational_operation to use const_true_rtx, not
	const1_rtx.  Abort if it ever returns a non-constant result.

	* cfgloopanal.c (count_strange_loop_iterations): Use the function
	simplify_relational_operation, not simplify_gen_relational, if
	we're only interested in constant comparisons and we'll ignore
	non-constant results.


Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.158
diff -c -3 -p -r1.158 simplify-rtx.c
*** simplify-rtx.c	11 Sep 2003 13:01:32 -0000	1.158
--- simplify-rtx.c	14 Sep 2003 19:37:30 -0000
*************** simplify_gen_relational (enum rtx_code c
*** 197,234 ****
  {
    rtx tem;

!   if ((tem = simplify_relational_operation (code, cmp_mode, op0, op1)) != 0)
!     return tem;

    /* For the following tests, ensure const0_rtx is op1.  */
!   if (op0 == const0_rtx && swap_commutative_operands_p (op0, op1))
      tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);

    /* If op0 is a compare, extract the comparison arguments from it.  */
    if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
!     op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);

    /* If op0 is a comparison, extract the comparison arguments form it.  */
!   if (code == NE && op1 == const0_rtx
!       && GET_RTX_CLASS (GET_CODE (op0)) == '<')
!     return op0;
!   else if (code == EQ && op1 == const0_rtx)
!     {
!       /* The following tests GET_RTX_CLASS (GET_CODE (op0)) == '<'.  */
!       enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
!       if (new != UNKNOWN)
!         {
! 	  code = new;
! 	  mode = cmp_mode;
! 	  op1 = XEXP (op0, 1);
! 	  op0 = XEXP (op0, 0);
          }
      }

-   /* Put complex operands first and constants second.  */
-   if (swap_commutative_operands_p (op0, op1))
-     tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
-
    return gen_rtx_fmt_ee (code, mode, op0, op1);
  }

--- 197,258 ----
  {
    rtx tem;

!   if (cmp_mode == VOIDmode)
!     cmp_mode = GET_MODE (op0);
!   if (cmp_mode == VOIDmode)
!     cmp_mode = GET_MODE (op1);
!
!   if (cmp_mode != VOIDmode)
!     {
!       tem = simplify_relational_operation (code, cmp_mode, op0, op1);
!
!       if (tem)
! 	{
! #ifdef FLOAT_STORE_FLAG_VALUE
! 	  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
! 	    {
! 	      REAL_VALUE_TYPE val;
! 	      if (tem == const0_rtx)
! 		return CONST0_RTX (mode);
! 	      if (tem != const_true_rtx)
! 		abort ();
! 	      val = FLOAT_STORE_FLAG_VALUE (mode);
! 	      return CONST_DOUBLE_FROM_REAL_VALUE (val, mode);
! 	    }
! #endif
! 	  return tem;
! 	}
!     }

    /* For the following tests, ensure const0_rtx is op1.  */
!   if (swap_commutative_operands_p (op0, op1)
!       || (op0 == const0_rtx && op1 != const0_rtx))
      tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);

    /* If op0 is a compare, extract the comparison arguments from it.  */
    if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
!     return simplify_gen_relational (code, mode, VOIDmode,
! 				    XEXP (op0, 0), XEXP (op0, 1));

    /* If op0 is a comparison, extract the comparison arguments form it.  */
!   if (GET_RTX_CLASS (GET_CODE (op0)) == '<' && op1 == const0_rtx)
!     {
!       if (code == NE)
! 	{
! 	  if (GET_MODE (op0) == mode)
! 	    return op0;
! 	  return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode,
! 					  XEXP (op0, 0), XEXP (op0, 1));
! 	}
!       else if (code == EQ)
! 	{
! 	  enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
! 	  if (new != UNKNOWN)
! 	    return simplify_gen_relational (new, mode, VOIDmode,
! 					    XEXP (op0, 0), XEXP (op0, 1));
          }
      }

    return gen_rtx_fmt_ee (code, mode, op0, op1);
  }

*************** simplify_replace_rtx (rtx x, rtx old, rt
*** 272,295 ****
  				     : GET_MODE (XEXP (x, 1)));
  	rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
  	rtx op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
! 	rtx temp = simplify_gen_relational (code, mode,
! 					    (op_mode != VOIDmode
! 					     ? op_mode
! 					     : GET_MODE (op0) != VOIDmode
! 					       ? GET_MODE (op0)
! 					       : GET_MODE (op1)),
! 					    op0, op1);
! #ifdef FLOAT_STORE_FLAG_VALUE
! 	if (GET_MODE_CLASS (mode) == MODE_FLOAT)
! 	{
! 	  if (temp == const0_rtx)
! 	    temp = CONST0_RTX (mode);
! 	  else if (temp == const_true_rtx)
! 	    temp = CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE (mode),
! 						 mode);
! 	}
! #endif
! 	return temp;
        }

      case '3':
--- 296,302 ----
  				     : GET_MODE (XEXP (x, 1)));
  	rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
  	rtx op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
! 	return simplify_gen_relational (code, mode, op_mode, op0, op1);
        }

      case '3':
*************** simplify_unary_operation (enum rtx_code
*** 800,809 ****
  	    return XEXP (op, 0);

  	  /* (not (eq X Y)) == (ne X Y), etc.  */
! 	  if (mode == BImode && GET_RTX_CLASS (GET_CODE (op)) == '<'
  	      && ((reversed = reversed_comparison_code (op, NULL_RTX))
  		  != UNKNOWN))
! 	    return simplify_gen_relational (reversed, op_mode, op_mode,
  					    XEXP (op, 0), XEXP (op, 1));

            /* (not (plus X -1)) can become (neg X).  */
--- 807,816 ----
  	    return XEXP (op, 0);

  	  /* (not (eq X Y)) == (ne X Y), etc.  */
! 	  if (GET_RTX_CLASS (GET_CODE (op)) == '<'
  	      && ((reversed = reversed_comparison_code (op, NULL_RTX))
  		  != UNKNOWN))
! 	    return simplify_gen_relational (reversed, mode, op_mode,
  					    XEXP (op, 0), XEXP (op, 1));

            /* (not (plus X -1)) can become (neg X).  */
*************** simplify_unary_operation (enum rtx_code
*** 842,848 ****
  	      && GET_RTX_CLASS (GET_CODE (op)) == '<'
  	      && (reversed = reversed_comparison_code (op, NULL_RTX))
  		 != UNKNOWN)
! 	    return simplify_gen_relational (reversed, op_mode, op_mode,
  					    XEXP (op, 0), XEXP (op, 1));

  	  /* (not (ashiftrt foo C)) where C is the number of bits in FOO
--- 849,855 ----
  	      && GET_RTX_CLASS (GET_CODE (op)) == '<'
  	      && (reversed = reversed_comparison_code (op, NULL_RTX))
  		 != UNKNOWN)
! 	    return simplify_gen_relational (reversed, mode, op_mode,
  					    XEXP (op, 0), XEXP (op, 1));

  	  /* (not (ashiftrt foo C)) where C is the number of bits in FOO
*************** simplify_unary_operation (enum rtx_code
*** 853,860 ****
  	      && GET_CODE (op) == ASHIFTRT
  	      && GET_CODE (XEXP (op, 1)) == CONST_INT
  	      && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
! 	    return simplify_gen_relational (GE, mode, mode, XEXP (op, 0),
! 					    const0_rtx);

  	  break;

--- 860,867 ----
  	      && GET_CODE (op) == ASHIFTRT
  	      && GET_CODE (XEXP (op, 1)) == CONST_INT
  	      && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
! 	    return simplify_gen_relational (GE, mode, op_mode,
! 					    XEXP (op, 0), const0_rtx);

  	  break;

*************** simplify_ternary_operation (enum rtx_cod
*** 2725,2734 ****
  	  /* See if any simplifications were possible.  */
  	  if (temp == const0_rtx)
  	    return op2;
! 	  else if (temp == const1_rtx)
  	    return op1;
  	  else if (temp)
! 	    op0 = temp;

  	  /* Look for happy constants in op1 and op2.  */
  	  if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
--- 2732,2741 ----
  	  /* See if any simplifications were possible.  */
  	  if (temp == const0_rtx)
  	    return op2;
! 	  else if (temp == const_true_rtx)
  	    return op1;
  	  else if (temp)
! 	    abort ();

  	  /* Look for happy constants in op1 and op2.  */
  	  if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
Index: cfgloopanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloopanal.c,v
retrieving revision 1.11
diff -c -3 -p -r1.11 cfgloopanal.c
*** cfgloopanal.c	19 Aug 2003 23:21:52 -0000	1.11
--- cfgloopanal.c	14 Sep 2003 19:37:30 -0000
*************** count_strange_loop_iterations (rtx init,
*** 470,476 ****

    /* If we are able to prove that we don't pass the first test, we are
       done.  */
!   rqmt = simplify_gen_relational (cond, SImode, mode, init, lim);
    if (rqmt == const0_rtx)
      return const0_rtx;

--- 470,476 ----

    /* If we are able to prove that we don't pass the first test, we are
       done.  */
!   rqmt = simplify_relational_operation (cond, mode, init, lim);
    if (rqmt == const0_rtx)
      return const0_rtx;

*************** count_strange_loop_iterations (rtx init,
*** 560,566 ****
    /* If this is const_true_rtx and we did not take a conservative approximation
       of after_wrap above, we might iterate the calculation (but of course we
       would have to take care about infinite cases).  Ignore this for now.  */
!   rqmt = simplify_gen_relational (cond, SImode, mode, after_wrap, lim);
    if (rqmt != const0_rtx)
      return NULL_RTX;

--- 560,566 ----
    /* If this is const_true_rtx and we did not take a conservative approximation
       of after_wrap above, we might iterate the calculation (but of course we
       would have to take care about infinite cases).  Ignore this for now.  */
!   rqmt = simplify_relational_operation (cond, mode, after_wrap, lim);
    if (rqmt != const0_rtx)
      return NULL_RTX;


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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