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]

simplify-rtx and constant pool references


Hi,
this somewhat largist, but mechanical patch makes simplify-rtx smart enought
to realize that constant pool references are constants, when this allows
simplification.

This is important, because combine never attempts to replace these back
by constants, so currently we fail to simplify for example:

float a,b;
main()
{
	float e=0;
	float c= e-b;
	a+=c;
}

With this patch, considerably more simplifications are perofmed in some
fortran testcase I have.

Bootrap/regtesting in progress on i586.  OK assuming it passes?
Honza

Mon Jul 16 22:33:39 CEST 2001  Jan Hubicka  <jh@suse.cz>
	* simplify-rtx.c (avoid_constatn_pool_reference): New static function.
	(simplify_binary_operation, simplify_unary_operation,
	 simplify_relational_operation): Use it.
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/simplify-rtx.c,v
retrieving revision 1.68
diff -c -3 -p -r1.68 simplify-rtx.c
*** simplify-rtx.c	2001/07/11 09:41:34	1.68
--- simplify-rtx.c	2001/07/16 20:33:21
*************** Boston, MA 02111-1307, USA.  */
*** 99,104 ****
--- 99,105 ----
  static rtx simplify_plus_minus		PARAMS ((enum rtx_code,
  						 enum machine_mode, rtx, rtx));
  static void check_fold_consts		PARAMS ((PTR));
+ static rtx avoid_constant_pool_reference PARAMS ((rtx));
  
  /* Make a binary operation by properly ordering the operands and 
     seeing if the expression folds.  */
*************** simplify_gen_binary (code, mode, op0, op
*** 135,140 ****
--- 136,154 ----
      return gen_rtx_fmt_ee (code, mode, op0, op1);
  }
  
