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]

Fold-const patch



Hi
This patch makes fold_const more serious about optimizing artihmetic
expressions.  It adds functions simplify_negate_expr and simplify_bit_not_expr,
that construct negated (not-ed) expression when it is possible to do so cheaply
(i.e w/o adding extra tree node).  Using it fold_const can convert subs to adds
and vice versa, propagate nots outside multiply and real divide etc.
Also some code duplication is avoided.

Note that I am not 100% sure that all the operations are valid for IEEE fp, but
I believe so, because IEEE fp behaves quite nicely to negate operation.
I didn't added any transformations that wasn't already done, only extended them
(by accepting not only NEGATE as subexpression, but any expression cheap to negate).

PS:
(OOPS. I see I forgot the prototype. I will add it...)

Čt prosinec 16 14:47:26 CET 1999  Jan Hubicka  <hubicka@freesoft.cz>
	* fold_const.c (simplify_negate_expr): New.
	(simplify_bit_not_expr): New.  (simplify_negate): Use
	simplify_negate_expr.  (fold): Optimize BIT_NOT_EXPR using
	simplify_bit_not_expr; likewise NEGATE_EXPR; optimize MINUS_EXPR to
	PLUS_EXPR when second operand can be negates; be more aggresive about
	propagating NEGATES outside MULT and RDIV; propagate NOTs outside XOR;
	optimize away XOR, AND and OR when operands are equal.

*** fold-const.c.noo	Thu Dec 16 09:54:45 1999
--- fold-const.c	Thu Dec 16 14:57:15 1999
*************** real_hex_to_f (s, mode)
*** 1205,1215 ****
  
  #endif /* no REAL_ARITHMETIC */
  
! /* Given T, an expression, return the negation of T.  Allow for T to be
!    null, in which case return null.  */
  
  static tree
! negate_expr (t)
       tree t;
  {
    tree type;
--- 1205,1215 ----
  
  #endif /* no REAL_ARITHMETIC */
  
! /* Given T, an expression, return the negation of T if it is possible to do it
!    without extra NEGATE operator.  Return NULL_TREE otherwise.  */
  
  static tree
! simplify_negate_expr (t)
       tree t;
  {
    tree type;
*************** negate_expr (t)
*** 1234,1239 ****
--- 1234,1247 ----
      case NEGATE_EXPR:
        return convert (type, TREE_OPERAND (t, 0));
  
+     case BIT_NOT_EXPR:
+       {
+ 	tree m1 = build_int_2 (1, 0);
+ 	TREE_TYPE (m1) = type;
+ 
+         return convert (type, fold (build (PLUS_EXPR, TREE_TYPE (t),
+ 					   TREE_OPERAND (t, 0), m1)));
+       }
      case MINUS_EXPR:
        /* - (A - B) -> B - A  */
        if (! FLOAT_TYPE_P (type) || flag_fast_math)
*************** negate_expr (t)
*** 1242,1252 ****
--- 1250,1361 ----
  				     TREE_OPERAND (t, 1),
  				     TREE_OPERAND (t, 0))));
        break;
+     case PLUS_EXPR:
+       /* - ((- A) + B) -> (A - B)  */
+       if (! FLOAT_TYPE_P (type) || flag_fast_math)
+ 	{
+ 	  tree tmp = simplify_negate_expr (TREE_OPERAND (t, 0));
+ 	  if (tmp != NULL_TREE)
+ 	    return convert (type,
+ 			    fold (build (MINUS_EXPR, TREE_TYPE (t),
+ 					 tmp,
+ 					 TREE_OPERAND (t, 1))));
+ 	  tmp = simplify_negate_expr (TREE_OPERAND (t, 1));
+ 	  if (tmp != NULL_TREE)
+ 	    return convert (type,
+ 			    fold (build (MINUS_EXPR, TREE_TYPE (t),
+ 					 tmp,
+ 					 TREE_OPERAND (t, 0))));
+ 	}
+       break;
  
      default:
        break;
      }
  
