[PATCH] New simplify_associative_operation function

Roger Sayle roger@eyesopen.com
Sun Aug 17 03:57:00 GMT 2003


This is another step towards unification of our RTL simplifiers.

The following patch implements some optimizations of associative
binary operations in simplify_binary_operation.  Because these
transformations are valid for PLUS, MULT, AND, IOR, XOR, SMIN,
SMAX, UMIN and UMAX they've been factored into their own function,
simplify_associative_operation that's shared by all of the above.

The transformations that are performed include

	(x op c1) op c2		=>	x op (c1 op c2)
	(x op c1) op (y op c2)	=>	(x op y) op (c1 op c2)
	(x op c) op y		=>	(x op y) op c
	x op (y op c)		=>	(x op y) op c

where "c" is an immediate integer or floating point constant.
Because these constants may be represented by either CONST_INT or
CONST_DOUBLE and may even be stored in a constant pool, this patch
also introduces a associative_constant_p function for identifying
suitable constants.

Finally, we make sure that we only reassociate floating point
additions and multiplications when the user requests unsafe
math optimizations.


There are no new test cases with this patch, as many/most/all? of these
transformations are already applied in fold_rtx and combine_simplify_rtx,
hence its difficult to show an observable change in functionality.  This
patch will, however, allow us to remove this redundancy in the future.


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-08-16  Roger Sayle  <roger@eyesopen.com>

	* simplify-rtx.c (associative_constant_p): New function to test
	whether an RTX expression is an immediate constant.
	(simplify_associative_operation): New function to perform some
	reassociation optimizations of associative binary expressions.
	(simplify_binary_operation): Use simplify_associative_operation
	to simplify PLUS, MULT, AND, IOR, XOR, SMIN, SMAX, UMIN and UMAX.
	Floating point expressions are only reassociated when unsafe
	math optimizations are permitted.


Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.152
diff -c -3 -p -r1.152 simplify-rtx.c
*** simplify-rtx.c	12 Aug 2003 01:46:54 -0000	1.152
--- simplify-rtx.c	16 Aug 2003 20:02:48 -0000
*************** static rtx neg_const_int (enum machine_m
*** 53,58 ****
--- 53,61 ----
  static int simplify_plus_minus_op_data_cmp (const void *, const void *);
  static rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx,
  				rtx, int);
+ static bool associative_constant_p (rtx);
+ static rtx simplify_associative_operation (enum rtx_code, enum machine_mode,
+ 					   rtx, rtx);

  /* Negate a CONST_INT rtx, truncating (because a conversion from a
     maximally negative number can overflow).  */
*************** simplify_unary_operation (enum rtx_code
*** 854,859 ****
--- 857,928 ----
      }
  }

+ /* Subroutine of simplify_associative_operation.  Return true if rtx OP
+    is a suitable integer or floating point immediate constant.  */
+ static bool
+ associative_constant_p (rtx op)
+ {
+   if (GET_CODE (op) == CONST_INT
+       || GET_CODE (op) == CONST_DOUBLE)
+     return true;
+   op = avoid_constant_pool_reference (op);
+   return GET_CODE (op) == CONST_INT
+ 	 || GET_CODE (op) == CONST_DOUBLE;
+ }
+
+ /* Subroutine of simplify_binary_operation to simplify an associative
+    binary operation CODE with result mode MODE, operating on OP0 and OP1.
+    Return 0 if no simplification is possible.  */
+ static rtx
+ simplify_associative_operation (enum rtx_code code, enum machine_mode mode,
+ 				rtx op0, rtx op1)
+ {
+   rtx tem;
+
+   /* Simplify (x op c1) op c2 as x op (c1 op c2).  */
+   if (GET_CODE (op0) == code
+       && associative_constant_p (op1)
+       && associative_constant_p (XEXP (op0, 1)))
+     {
+       tem = simplify_binary_operation (code, mode, XEXP (op0, 1), op1);
+       if (! tem)
+ 	return tem;
+       return simplify_gen_binary (code, mode, XEXP (op0, 0), tem);
+     }
+
+   /* Simplify (x op c1) op (y op c2) as (x op y) op (c1 op c2).  */
+   if (GET_CODE (op0) == code
+       && GET_CODE (op1) == code
+       && associative_constant_p (XEXP (op0, 1))
+       && associative_constant_p (XEXP (op1, 1)))
+     {
+       rtx c = simplify_binary_operation (code, mode,
+ 					 XEXP (op0, 1), XEXP (op1, 1));
+       if (! c)
+ 	return 0;
+       tem = simplify_gen_binary (code, mode, XEXP (op0, 0), XEXP (op1, 0));
+       return simplify_gen_binary (code, mode, tem, c);
+     }
+
+   /* Canonicalize (x op c) op y as (x op y) op c.  */
+   if (GET_CODE (op0) == code
+       && associative_constant_p (XEXP (op0, 1)))
+     {
+       tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1);
+       return simplify_gen_binary (code, mode, tem, XEXP (op0, 1));
+     }
+
+   /* Canonicalize x op (y op c) as (x op y) op c.  */
+   if (GET_CODE (op1) == code
+       && associative_constant_p (XEXP (op1, 1)))
+     {
+       tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0));
+       return simplify_gen_binary (code, mode, tem, XEXP (op1, 1));
+     }
+
+   return 0;
+ }
+
  /* Simplify a binary operation CODE with result mode MODE, operating on OP0
     and OP1.  Return 0 if no simplification is possible.

*************** simplify_binary_operation (enum rtx_code
*** 1179,1184 ****
--- 1248,1263 ----
  		      && GET_CODE (XEXP (op1, 0)) == PLUS))
  	      && (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
  	    return tem;
+
+ 	  /* Reassociate floating point addition only when the user
+ 	     specifies unsafe math optimizations.  */
+ 	  if (FLOAT_MODE_P (mode)
+ 	      && flag_unsafe_math_optimizations)
+ 	    {
+ 	      tem = simplify_associative_operation (code, mode, op0, op1);
+ 	      if (tem)
+ 		return tem;
+ 	    }
  	  break;

  	case COMPARE:
*************** simplify_binary_operation (enum rtx_code
*** 1388,1393 ****
--- 1467,1482 ----
  	      if (REAL_VALUES_EQUAL (d, dconstm1))
  		return simplify_gen_unary (NEG, mode, op0, mode);
  	    }
+
+ 	  /* Reassociate multiplication, but for floating point MULTs
+ 	     only when the user specifies unsafe math optimizations.  */
+ 	  if (! FLOAT_MODE_P (mode)
+ 	      || flag_unsafe_math_optimizations)
+ 	    {
+ 	      tem = simplify_associative_operation (code, mode, op0, op1);
+ 	      if (tem)
+ 		return tem;
+ 	    }
  	  break;

  	case IOR:
*************** simplify_binary_operation (enum rtx_code
*** 1405,1410 ****
--- 1494,1502 ----
  	      && ! side_effects_p (op0)
  	      && GET_MODE_CLASS (mode) != MODE_CC)
  	    return constm1_rtx;
+ 	  tem = simplify_associative_operation (code, mode, op0, op1);
+ 	  if (tem)
+ 	    return tem;
  	  break;

  	case XOR:
*************** simplify_binary_operation (enum rtx_code
*** 1417,1422 ****
--- 1509,1517 ----
  	  if (trueop0 == trueop1 && ! side_effects_p (op0)
  	      && GET_MODE_CLASS (mode) != MODE_CC)
  	    return const0_rtx;
+ 	  tem = simplify_associative_operation (code, mode, op0, op1);
+ 	  if (tem)
+ 	    return tem;
  	  break;

  	case AND:
*************** simplify_binary_operation (enum rtx_code
*** 1435,1440 ****
--- 1530,1538 ----
  	      && ! side_effects_p (op0)
  	      && GET_MODE_CLASS (mode) != MODE_CC)
  	    return const0_rtx;
+ 	  tem = simplify_associative_operation (code, mode, op0, op1);
+ 	  if (tem)
+ 	    return tem;
  	  break;

  	case UDIV:
*************** simplify_binary_operation (enum rtx_code
*** 1524,1559 ****
  	  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;

  	case SS_PLUS:
--- 1622,1671 ----
  	  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;
! 	  if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
+ 	  tem = simplify_associative_operation (code, mode, op0, op1);
+ 	  if (tem)
+ 	    return tem;
  	  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;
! 	  if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
+ 	  tem = simplify_associative_operation (code, mode, op0, op1);
+ 	  if (tem)
+ 	    return tem;
  	  break;

  	case UMIN:
  	  if (trueop1 == const0_rtx && ! side_effects_p (op0))
  	    return op1;
! 	  if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
+ 	  tem = simplify_associative_operation (code, mode, op0, op1);
+ 	  if (tem)
+ 	    return tem;
  	  break;

  	case UMAX:
  	  if (trueop1 == constm1_rtx && ! side_effects_p (op0))
  	    return op1;
! 	  if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
  	    return op0;
+ 	  tem = simplify_associative_operation (code, mode, op0, op1);
+ 	  if (tem)
+ 	    return tem;
  	  break;

  	case SS_PLUS:

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



More information about the Gcc-patches mailing list