+ /* In case X is MEM referencing constant pool, return the real value.
+    Otherwise return X.  */
+ static rtx
+ avoid_constant_pool_reference (x)
+      rtx x;
+ {
+   if (GET_CODE (x) != MEM)
+     return x;
+   if (!CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
+     return x;
+   return get_pool_constant (XEXP (x, 0));
+ }
+ 
  /* Make a unary operation by first seeing if it folds and otherwise making
     the specified operation.  */
  
*************** simplify_unary_operation (code, mode, op
*** 287,292 ****
--- 301,307 ----
       enum machine_mode op_mode;
  {
    unsigned int width = GET_MODE_BITSIZE (mode);
+   rtx trueop = avoid_constant_pool_reference (op);
  
    /* The order of these tests is critical so that, for example, we don't
       check the wrong mode (input vs. output) for a conversion operation,
*************** simplify_unary_operation (code, mode, op
*** 294,309 ****
  
  #if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
  
!   if (code == FLOAT && GET_MODE (op) == VOIDmode
!       && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
      {
        HOST_WIDE_INT hv, lv;
        REAL_VALUE_TYPE d;
  
!       if (GET_CODE (op) == CONST_INT)
! 	lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv);
        else
! 	lv = CONST_DOUBLE_LOW (op),  hv = CONST_DOUBLE_HIGH (op);
  
  #ifdef REAL_ARITHMETIC
        REAL_VALUE_FROM_INT (d, lv, hv, mode);
--- 309,324 ----
  
  #if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
  
!   if (code == FLOAT && GET_MODE (trueop) == VOIDmode
!       && (GET_CODE (trueop) == CONST_DOUBLE || GET_CODE (trueop) == CONST_INT))
      {
        HOST_WIDE_INT hv, lv;
        REAL_VALUE_TYPE d;
  
!       if (GET_CODE (trueop) == CONST_INT)
! 	lv = INTVAL (trueop), hv = HWI_SIGN_EXTEND (lv);
        else
! 	lv = CONST_DOUBLE_LOW (trueop),  hv = CONST_DOUBLE_HIGH (trueop);
  
  #ifdef REAL_ARITHMETIC
        REAL_VALUE_FROM_INT (d, lv, hv, mode);
*************** simplify_unary_operation (code, mode, op
*** 327,342 ****
        d = real_value_truncate (mode, d);
        return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
      }
!   else if (code == UNSIGNED_FLOAT && GET_MODE (op) == VOIDmode
! 	   && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
      {
        HOST_WIDE_INT hv, lv;
        REAL_VALUE_TYPE d;
  
!       if (GET_CODE (op) == CONST_INT)
! 	lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv);
        else
! 	lv = CONST_DOUBLE_LOW (op),  hv = CONST_DOUBLE_HIGH (op);
  
        if (op_mode == VOIDmode)
  	{
--- 342,358 ----
        d = real_value_truncate (mode, d);
        return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
      }
!   else if (code == UNSIGNED_FLOAT && GET_MODE (trueop) == VOIDmode
! 	   && (GET_CODE (trueop) == CONST_DOUBLE
! 	       || GET_CODE (trueop) == CONST_INT))
      {
        HOST_WIDE_INT hv, lv;
        REAL_VALUE_TYPE d;
  
!       if (GET_CODE (trueop) == CONST_INT)
! 	lv = INTVAL (trueop), hv = HWI_SIGN_EXTEND (lv);
        else
! 	lv = CONST_DOUBLE_LOW (trueop),  hv = CONST_DOUBLE_HIGH (trueop);
  
        if (op_mode == VOIDmode)
  	{
*************** simplify_unary_operation (code, mode, op
*** 364,373 ****
      }
  #endif
  
!   if (GET_CODE (op) == CONST_INT
        && width <= HOST_BITS_PER_WIDE_INT && width > 0)
      {
!       register HOST_WIDE_INT arg0 = INTVAL (op);
        register HOST_WIDE_INT val;
  
        switch (code)
--- 380,389 ----
      }
  #endif
  
!   if (GET_CODE (trueop) == CONST_INT
        && width <= HOST_BITS_PER_WIDE_INT && width > 0)
      {
!       register HOST_WIDE_INT arg0 = INTVAL (trueop);
        register HOST_WIDE_INT val;
  
        switch (code)
*************** simplify_unary_operation (code, mode, op
*** 453,468 ****
  
    /* We can do some operations on integer CONST_DOUBLEs.  Also allow
       for a DImode operation on a CONST_INT.  */
!   else if (GET_MODE (op) == VOIDmode && width <= HOST_BITS_PER_INT * 2
! 	   && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
      {
        unsigned HOST_WIDE_INT l1, lv;
        HOST_WIDE_INT h1, hv;
  
!       if (GET_CODE (op) == CONST_DOUBLE)
! 	l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op);
        else
! 	l1 = INTVAL (op), h1 = HWI_SIGN_EXTEND (l1);
  
        switch (code)
  	{
--- 469,485 ----
  
    /* We can do some operations on integer CONST_DOUBLEs.  Also allow
       for a DImode operation on a CONST_INT.  */
!   else if (GET_MODE (trueop) == VOIDmode && width <= HOST_BITS_PER_INT * 2
! 	   && (GET_CODE (trueop) == CONST_DOUBLE
! 	       || GET_CODE (trueop) == CONST_INT))
      {
        unsigned HOST_WIDE_INT l1, lv;
        HOST_WIDE_INT h1, hv;
  
!       if (GET_CODE (trueop) == CONST_DOUBLE)
! 	l1 = CONST_DOUBLE_LOW (trueop), h1 = CONST_DOUBLE_HIGH (trueop);
        else
! 	l1 = INTVAL (trueop), h1 = HWI_SIGN_EXTEND (l1);
  
        switch (code)
  	{
*************** simplify_unary_operation (code, mode, op
*** 531,537 ****
      }
  
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
!   else if (GET_CODE (op) == CONST_DOUBLE
  	   && GET_MODE_CLASS (mode) == MODE_FLOAT)
      {
        REAL_VALUE_TYPE d;
--- 548,554 ----
      }
  
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
!   else if (GET_CODE (trueop) == CONST_DOUBLE
  	   && GET_MODE_CLASS (mode) == MODE_FLOAT)
      {
        REAL_VALUE_TYPE d;
*************** simplify_unary_operation (code, mode, op
*** 546,552 ****
  
        set_float_handler (handler);
  
!       REAL_VALUE_FROM_CONST_DOUBLE (d, op);
  
        switch (code)
  	{
--- 563,569 ----
  
        set_float_handler (handler);
  
!       REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
  
        switch (code)
  	{
*************** simplify_unary_operation (code, mode, op
*** 587,594 ****
        return x;
      }
  
!   else if (GET_CODE (op) == CONST_DOUBLE
! 	   && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
  	   && GET_MODE_CLASS (mode) == MODE_INT
  	   && width <= HOST_BITS_PER_WIDE_INT && width > 0)
      {
--- 604,611 ----
        return x;
      }
  
!   else if (GET_CODE (trueop) == CONST_DOUBLE
! 	   && GET_MODE_CLASS (GET_MODE (trueop)) == MODE_FLOAT
  	   && GET_MODE_CLASS (mode) == MODE_INT
  	   && width <= HOST_BITS_PER_WIDE_INT && width > 0)
      {
*************** simplify_unary_operation (code, mode, op
*** 601,607 ****
  
        set_float_handler (handler);
  
!       REAL_VALUE_FROM_CONST_DOUBLE (d, op);
  
        switch (code)
  	{
--- 618,624 ----
  
        set_float_handler (handler);
  
!       REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
  
        switch (code)
  	{
*************** simplify_binary_operation (code, mode, o
*** 713,718 ****
--- 730,737 ----
    HOST_WIDE_INT val;
    unsigned int width = GET_MODE_BITSIZE (mode);
    rtx tem;
+   rtx trueop0 = avoid_constant_pool_reference (op0);
+   rtx trueop1 = avoid_constant_pool_reference (op1);
  
    /* Relational operations don't work here.  We must know the mode
       of the operands in order to do the comparison correctly.
*************** simplify_binary_operation (code, mode, o
*** 722,730 ****
    if (GET_RTX_CLASS (code) == '<')
      abort ();
  
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
    if (GET_MODE_CLASS (mode) == MODE_FLOAT
!       && GET_CODE (op0) == CONST_DOUBLE && GET_CODE (op1) == CONST_DOUBLE
        && mode == GET_MODE (op0) && mode == GET_MODE (op1))
      {
        REAL_VALUE_TYPE f0, f1, value;
--- 741,758 ----
    if (GET_RTX_CLASS (code) == '<')
      abort ();
  
+   /* Make sure the constant is second.  */
+   if (GET_RTX_CLASS (code) == 'c'
+       && swap_commutative_operands_p (trueop0, trueop1))
+     {
+       tem = op0, op0 = op1, op1 = tem;
+       tem = trueop0, trueop0 = trueop1, trueop1 = tem;
+     }
+ 
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
    if (GET_MODE_CLASS (mode) == MODE_FLOAT
!       && GET_CODE (trueop0) == CONST_DOUBLE
!       && GET_CODE (trueop1) == CONST_DOUBLE
        && mode == GET_MODE (op0) && mode == GET_MODE (op1))
      {
        REAL_VALUE_TYPE f0, f1, value;
*************** simplify_binary_operation (code, mode, o
*** 735,742 ****
  
        set_float_handler (handler);
  
!       REAL_VALUE_FROM_CONST_DOUBLE (f0, op0);
!       REAL_VALUE_FROM_CONST_DOUBLE (f1, op1);
        f0 = real_value_truncate (mode, f0);
        f1 = real_value_truncate (mode, f1);
  
--- 763,770 ----
  
        set_float_handler (handler);
  
!       REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
!       REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
        f0 = real_value_truncate (mode, f0);
        f1 = real_value_truncate (mode, f1);
  
*************** simplify_binary_operation (code, mode, o
*** 785,805 ****
    /* We can fold some multi-word operations.  */
    if (GET_MODE_CLASS (mode) == MODE_INT
        && width == HOST_BITS_PER_WIDE_INT * 2
!       && (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT)
!       && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT))
      {
        unsigned HOST_WIDE_INT l1, l2, lv;
        HOST_WIDE_INT h1, h2, hv;
  
!       if (GET_CODE (op0) == CONST_DOUBLE)
! 	l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0);
        else
! 	l1 = INTVAL (op0), h1 = HWI_SIGN_EXTEND (l1);
  
!       if (GET_CODE (op1) == CONST_DOUBLE)
! 	l2 = CONST_DOUBLE_LOW (op1), h2 = CONST_DOUBLE_HIGH (op1);
        else
! 	l2 = INTVAL (op1), h2 = HWI_SIGN_EXTEND (l2);
  
        switch (code)
  	{
--- 813,835 ----
    /* We can fold some multi-word operations.  */
    if (GET_MODE_CLASS (mode) == MODE_INT
        && width == HOST_BITS_PER_WIDE_INT * 2
!       && (GET_CODE (trueop0) == CONST_DOUBLE
! 	  || GET_CODE (trueop0) == CONST_INT)
!       && (GET_CODE (trueop1) == CONST_DOUBLE
! 	  || GET_CODE (trueop1) == CONST_INT))
      {
        unsigned HOST_WIDE_INT l1, l2, lv;
        HOST_WIDE_INT h1, h2, hv;
  
!       if (GET_CODE (trueop0) == CONST_DOUBLE)
! 	l1 = CONST_DOUBLE_LOW (trueop0), h1 = CONST_DOUBLE_HIGH (trueop0);
        else
! 	l1 = INTVAL (trueop0), h1 = HWI_SIGN_EXTEND (l1);
  
!       if (GET_CODE (trueop1) == CONST_DOUBLE)
! 	l2 = CONST_DOUBLE_LOW (trueop1), h2 = CONST_DOUBLE_HIGH (trueop1);
        else
! 	l2 = INTVAL (trueop1), h2 = HWI_SIGN_EXTEND (l2);
  
        switch (code)
  	{
*************** simplify_binary_operation (code, mode, o
*** 919,925 ****
  	      && FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations)
  	    break;
  
! 	  if (op1 == CONST0_RTX (mode))
  	    return op0;
  
  	  /* ((-a) + b) -> (b - a) and similarly for (a + (-b)) */
--- 949,955 ----
  	      && FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations)
  	    break;
  
! 	  if (trueop1 == CONST0_RTX (mode))
  	    return op0;
  
  	  /* ((-a) + b) -> (b - a) and similarly for (a + (-b)) */
*************** simplify_binary_operation (code, mode, o
*** 931,938 ****
  	  /* (~a) + 1 -> -a */
  	  if (INTEGRAL_MODE_P (mode)
  	      && GET_CODE (op0) == NOT
! 	      && GET_CODE (op1) == CONST_INT
! 	      && INTVAL (op1) == 1)
  	    return gen_rtx_NEG (mode, XEXP (op0, 0));
  
  	  /* Handle both-operands-constant cases.  We can only add
--- 961,967 ----
  	  /* (~a) + 1 -> -a */
  	  if (INTEGRAL_MODE_P (mode)
  	      && GET_CODE (op0) == NOT
! 	      && trueop1 == const1_rtx)
  	    return gen_rtx_NEG (mode, XEXP (op0, 0));
  
  	  /* Handle both-operands-constant cases.  We can only add
*************** simplify_binary_operation (code, mode, o
*** 1025,1031 ****
  
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
! 	      && op1 == CONST0_RTX (mode))
  	    return op0;
  #endif
  
--- 1054,1060 ----
  
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
! 	      && trueop1 == CONST0_RTX (mode))
  	    return op0;
  #endif
  
*************** simplify_binary_operation (code, mode, o
*** 1060,1080 ****
  	  /* We can't assume x-x is 0 even with non-IEEE floating point,
  	     but since it is zero except in very strange circumstances, we
  	     will treat it as zero with -funsafe-math-optimizations.  */
! 	  if (rtx_equal_p (op0, op1)
  	      && ! side_effects_p (op0)
  	      && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
  	    return CONST0_RTX (mode);
  
  	  /* Change subtraction from zero into negation.  */
! 	  if (op0 == CONST0_RTX (mode))
  	    return gen_rtx_NEG (mode, op1);
  
  	  /* (-1 - a) is ~a.  */
! 	  if (op0 == constm1_rtx)
  	    return gen_rtx_NOT (mode, op1);
  
  	  /* Subtracting 0 has no effect.  */
! 	  if (op1 == CONST0_RTX (mode))
  	    return op0;
  
  	  /* See if this is something like X * C - X or vice versa or
--- 1089,1109 ----
  	  /* We can't assume x-x is 0 even with non-IEEE floating point,
  	     but since it is zero except in very strange circumstances, we
  	     will treat it as zero with -funsafe-math-optimizations.  */
! 	  if (rtx_equal_p (trueop0, trueop1)
  	      && ! side_effects_p (op0)
  	      && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
  	    return CONST0_RTX (mode);
  
  	  /* Change subtraction from zero into negation.  */
! 	  if (trueop0 == CONST0_RTX (mode))
  	    return gen_rtx_NEG (mode, op1);
  
  	  /* (-1 - a) is ~a.  */
! 	  if (trueop0 == constm1_rtx)
  	    return gen_rtx_NOT (mode, op1);
  
  	  /* Subtracting 0 has no effect.  */
! 	  if (trueop1 == CONST0_RTX (mode))
  	    return op0;
  
  	  /* See if this is something like X * C - X or vice versa or
*************** simplify_binary_operation (code, mode, o
*** 1164,1170 ****
  	  break;
  
  	case MULT:
! 	  if (op1 == constm1_rtx)
  	    {
  	      tem = simplify_unary_operation (NEG, mode, op0, mode);
  
--- 1193,1199 ----
  	  break;
  
  	case MULT:
! 	  if (trueop1 == constm1_rtx)
  	    {
  	      tem = simplify_unary_operation (NEG, mode, op0, mode);
  
*************** simplify_binary_operation (code, mode, o
*** 1174,1193 ****
  	  /* In IEEE floating point, x*0 is not always 0.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
! 	      && op1 == CONST0_RTX (mode)
  	      && ! side_effects_p (op0))
  	    return op1;
  
  	  /* In IEEE floating point, x*1 is not equivalent to x for nans.
  	     However, ANSI says we can drop signals,
  	     so we can do this anyway.  */
! 	  if (op1 == CONST1_RTX (mode))
  	    return op0;
  
  	  /* Convert multiply by constant power of two into shift unless
  	     we are still generating RTL.  This test is a kludge.  */
! 	  if (GET_CODE (op1) == CONST_INT
! 	      && (val = exact_log2 (INTVAL (op1))) >= 0
  	      /* If the mode is larger than the host word size, and the
  		 uppermost bit is set, then this isn't a power of two due
  		 to implicit sign extension.  */
--- 1203,1222 ----
  	  /* In IEEE floating point, x*0 is not always 0.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
! 	      && trueop1 == CONST0_RTX (mode)
  	      && ! side_effects_p (op0))
  	    return op1;
  
  	  /* In IEEE floating point, x*1 is not equivalent to x for nans.
  	     However, ANSI says we can drop signals,
  	     so we can do this anyway.  */
! 	  if (trueop1 == CONST1_RTX (mode))
  	    return op0;
  
  	  /* Convert multiply by constant power of two into shift unless
  	     we are still generating RTL.  This test is a kludge.  */
! 	  if (GET_CODE (trueop1) == CONST_INT
! 	      && (val = exact_log2 (INTVAL (trueop1))) >= 0
  	      /* If the mode is larger than the host word size, and the
  		 uppermost bit is set, then this isn't a power of two due
  		 to implicit sign extension.  */
*************** simplify_binary_operation (code, mode, o
*** 1196,1203 ****
  	      && ! rtx_equal_function_value_matters)
  	    return gen_rtx_ASHIFT (mode, op0, GEN_INT (val));
  
! 	  if (GET_CODE (op1) == CONST_DOUBLE
! 	      && GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT)
  	    {
  	      REAL_VALUE_TYPE d;
  	      jmp_buf handler;
--- 1225,1232 ----
  	      && ! rtx_equal_function_value_matters)
  	    return gen_rtx_ASHIFT (mode, op0, GEN_INT (val));
  
! 	  if (GET_CODE (trueop1) == CONST_DOUBLE
! 	      && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT)
  	    {
  	      REAL_VALUE_TYPE d;
  	      jmp_buf handler;
*************** simplify_binary_operation (code, mode, o
*** 1207,1213 ****
  		return 0;
  
  	      set_float_handler (handler);
! 	      REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
  	      op1is2 = REAL_VALUES_EQUAL (d, dconst2);
  	      op1ism1 = REAL_VALUES_EQUAL (d, dconstm1);
  	      set_float_handler (NULL);
--- 1236,1242 ----
  		return 0;
  
  	      set_float_handler (handler);
! 	      REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
  	      op1is2 = REAL_VALUES_EQUAL (d, dconst2);
  	      op1ism1 = REAL_VALUES_EQUAL (d, dconstm1);
  	      set_float_handler (NULL);
*************** simplify_binary_operation (code, mode, o
*** 1222,1233 ****
  	  break;
  
  	case IOR:
! 	  if (op1 == const0_rtx)
  	    return op0;
! 	  if (GET_CODE (op1) == CONST_INT
! 	      && (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
  	    return op1;
! 	  if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
  	    return op0;
  	  /* A | (~A) -> -1 */
  	  if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
--- 1251,1263 ----
  	  break;
  
  	case IOR:
! 	  if (trueop1 == const0_rtx)
  	    return op0;
! 	  if (GET_CODE (trueop1) == CONST_INT
! 	      && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
! 	          == GET_MODE_MASK (mode)))
  	    return op1;
! 	  if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
  	  /* A | (~A) -> -1 */
  	  if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
*************** simplify_binary_operation (code, mode, o
*** 1238,1260 ****
  	  break;
  
  	case XOR:
! 	  if (op1 == const0_rtx)
  	    return op0;
! 	  if (GET_CODE (op1) == CONST_INT
! 	      && (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
  	    return gen_rtx_NOT (mode, op0);
! 	  if (op0 == op1 && ! side_effects_p (op0)
  	      && GET_MODE_CLASS (mode) != MODE_CC)
  	    return const0_rtx;
  	  break;
  
  	case AND:
! 	  if (op1 == const0_rtx && ! side_effects_p (op0))
  	    return const0_rtx;
! 	  if (GET_CODE (op1) == CONST_INT
! 	      && (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
  	    return op0;
! 	  if (op0 == op1 && ! side_effects_p (op0)
  	      && GET_MODE_CLASS (mode) != MODE_CC)
  	    return op0;
  	  /* A & (~A) -> 0 */
--- 1268,1292 ----
  	  break;
  
  	case XOR:
! 	  if (trueop1 == const0_rtx)
  	    return op0;
! 	  if (GET_CODE (trueop1) == CONST_INT
! 	      && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
! 		  == GET_MODE_MASK (mode)))
  	    return gen_rtx_NOT (mode, op0);
! 	  if (trueop0 == trueop1 && ! side_effects_p (op0)
  	      && GET_MODE_CLASS (mode) != MODE_CC)
  	    return const0_rtx;
  	  break;
  
  	case AND:
! 	  if (trueop1 == const0_rtx && ! side_effects_p (op0))
  	    return const0_rtx;
! 	  if (GET_CODE (trueop1) == CONST_INT
! 	      && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
! 		  == GET_MODE_MASK (mode)))
  	    return op0;
! 	  if (trueop0 == trueop1 && ! side_effects_p (op0)
  	      && GET_MODE_CLASS (mode) != MODE_CC)
  	    return op0;
  	  /* A & (~A) -> 0 */
*************** simplify_binary_operation (code, mode, o
*** 1268,1300 ****
  	case UDIV:
  	  /* Convert divide by power of two into shift (divide by 1 handled
  	     below).  */
! 	  if (GET_CODE (op1) == CONST_INT
! 	      && (arg1 = exact_log2 (INTVAL (op1))) > 0)
  	    return gen_rtx_LSHIFTRT (mode, op0, GEN_INT (arg1));
  
  	  /* ... fall through ...  */
  
  	case DIV:
! 	  if (op1 == CONST1_RTX (mode))
  	    return op0;
  
  	  /* In IEEE floating point, 0/x is not always 0.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
! 	      && op0 == CONST0_RTX (mode)
  	      && ! side_effects_p (op1))
  	    return op0;
  
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
  	  /* Change division by a constant into multiplication.  Only do
  	     this with -funsafe-math-optimizations.  */
! 	  else if (GET_CODE (op1) == CONST_DOUBLE
! 		   && GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT
! 		   && op1 != CONST0_RTX (mode)
  		   && flag_unsafe_math_optimizations)
  	    {
  	      REAL_VALUE_TYPE d;
! 	      REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
  
  	      if (! REAL_VALUES_EQUAL (d, dconst0))
  		{
--- 1300,1332 ----
  	case UDIV:
  	  /* Convert divide by power of two into shift (divide by 1 handled
  	     below).  */
! 	  if (GET_CODE (trueop1) == CONST_INT
! 	      && (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
  	    return gen_rtx_LSHIFTRT (mode, op0, GEN_INT (arg1));
  
  	  /* ... fall through ...  */
  
  	case DIV:
! 	  if (trueop1 == CONST1_RTX (mode))
  	    return op0;
  
  	  /* In IEEE floating point, 0/x is not always 0.  */
  	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
  	       || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
! 	      && trueop0 == CONST0_RTX (mode)
  	      && ! side_effects_p (op1))
  	    return op0;
  
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
  	  /* Change division by a constant into multiplication.  Only do
  	     this with -funsafe-math-optimizations.  */
! 	  else if (GET_CODE (trueop1) == CONST_DOUBLE
! 		   && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
! 		   && trueop1 != CONST0_RTX (mode)
  		   && flag_unsafe_math_optimizations)
  	    {
  	      REAL_VALUE_TYPE d;
! 	      REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
  
  	      if (! REAL_VALUES_EQUAL (d, dconst0))
  		{
*************** simplify_binary_operation (code, mode, o
*** 1314,1327 ****
  
  	case UMOD:
  	  /* Handle modulus by power of two (mod with 1 handled below).  */
! 	  if (GET_CODE (op1) == CONST_INT
! 	      && exact_log2 (INTVAL (op1)) > 0)
  	    return gen_rtx_AND (mode, op0, GEN_INT (INTVAL (op1) - 1));
  
  	  /* ... fall through ...  */
  
  	case MOD:
! 	  if ((op0 == const0_rtx || op1 == const1_rtx)
  	      && ! side_effects_p (op0) && ! side_effects_p (op1))
  	    return const0_rtx;
  	  break;
--- 1346,1359 ----
  
  	case UMOD:
  	  /* Handle modulus by power of two (mod with 1 handled below).  */
! 	  if (GET_CODE (trueop1) == CONST_INT
! 	      && exact_log2 (INTVAL (trueop1)) > 0)
  	    return gen_rtx_AND (mode, op0, GEN_INT (INTVAL (op1) - 1));
  
  	  /* ... fall through ...  */
  
  	case MOD:
! 	  if ((trueop0 == const0_rtx || trueop1 == const1_rtx)
  	      && ! side_effects_p (op0) && ! side_effects_p (op1))
  	    return const0_rtx;
  	  break;
*************** simplify_binary_operation (code, mode, o
*** 1329,1336 ****
  	case ROTATERT:
  	case ROTATE:
  	  /* Rotating ~0 always results in ~0.  */
! 	  if (GET_CODE (op0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT
! 	      && (unsigned HOST_WIDE_INT) INTVAL (op0) == GET_MODE_MASK (mode)
  	      && ! side_effects_p (op1))
  	    return op0;
  
--- 1361,1368 ----
  	case ROTATERT:
  	case ROTATE:
  	  /* Rotating ~0 always results in ~0.  */
! 	  if (GET_CODE (trueop0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT
! 	      && (unsigned HOST_WIDE_INT) INTVAL (trueop0) == GET_MODE_MASK (mode)
  	      && ! side_effects_p (op1))
  	    return op0;
  
*************** simplify_binary_operation (code, mode, o
*** 1339,1380 ****
  	case ASHIFT:
  	case ASHIFTRT:
  	case LSHIFTRT:
! 	  if (op1 == const0_rtx)
  	    return op0;
! 	  if (op0 == const0_rtx && ! side_effects_p (op1))
  	    return op0;
  	  break;
  
  	case SMIN:
! 	  if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT 
! 	      && INTVAL (op1) == (HOST_WIDE_INT) 1 << (width -1)
  	      && ! side_effects_p (op0))
  	    return op1;
! 	  else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
  	    return op0;
  	  break;
  	   
  	case SMAX:
! 	  if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT
! 	      && ((unsigned HOST_WIDE_INT) INTVAL (op1)
  		  == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1)
  	      && ! side_effects_p (op0))
  	    return op1;
! 	  else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
  	    return op0;
  	  break;
  
  	case UMIN:
! 	  if (op1 == const0_rtx && ! side_effects_p (op0))
  	    return op1;
! 	  else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
  	    return op0;
  	  break;
  	    
  	case UMAX:
! 	  if (op1 == constm1_rtx && ! side_effects_p (op0))
  	    return op1;
! 	  else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
  	    return op0;
  	  break;
  
--- 1371,1412 ----
  	case ASHIFT:
  	case ASHIFTRT:
  	case LSHIFTRT:
! 	  if (trueop1 == const0_rtx)
  	    return op0;
! 	  if (trueop0 == const0_rtx && ! side_effects_p (op1))
  	    return op0;
  	  break;
  
  	case SMIN:
! 	  if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT 
! 	      && INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1)
  	      && ! side_effects_p (op0))
  	    return op1;
! 	  else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
  	  break;
  	   
  	case SMAX:
! 	  if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
! 	      && ((unsigned HOST_WIDE_INT) INTVAL (trueop1)
  		  == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1)
  	      && ! side_effects_p (op0))
  	    return op1;
! 	  else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
  	  break;
  
  	case UMIN:
! 	  if (trueop1 == const0_rtx && ! side_effects_p (op0))
  	    return op1;
! 	  else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
  	  break;
  	    
  	case UMAX:
! 	  if (trueop1 == constm1_rtx && ! side_effects_p (op0))
  	    return op1;
! 	  else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
  	  break;
  
*************** simplify_binary_operation (code, mode, o
*** 1388,1395 ****
    /* Get the integer argument values in two forms:
       zero-extended in ARG0, ARG1 and sign-extended in ARG0S, ARG1S.  */
  
!   arg0 = INTVAL (op0);
!   arg1 = INTVAL (op1);
  
    if (width < HOST_BITS_PER_WIDE_INT)
      {
--- 1420,1427 ----
    /* Get the integer argument values in two forms:
       zero-extended in ARG0, ARG1 and sign-extended in ARG0S, ARG1S.  */
  
!   arg0 = INTVAL (trueop0);
!   arg1 = INTVAL (trueop1);
  
    if (width < HOST_BITS_PER_WIDE_INT)
      {
*************** simplify_relational_operation (code, mod
*** 1785,1790 ****
--- 1817,1824 ----
  {
    int equal, op0lt, op0ltu, op1lt, op1ltu;
    rtx tem;
+   rtx trueop0 = avoid_constant_pool_reference (op0);
+   rtx trueop1 = avoid_constant_pool_reference (op1);
  
    if (mode == VOIDmode
        && (GET_MODE (op0) != VOIDmode
*************** simplify_relational_operation (code, mod
*** 1805,1813 ****
      return 0;
  
    /* Make sure the constant is second.  */
!   if (swap_commutative_operands_p (op0, op1))
      {
        tem = op0, op0 = op1, op1 = tem;
        code = swap_condition (code);
      }
  
--- 1839,1848 ----
      return 0;
  
    /* Make sure the constant is second.  */
!   if (swap_commutative_operands_p (trueop0, trueop1))
      {
        tem = op0, op0 = op1, op1 = tem;
+       tem = trueop0, trueop0 = trueop1, trueop1 = tem;
        code = swap_condition (code);
      }
  
*************** simplify_relational_operation (code, mod
*** 1821,1829 ****
       ANSI C defines unsigned operations such that they never overflow, and
       thus such cases can not be ignored.  */
  
!   if (INTEGRAL_MODE_P (mode) && op1 != const0_rtx
!       && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == CONST_INT)
! 	    && (GET_CODE (op1) == REG || GET_CODE (op1) == CONST_INT))
        && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
        && code != GTU && code != GEU && code != LTU && code != LEU)
      return simplify_relational_operation (signed_condition (code),
--- 1856,1864 ----
       ANSI C defines unsigned operations such that they never overflow, and
       thus such cases can not be ignored.  */
  
!   if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx
!       && ! ((GET_CODE (op0) == REG || GET_CODE (trueop0) == CONST_INT)
! 	    && (GET_CODE (op1) == REG || GET_CODE (trueop1) == CONST_INT))
        && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
        && code != GTU && code != GEU && code != LTU && code != LEU)
      return simplify_relational_operation (signed_condition (code),
*************** simplify_relational_operation (code, mod
*** 1837,1859 ****
  
    /* For non-IEEE floating-point, if the two operands are equal, we know the
       result.  */
!   if (rtx_equal_p (op0, op1)
        && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	  || ! FLOAT_MODE_P (GET_MODE (op0)) 
  	  || flag_unsafe_math_optimizations))
      equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
  
    /* If the operands are floating-point constants, see if we can fold
       the result.  */
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
!   else if (GET_CODE (op0) == CONST_DOUBLE && GET_CODE (op1) == CONST_DOUBLE
! 	   && GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
      {
        struct cfc_args args;
  
        /* Setup input for check_fold_consts() */
!       args.op0 = op0;
!       args.op1 = op1;
        
        
        if (!do_float_handler (check_fold_consts, (PTR) &args))
--- 1872,1895 ----
  
    /* For non-IEEE floating-point, if the two operands are equal, we know the
       result.  */
!   if (rtx_equal_p (trueop0, trueop1)
        && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
! 	  || ! FLOAT_MODE_P (GET_MODE (trueop0)) 
  	  || flag_unsafe_math_optimizations))
      equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
  
    /* If the operands are floating-point constants, see if we can fold
       the result.  */
  #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
!   else if (GET_CODE (trueop0) == CONST_DOUBLE
! 	   && GET_CODE (trueop1) == CONST_DOUBLE
! 	   && GET_MODE_CLASS (GET_MODE (trueop0)) == MODE_FLOAT)
      {
        struct cfc_args args;
  
        /* Setup input for check_fold_consts() */
!       args.op0 = trueop0;
!       args.op1 = trueop1;
        
        
        if (!do_float_handler (check_fold_consts, (PTR) &args))
*************** simplify_relational_operation (code, mod
*** 1891,1923 ****
  
    /* Otherwise, see if the operands are both integers.  */
    else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode)
! 	   && (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT)
! 	   && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT))
      {
        int width = GET_MODE_BITSIZE (mode);
        HOST_WIDE_INT l0s, h0s, l1s, h1s;
        unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u;
  
        /* Get the two words comprising each integer constant.  */
!       if (GET_CODE (op0) == CONST_DOUBLE)
  	{
! 	  l0u = l0s = CONST_DOUBLE_LOW (op0);
! 	  h0u = h0s = CONST_DOUBLE_HIGH (op0);
  	}
        else
  	{
! 	  l0u = l0s = INTVAL (op0);
  	  h0u = h0s = HWI_SIGN_EXTEND (l0s);
  	}
  	  
!       if (GET_CODE (op1) == CONST_DOUBLE)
  	{
! 	  l1u = l1s = CONST_DOUBLE_LOW (op1);
! 	  h1u = h1s = CONST_DOUBLE_HIGH (op1);
  	}
        else
  	{
! 	  l1u = l1s = INTVAL (op1);
  	  h1u = h1s = HWI_SIGN_EXTEND (l1s);
  	}
  
--- 1927,1961 ----
  
    /* Otherwise, see if the operands are both integers.  */
    else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode)
! 	   && (GET_CODE (trueop0) == CONST_DOUBLE
! 	       || GET_CODE (trueop0) == CONST_INT)
! 	   && (GET_CODE (trueop1) == CONST_DOUBLE
! 	       || GET_CODE (trueop1) == CONST_INT))
      {
        int width = GET_MODE_BITSIZE (mode);
        HOST_WIDE_INT l0s, h0s, l1s, h1s;
        unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u;
  
        /* Get the two words comprising each integer constant.  */
!       if (GET_CODE (trueop0) == CONST_DOUBLE)
  	{
! 	  l0u = l0s = CONST_DOUBLE_LOW (trueop0);
! 	  h0u = h0s = CONST_DOUBLE_HIGH (trueop0);
  	}
        else
  	{
! 	  l0u = l0s = INTVAL (trueop0);
  	  h0u = h0s = HWI_SIGN_EXTEND (l0s);
  	}
  	  
!       if (GET_CODE (trueop1) == CONST_DOUBLE)
  	{
! 	  l1u = l1s = CONST_DOUBLE_LOW (trueop1);
! 	  h1u = h1s = CONST_DOUBLE_HIGH (trueop1);
  	}
        else
  	{
! 	  l1u = l1s = INTVAL (trueop1);
  	  h1u = h1s = HWI_SIGN_EXTEND (l1s);
  	}
  
*************** simplify_relational_operation (code, mod
*** 1952,1959 ****
  	case EQ:
  	  /* References to the frame plus a constant or labels cannot
  	     be zero, but a SYMBOL_REF can due to #pragma weak.  */
! 	  if (((NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx)
! 	       || GET_CODE (op0) == LABEL_REF)
  #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
  	      /* On some machines, the ap reg can be 0 sometimes.  */
  	      && op0 != arg_pointer_rtx
--- 1990,1997 ----
  	case EQ:
  	  /* References to the frame plus a constant or labels cannot
  	     be zero, but a SYMBOL_REF can due to #pragma weak.  */
! 	  if (((NONZERO_BASE_PLUS_P (op0) && trueop1 == const0_rtx)
! 	       || GET_CODE (trueop0) == LABEL_REF)
  #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
  	      /* On some machines, the ap reg can be 0 sometimes.  */
  	      && op0 != arg_pointer_rtx
*************** simplify_relational_operation (code, mod
*** 1963,1970 ****
  	  break;
  
  	case NE:
! 	  if (((NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx)
! 	       || GET_CODE (op0) == LABEL_REF)
  #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
  	      && op0 != arg_pointer_rtx
  #endif
--- 2001,2008 ----
  	  break;
  
  	case NE:
! 	  if (((NONZERO_BASE_PLUS_P (op0) && trueop1 == const0_rtx)
! 	       || GET_CODE (trueop0) == LABEL_REF)
  #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
  	      && op0 != arg_pointer_rtx
  #endif
*************** simplify_relational_operation (code, mod
*** 1974,2000 ****
  
  	case GEU:
  	  /* Unsigned values are never negative.  */
! 	  if (op1 == const0_rtx)
  	    return const_true_rtx;
  	  break;
  
  	case LTU:
! 	  if (op1 == const0_rtx)
  	    return const0_rtx;
  	  break;
  
  	case LEU:
  	  /* Unsigned values are never greater than the largest
  	     unsigned value.  */
! 	  if (GET_CODE (op1) == CONST_INT
! 	      && (unsigned HOST_WIDE_INT) INTVAL (op1) == GET_MODE_MASK (mode)
  	    && INTEGRAL_MODE_P (mode))
  	  return const_true_rtx;
  	  break;
  
  	case GTU:
! 	  if (GET_CODE (op1) == CONST_INT
! 	      && (unsigned HOST_WIDE_INT) INTVAL (op1) == GET_MODE_MASK (mode)
  	      && INTEGRAL_MODE_P (mode))
  	    return const0_rtx;
  	  break;
--- 2012,2038 ----
  
  	case GEU:
  	  /* Unsigned values are never negative.  */
! 	  if (trueop1 == const0_rtx)
  	    return const_true_rtx;
  	  break;
  
  	case LTU:
! 	  if (trueop1 == const0_rtx)
  	    return const0_rtx;
  	  break;
  
  	case LEU:
  	  /* Unsigned values are never greater than the largest
  	     unsigned value.  */
! 	  if (GET_CODE (trueop1) == CONST_INT
! 	      && (unsigned HOST_WIDE_INT) INTVAL (trueop1) == GET_MODE_MASK (mode)
  	    && INTEGRAL_MODE_P (mode))
  	  return const_true_rtx;
  	  break;
  
  	case GTU:
! 	  if (GET_CODE (trueop1) == CONST_INT
! 	      && (unsigned HOST_WIDE_INT) INTVAL (trueop1) == GET_MODE_MASK (mode)
  	      && INTEGRAL_MODE_P (mode))
  	    return const0_rtx;
  	  break;


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