+   return NULL_TREE;
+ }
+ 
+ /* Given T, an expression, return the ~T if it is possible to do it
+    without extra BIT_NOT operator.  Return NULL_TREE otherwise.  */
+ 
+ static tree
+ simplify_bit_not_expr (t)
+      tree t;
+ {
+   tree type;
+   tree tem;
+ 
+   if (t == 0)
+     return 0;
+ 
+   type = TREE_TYPE (t);
+   STRIP_SIGN_NOPS (t);
+ 
+   switch (TREE_CODE (t))
+     {
+     case INTEGER_CST:
+     case REAL_CST:
+       if (!TREE_UNSIGNED (type)
+ 	  && 0 != (tem = fold (build1 (BIT_NOT_EXPR, type, t)))
+ 	  && !TREE_OVERFLOW (tem))
+ 	return tem;
+       break;
+ 
+     case BIT_NOT_EXPR:
+       return convert (type, TREE_OPERAND (t, 0));
+ 
+     case NEGATE_EXPR:
+       {
+ 	tree m1 = build_int_2 (~0, ~0);
+ 	TREE_TYPE (m1) = type;
+ 	force_fit_type (m1, 0);
+ 
+ 	return convert (type, fold (build (PLUS_EXPR, TREE_TYPE (t),
+ 					   TREE_OPERAND (t, 0), m1)));
+       }
+     case BIT_XOR_EXPR:
+       {
+ 	tree tmp = simplify_bit_not_expr (TREE_OPERAND (t, 0));
+ 	if (tmp)
+ 	    return convert (type,
+ 			    fold (build (BIT_XOR_EXPR, TREE_TYPE (t),
+ 					 tmp,
+ 					 TREE_OPERAND (t, 1))));
+ 	tmp = simplify_bit_not_expr (TREE_OPERAND (t, 1));
+ 	if (tmp)
+ 	    return convert (type,
+ 			    fold (build (BIT_XOR_EXPR, TREE_TYPE (t),
+ 					 tmp,
+ 					 TREE_OPERAND (t, 0))));
+       }
+ 
+     default:
+       break;
+     }
+ 
+   return NULL_TREE;
+ }
+ /* Given T, an expression, return the negation of T.  Allow for T to be
+    null, in which case return null.  */
+ 
+ static tree
+ negate_expr (t)
+      tree t;
+ {
+   tree type;
+   tree tem;
+ 
+   if (t == 0)
+     return 0;
+ 
+   tem = simplify_negate_expr(t);
+   if (tem != NULL_TREE)
+     return tem;
+ 
+   type = TREE_TYPE (t);
+   STRIP_SIGN_NOPS (t);
+ 
    return convert (type, build1 (NEGATE_EXPR, TREE_TYPE (t), t));
  }
  
*************** fold (expr) 
*** 5075,5088 ****
  	  else if (TREE_CODE (arg0) == REAL_CST)
  	    t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
  	}
-       else if (TREE_CODE (arg0) == NEGATE_EXPR)
- 	return TREE_OPERAND (arg0, 0);
  
!       /* Convert - (a - b) to (b - a) for non-floating-point.  */
!       else if (TREE_CODE (arg0) == MINUS_EXPR
! 	       && (! FLOAT_TYPE_P (type) || flag_fast_math))
! 	return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
! 		      TREE_OPERAND (arg0, 0));
  
        return t;
  
--- 5184,5194 ----
  	  else if (TREE_CODE (arg0) == REAL_CST)
  	    t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
  	}
  
!       /* Avoid infinite recursion.  */
!       if (TREE_CODE (arg0) != INTEGER_CST && TREE_CODE (arg0) != REAL_CST
! 	  && (t1 = simplify_negate_expr (arg0)) != NULL_TREE)
! 	return t1;
  
        return t;
  
*************** fold (expr) 
*** 5148,5155 ****
  	  TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
  	  TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0);
  	}
!       else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
! 	return TREE_OPERAND (arg0, 0);
        return t;
  
      case PLUS_EXPR:
--- 5254,5264 ----
  	  TREE_OVERFLOW (t) = TREE_OVERFLOW (arg0);
  	  TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0);
  	}
! 
!       /* Avoid infinite recursion.  */
!       if (TREE_CODE (arg0) != INTEGER_CST && TREE_CODE (arg0) != REAL_CST
! 	  && (t1 = simplify_bit_not_expr (arg0)) != NULL_TREE)
! 	return t1;
        return t;
  
      case PLUS_EXPR:
*************** fold (expr) 
*** 5405,5420 ****
        return t;
  
      case MINUS_EXPR:
!       /* A - (-B) -> A + B */
!       if (TREE_CODE (arg1) == NEGATE_EXPR)
! 	return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
!       /* (-A) - CST -> (-CST) - A   for floating point (what about ints ?)  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST)
! 	return
! 	  fold (build (MINUS_EXPR, type, 
! 		       build_real (TREE_TYPE (arg1),
! 				   REAL_VALUE_NEGATE (TREE_REAL_CST (arg1))),
! 		       TREE_OPERAND (arg0, 0)));
  
        if (! FLOAT_TYPE_P (type))
  	{
--- 5514,5523 ----
        return t;
  
      case MINUS_EXPR:
!       /* Convert MINUS to PLUS if possible.  */
!       t1 = simplify_negate_expr (arg1);
!       if (t1 != NULL_TREE)
! 	return fold (build (PLUS_EXPR, type, arg0, t1));
  
        if (! FLOAT_TYPE_P (type))
  	{
*************** fold (expr) 
*** 5423,5428 ****
--- 5526,5538 ----
  	  if (integer_zerop (arg1))
  	    return non_lvalue (convert (type, arg0));
  
+ 	  /* Try to convert (-A) - B to -(A + B) in hope that more powerfull
+ 	     optimizations for PLUS will be done or NOT will be eliminated later.  */
+ 	  if (TREE_CODE (arg0) == NEGATE_EXPR)
+ 	    return fold (build1 (NEGATE_EXPR, type,
+ 				 fold (build (PLUS_EXPR, type,
+ 					      TREE_OPERAND (arg0, 0), arg1))));
+ 
  	  /* (A * C) - (B * C) -> (A-B) * C.  Since we are most concerned
  	     about the case where C is a constant, just try one of the
  	     four possibilities.  */
*************** fold (expr) 
*** 5462,5470 ****
  
      case MULT_EXPR:
        /* (-A) * (-B) -> A * B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
! 	return fold (build (MULT_EXPR, type, TREE_OPERAND (arg0, 0),
! 		            TREE_OPERAND (arg1, 0)));
  
        if (! FLOAT_TYPE_P (type))
  	{
--- 5572,5583 ----
  
      case MULT_EXPR:
        /* (-A) * (-B) -> A * B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR 
! 	  && (t1 = simplify_negate_expr (arg1)) != NULL_TREE)
! 	return fold (build (MULT_EXPR, type, TREE_OPERAND (arg0, 0), t1));
!       if (TREE_CODE (arg1) == NEGATE_EXPR 
! 	  && (t1 = simplify_negate_expr (arg0)) != NULL_TREE)
! 	return fold (build (MULT_EXPR, type, t1, TREE_OPERAND (arg1, 0)));
  
        if (! FLOAT_TYPE_P (type))
  	{
*************** fold (expr) 
*** 5515,5521 ****
      bit_ior:
        if (integer_all_onesp (arg1))
  	return omit_one_operand (type, arg1, arg0);
!       if (integer_zerop (arg1))
  	return non_lvalue (convert (type, arg0));
        t1 = distribute_bit_expr (code, type, arg0, arg1);
        if (t1 != NULL_TREE)
--- 5628,5634 ----
      bit_ior:
        if (integer_all_onesp (arg1))
  	return omit_one_operand (type, arg1, arg0);
!       if (integer_zerop (arg1) || operand_equal_p (arg0, arg1, 0))
  	return non_lvalue (convert (type, arg0));
        t1 = distribute_bit_expr (code, type, arg0, arg1);
        if (t1 != NULL_TREE)
*************** fold (expr) 
*** 5545,5550 ****
--- 5658,5665 ----
  	return non_lvalue (convert (type, arg0));
        if (integer_all_onesp (arg1))
  	return fold (build1 (BIT_NOT_EXPR, type, arg0));
+       if (operand_equal_p (arg0, arg1, 0))
+ 	return convert (type, integer_zero_node);
  
        /* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
           with a constant, and the two constants have no bits in common,
*************** fold (expr) 
*** 5562,5574 ****
  	   goto bit_ior;
          }
  
        /* See if this can be simplified into a rotate first.  If that
  	 is unsuccessful continue in the association code.  */
        goto bit_rotate;
  
      case BIT_AND_EXPR:
      bit_and:
!       if (integer_all_onesp (arg1))
  	return non_lvalue (convert (type, arg0));
        if (integer_zerop (arg1))
  	return omit_one_operand (type, arg1, arg0);
--- 5677,5701 ----
  	   goto bit_ior;
          }
  
+       /* Propagate NOTs outside XOR.  */
+       if (TREE_CODE (arg0) == BIT_NOT_EXPR)
+ 	return fold (build1 (BIT_NOT_EXPR, type,
+ 			     fold (build (BIT_XOR_EXPR, type,
+ 					  TREE_OPERAND (arg0, 0),
+ 					  arg1))));
+       if (TREE_CODE (arg1) == BIT_NOT_EXPR)
+ 	return fold (build1 (BIT_NOT_EXPR, type,
+ 			     fold (build (BIT_XOR_EXPR, type,
+ 					  arg0,
+ 					  TREE_OPERAND (arg1, 0)))));
+ 
        /* See if this can be simplified into a rotate first.  If that
  	 is unsuccessful continue in the association code.  */
        goto bit_rotate;
  
      case BIT_AND_EXPR:
      bit_and:
!       if (integer_all_onesp (arg1) || operand_equal_p (arg0, arg1, 0))
  	return non_lvalue (convert (type, arg0));
        if (integer_zerop (arg1))
  	return omit_one_operand (type, arg1, arg0);
*************** fold (expr) 
*** 5635,5643 ****
  #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
  
        /* (-A) / (-B) -> A / B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
! 	return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
! 			    TREE_OPERAND (arg1, 0)));
  
        /* In IEEE floating point, x/1 is not equivalent to x for snans.
  	 However, ANSI says we can drop signals, so we can do this anyway.  */
--- 5762,5773 ----
  #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
  
        /* (-A) / (-B) -> A / B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR 
! 	  && (t1 = simplify_negate_expr (arg1)) != NULL_TREE)
! 	return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0), t1));
!       if (TREE_CODE (arg1) == NEGATE_EXPR 
! 	  && (t1 = simplify_negate_expr (arg0)) != NULL_TREE)
! 	return fold (build (RDIV_EXPR, type, t1, TREE_OPERAND (arg1, 0)));
  
        /* In IEEE floating point, x/1 is not equivalent to x for snans.
  	 However, ANSI says we can drop signals, so we can do this anyway.  */


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