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][no-undefined-overflow] Finish fold binary transition


This finishes audit of the PLUS/MINUS/MULT expression foldings and
reassociation.  I also removed restrictions on reassociation that
were in place because of correctness with undefined overflow.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the 
branch.

Richard.

2009-03-12  Richard Guenther  <rguenther@suse.de>

	* fold-const.c (fold_plusminus_mult_expr): Handle *NV_EXPR.
	(fold_binary): Complete PLUS_EXPR, MINUS_EXPR and MULT_EXPR
	auditing.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c.orig	2009-03-10 16:58:45.000000000 +0100
--- gcc/fold-const.c	2009-03-10 17:35:16.000000000 +0100
*************** fold_plusminus_mult_expr (enum tree_code
*** 7406,7412 ****
       but other combinations show up during loop reduction.  Since
       it is not difficult, try all four possibilities.  */
  
!   if (TREE_CODE (arg0) == MULT_EXPR)
      {
        arg00 = TREE_OPERAND (arg0, 0);
        arg01 = TREE_OPERAND (arg0, 1);
--- 7406,7412 ----
       but other combinations show up during loop reduction.  Since
       it is not difficult, try all four possibilities.  */
  
!   if (MULT_EXPR_P (arg0))
      {
        arg00 = TREE_OPERAND (arg0, 0);
        arg01 = TREE_OPERAND (arg0, 1);
*************** fold_plusminus_mult_expr (enum tree_code
*** 7424,7430 ****
        arg00 = arg0;
        arg01 = build_one_cst (type);
      }
!   if (TREE_CODE (arg1) == MULT_EXPR)
      {
        arg10 = TREE_OPERAND (arg1, 0);
        arg11 = TREE_OPERAND (arg1, 1);
--- 7424,7430 ----
        arg00 = arg0;
        arg01 = build_one_cst (type);
      }
!   if (MULT_EXPR_P (arg1))
      {
        arg10 = TREE_OPERAND (arg1, 0);
        arg11 = TREE_OPERAND (arg1, 1);
*************** fold_plusminus_mult_expr (enum tree_code
*** 7436,7442 ****
  	 the purpose of this canonicalization.  */
        if (TREE_INT_CST_HIGH (arg1) == -1
  	  && negate_expr_p (arg1)
! 	  && code == PLUS_EXPR)
  	{
  	  arg11 = negate_expr (arg1);
  	  code = MINUS_EXPR;
--- 7436,7442 ----
  	 the purpose of this canonicalization.  */
        if (TREE_INT_CST_HIGH (arg1) == -1
  	  && negate_expr_p (arg1)
! 	  && PLUS_EXPR_CODE_P (code))
  	{
  	  arg11 = negate_expr (arg1);
  	  code = MINUS_EXPR;
*************** fold_plusminus_mult_expr (enum tree_code
*** 7501,7507 ****
  
    if (same)
      return fold_build2 (MULT_EXPR, type,
! 			fold_build2 (code, type,
  				     fold_convert (type, alt0),
  				     fold_convert (type, alt1)),
  			fold_convert (type, same));
--- 7501,7507 ----
  
    if (same)
      return fold_build2 (MULT_EXPR, type,
! 			fold_build2 (strip_nv (code), type,
  				     fold_convert (type, alt0),
  				     fold_convert (type, alt1)),
  			fold_convert (type, same));
*************** fold_binary (enum tree_code code, tree t
*** 9814,9823 ****
        if (integer_zerop (arg1))
  	return non_lvalue (fold_convert (type, arg0));
  
-       /* PTR_CST +p CST -> CST1 */
-       if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
- 	return fold_build2 (PLUS_EXPR, type, arg0, fold_convert (type, arg1));
- 
        /* INT +p INT -> (PTR)(INT + INT).  Stripping types allows for this. */
        if (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
  	   && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
--- 9814,9819 ----
*************** fold_binary (enum tree_code code, tree t
*** 9849,9857 ****
  					    TREE_TYPE (arg00), arg00, inner));
  	}
  
!      /* Try replacing &a[i1] +p c * i2 with &a[i1 + i2], if c is step
! 	of the array.  Loop optimizer sometimes produce this type of
! 	expressions.  */
        if (TREE_CODE (arg0) == ADDR_EXPR)
  	{
  	  tem = try_move_mult_to_index (arg0, fold_convert (sizetype, arg1));
--- 9845,9857 ----
  					    TREE_TYPE (arg00), arg00, inner));
  	}
  
!       /* PTR_CST +p CST -> CST1 */
!       if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
! 	return fold_build2 (PLUS_EXPR, type, arg0, fold_convert (type, arg1));
! 
!       /* Try replacing &a[i1] +p c * i2 with &a[i1 + i2], if c is step
! 	 of the array.  Loop optimizer sometimes produce this type of
! 	 expressions.  */
        if (TREE_CODE (arg0) == ADDR_EXPR)
  	{
  	  tem = try_move_mult_to_index (arg0, fold_convert (sizetype, arg1));
*************** fold_binary (enum tree_code code, tree t
*** 9863,9885 ****
  
      case PLUS_EXPR:
      case PLUSNV_EXPR:
-       if (! FLOAT_TYPE_P (type))
- 	{
- 	  if (integer_zerop (arg1))
- 	    return non_lvalue (fold_convert (type, arg0));
- 	}
- 
-       /* ???  Auditing required.  */
-       if (code == PLUSNV_EXPR)
- 	return NULL_TREE;
- 
        /* A + (-B) -> A - B */
!       if (TREE_CODE (arg1) == NEGATE_EXPR)
  	return fold_build2 (MINUS_EXPR, type,
  			    fold_convert (type, arg0),
  			    fold_convert (type, TREE_OPERAND (arg1, 0)));
        /* (-A) + B -> B - A */
!       if (TREE_CODE (arg0) == NEGATE_EXPR
  	  && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
  	return fold_build2 (MINUS_EXPR, type,
  			    fold_convert (type, arg1),
--- 9863,9875 ----
  
      case PLUS_EXPR:
      case PLUSNV_EXPR:
        /* A + (-B) -> A - B */
!       if (NEGATE_EXPR_P (arg1))
  	return fold_build2 (MINUS_EXPR, type,
  			    fold_convert (type, arg0),
  			    fold_convert (type, TREE_OPERAND (arg1, 0)));
        /* (-A) + B -> B - A */
!       if (NEGATE_EXPR_P (arg0)
  	  && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
  	return fold_build2 (MINUS_EXPR, type,
  			    fold_convert (type, arg1),
*************** fold_binary (enum tree_code code, tree t
*** 9922,9928 ****
  	    }
  
  	  /* X + (X / CST) * -CST is X % CST.  */
! 	  if (TREE_CODE (arg1) == MULT_EXPR
  	      && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
  	      && operand_equal_p (arg0,
  				  TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0))
--- 9912,9918 ----
  	    }
  
  	  /* X + (X / CST) * -CST is X % CST.  */
! 	  if (MULT_EXPR_P (arg1)
  	      && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
  	      && operand_equal_p (arg0,
  				  TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0))
*************** fold_binary (enum tree_code code, tree t
*** 9940,9947 ****
        /* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the
  	 same or one.  Make sure type is not saturating.
  	 fold_plusminus_mult_expr will re-associate.  */
!       if ((TREE_CODE (arg0) == MULT_EXPR
! 	   || TREE_CODE (arg1) == MULT_EXPR)
  	  && !TYPE_SATURATING (type)
  	  && (!FLOAT_TYPE_P (type) || flag_associative_math))
          {
--- 9930,9937 ----
        /* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the
  	 same or one.  Make sure type is not saturating.
  	 fold_plusminus_mult_expr will re-associate.  */
!       if ((MULT_EXPR_P (arg0)
! 	   || MULT_EXPR_P (arg1))
  	  && !TYPE_SATURATING (type)
  	  && (!FLOAT_TYPE_P (type) || flag_associative_math))
          {
*************** fold_binary (enum tree_code code, tree t
*** 9952,9957 ****
--- 9942,9950 ----
  
        if (! FLOAT_TYPE_P (type))
  	{
+ 	  if (integer_zerop (arg1))
+ 	    return non_lvalue (fold_convert (type, arg0));
+ 
  	  /* If we are adding two BIT_AND_EXPR's, both of which are and'ing
  	     with a constant, and the two constants have no bits in common,
  	     we should treat this as a BIT_IOR_EXPR since this may produce more
*************** fold_binary (enum tree_code code, tree t
*** 9971,10005 ****
  	  /* Reassociate (plus (plus (mult) (foo)) (mult)) as
  	     (plus (plus (mult) (mult)) (foo)) so that we can
  	     take advantage of the factoring cases below.  */
! 	  if (((TREE_CODE (arg0) == PLUS_EXPR
! 		|| TREE_CODE (arg0) == MINUS_EXPR)
! 	       && TREE_CODE (arg1) == MULT_EXPR)
! 	      || ((TREE_CODE (arg1) == PLUS_EXPR
! 		   || TREE_CODE (arg1) == MINUS_EXPR)
! 		  && TREE_CODE (arg0) == MULT_EXPR))
  	    {
  	      tree parg0, parg1, parg, marg;
  	      enum tree_code pcode;
  
! 	      if (TREE_CODE (arg1) == MULT_EXPR)
  		parg = arg0, marg = arg1;
  	      else
  		parg = arg1, marg = arg0;
! 	      pcode = TREE_CODE (parg);
  	      parg0 = TREE_OPERAND (parg, 0);
  	      parg1 = TREE_OPERAND (parg, 1);
  	      STRIP_NOPS (parg0);
  	      STRIP_NOPS (parg1);
  
! 	      if (TREE_CODE (parg0) == MULT_EXPR
! 		  && TREE_CODE (parg1) != MULT_EXPR)
  		return fold_build2 (pcode, type,
  				    fold_build2 (PLUS_EXPR, type,
  						 fold_convert (type, parg0),
  						 fold_convert (type, marg)),
  				    fold_convert (type, parg1));
! 	      if (TREE_CODE (parg0) != MULT_EXPR
! 		  && TREE_CODE (parg1) == MULT_EXPR)
  		return fold_build2 (PLUS_EXPR, type,
  				    fold_convert (type, parg0),
  				    fold_build2 (pcode, type,
--- 9964,9996 ----
  	  /* Reassociate (plus (plus (mult) (foo)) (mult)) as
  	     (plus (plus (mult) (mult)) (foo)) so that we can
  	     take advantage of the factoring cases below.  */
! 	  if (((PLUS_EXPR_P (arg0) || MINUS_EXPR_P (arg0))
! 	       && MULT_EXPR_P (arg1))
! 	      || ((PLUS_EXPR_P (arg1) || MINUS_EXPR_P (arg1))
! 		  && MULT_EXPR_P (arg0)))
  	    {
  	      tree parg0, parg1, parg, marg;
  	      enum tree_code pcode;
  
! 	      if (MULT_EXPR_P (arg1))
  		parg = arg0, marg = arg1;
  	      else
  		parg = arg1, marg = arg0;
! 	      pcode = strip_nv (TREE_CODE (parg));
  	      parg0 = TREE_OPERAND (parg, 0);
  	      parg1 = TREE_OPERAND (parg, 1);
  	      STRIP_NOPS (parg0);
  	      STRIP_NOPS (parg1);
  
! 	      if (MULT_EXPR_P (parg0)
! 		  && !MULT_EXPR_P (parg1))
  		return fold_build2 (pcode, type,
  				    fold_build2 (PLUS_EXPR, type,
  						 fold_convert (type, parg0),
  						 fold_convert (type, marg)),
  				    fold_convert (type, parg1));
! 	      if (!MULT_EXPR_P (parg0)
! 		  && MULT_EXPR_P (parg1))
  		return fold_build2 (PLUS_EXPR, type,
  				    fold_convert (type, parg0),
  				    fold_build2 (pcode, type,
*************** fold_binary (enum tree_code code, tree t
*** 10149,10155 ****
  		    == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
  	      return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
  			     code0 == LSHIFT_EXPR ? tree01 : tree11);
! 	    else if (code11 == MINUS_EXPR)
  	      {
  		tree tree110, tree111;
  		tree110 = TREE_OPERAND (tree11, 0);
--- 10140,10146 ----
  		    == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
  	      return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
  			     code0 == LSHIFT_EXPR ? tree01 : tree11);
! 	    else if (MINUS_EXPR_CODE_P (code11))
  	      {
  		tree tree110, tree111;
  		tree110 = TREE_OPERAND (tree11, 0);
*************** fold_binary (enum tree_code code, tree t
*** 10167,10173 ****
  				  : RROTATE_EXPR),
  				 type, TREE_OPERAND (arg0, 0), tree01);
  	      }
! 	    else if (code01 == MINUS_EXPR)
  	      {
  		tree tree010, tree011;
  		tree010 = TREE_OPERAND (tree01, 0);
--- 10158,10164 ----
  				  : RROTATE_EXPR),
  				 type, TREE_OPERAND (arg0, 0), tree01);
  	      }
! 	    else if (MINUS_EXPR_CODE_P (code01))
  	      {
  		tree tree010, tree011;
  		tree010 = TREE_OPERAND (tree01, 0);
*************** fold_binary (enum tree_code code, tree t
*** 10295,10308 ****
  
      case MINUS_EXPR:
      case MINUSNV_EXPR:
-       if (! FLOAT_TYPE_P (type))
- 	{
- 	  if (integer_zerop (arg0))
- 	    return negate_expr (fold_convert (type, arg1));
- 	  if (integer_zerop (arg1))
- 	    return non_lvalue (fold_convert (type, arg0));
- 	}
- 
        /* Pointer simplifications for subtraction, simple reassociations. */
        if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0)))
  	{
--- 10286,10291 ----
*************** fold_binary (enum tree_code code, tree t
*** 10331,10346 ****
  	    }
  	}
  
-       /* ???  Auditing required.  */
-       if (code == MINUSNV_EXPR)
- 	return NULL_TREE;
- 
        /* A - (-B) -> A + B */
!       if (TREE_CODE (arg1) == NEGATE_EXPR)
  	return fold_build2 (PLUS_EXPR, type, op0,
  			    fold_convert (type, TREE_OPERAND (arg1, 0)));
        /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR
  	  && (FLOAT_TYPE_P (type)
  	      || INTEGRAL_TYPE_P (type))
  	  && negate_expr_p (arg1)
--- 10314,10325 ----
  	    }
  	}
  
        /* A - (-B) -> A + B */
!       if (NEGATE_EXPR_P (arg1))
  	return fold_build2 (PLUS_EXPR, type, op0,
  			    fold_convert (type, TREE_OPERAND (arg1, 0)));
        /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
!       if (NEGATE_EXPR_P (arg0)
  	  && (FLOAT_TYPE_P (type)
  	      || INTEGRAL_TYPE_P (type))
  	  && negate_expr_p (arg1)
*************** fold_binary (enum tree_code code, tree t
*** 10350,10358 ****
  			    fold_convert (type, TREE_OPERAND (arg0, 0)));
        /* Convert -A - 1 to ~A.  */
        if (INTEGRAL_TYPE_P (type)
! 	  && TREE_CODE (arg0) == NEGATE_EXPR
! 	  && integer_onep (arg1)
! 	  && !TYPE_OVERFLOW_TRAPS (type))
  	return fold_build1 (BIT_NOT_EXPR, type,
  			    fold_convert (type, TREE_OPERAND (arg0, 0)));
  
--- 10329,10338 ----
  			    fold_convert (type, TREE_OPERAND (arg0, 0)));
        /* Convert -A - 1 to ~A.  */
        if (INTEGRAL_TYPE_P (type)
! 	  && ((TREE_CODE (arg0) == NEGATE_EXPR
! 	       && !TYPE_OVERFLOW_TRAPS (type))
! 	      || TREE_CODE (arg0) == NEGATENV_EXPR)
! 	  && integer_onep (arg1))
  	return fold_build1 (BIT_NOT_EXPR, type,
  			    fold_convert (type, TREE_OPERAND (arg0, 0)));
  
*************** fold_binary (enum tree_code code, tree t
*** 10364,10370 ****
  
        /* X - (X / CST) * CST is X % CST.  */
        if (INTEGRAL_TYPE_P (type)
! 	  && TREE_CODE (arg1) == MULT_EXPR
  	  && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
  	  && operand_equal_p (arg0,
  			      TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
--- 10344,10350 ----
  
        /* X - (X / CST) * CST is X % CST.  */
        if (INTEGRAL_TYPE_P (type)
! 	  && MULT_EXPR_P (arg1)
  	  && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
  	  && operand_equal_p (arg0,
  			      TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
*************** fold_binary (enum tree_code code, tree t
*** 10376,10381 ****
--- 10356,10366 ----
  
        if (! FLOAT_TYPE_P (type))
  	{
+ 	  if (integer_zerop (arg0))
+ 	    return negate_expr (fold_convert (type, arg1));
+ 	  if (integer_zerop (arg1))
+ 	    return non_lvalue (fold_convert (type, arg0));
+ 
  	  /* Fold A - (A & B) into ~B & A.  */
  	  if (!TREE_SIDE_EFFECTS (arg0)
  	      && TREE_CODE (arg1) == BIT_AND_EXPR)
*************** fold_binary (enum tree_code code, tree t
*** 10524,10531 ****
        /* Handle (A1 * C1) - (A2 * C2) with A1, A2 or C1, C2 being the
  	 same or one.  Make sure type is not saturating.
  	 fold_plusminus_mult_expr will re-associate.  */
!       if ((TREE_CODE (arg0) == MULT_EXPR
! 	   || TREE_CODE (arg1) == MULT_EXPR)
  	  && !TYPE_SATURATING (type)
  	  && (!FLOAT_TYPE_P (type) || flag_associative_math))
          {
--- 10509,10516 ----
        /* Handle (A1 * C1) - (A2 * C2) with A1, A2 or C1, C2 being the
  	 same or one.  Make sure type is not saturating.
  	 fold_plusminus_mult_expr will re-associate.  */
!       if ((MULT_EXPR_P (arg0)
! 	   || MULT_EXPR_P (arg1))
  	  && !TYPE_SATURATING (type)
  	  && (!FLOAT_TYPE_P (type) || flag_associative_math))
          {
*************** fold_binary (enum tree_code code, tree t
*** 10551,10566 ****
  	    return fold_convert (type, negate_expr (op0));
  	}
  
!       /* ???  Auditing required.  */
!       if (code == MULTNV_EXPR)
! 	return NULL_TREE;
! 
!       /* (-A) * (-B) -> A * B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
  	return fold_build2 (MULT_EXPR, type,
  			    fold_convert (type, TREE_OPERAND (arg0, 0)),
  			    fold_convert (type, negate_expr (arg1)));
!       if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
  	return fold_build2 (MULT_EXPR, type,
  			    fold_convert (type, negate_expr (arg0)),
  			    fold_convert (type, TREE_OPERAND (arg1, 0)));
--- 10536,10547 ----
  	    return fold_convert (type, negate_expr (op0));
  	}
  
!       /* (-A) * (-B) -> A * B.  */
!       if (NEGATE_EXPR_P (arg0) && negate_expr_p (arg1))
  	return fold_build2 (MULT_EXPR, type,
  			    fold_convert (type, TREE_OPERAND (arg0, 0)),
  			    fold_convert (type, negate_expr (arg1)));
!       if (NEGATE_EXPR_P (arg1) && negate_expr_p (arg0))
  	return fold_build2 (MULT_EXPR, type,
  			    fold_convert (type, negate_expr (arg0)),
  			    fold_convert (type, TREE_OPERAND (arg1, 0)));
*************** fold_binary (enum tree_code code, tree t
*** 10587,10593 ****
  				TREE_OPERAND (arg0, 1));
  
  	  /* (A + A) * C -> A * 2 * C  */
! 	  if (TREE_CODE (arg0) == PLUS_EXPR
  	      && TREE_CODE (arg1) == INTEGER_CST
  	      && operand_equal_p (TREE_OPERAND (arg0, 0),
  			          TREE_OPERAND (arg0, 1), 0))
--- 10568,10574 ----
  				TREE_OPERAND (arg0, 1));
  
  	  /* (A + A) * C -> A * 2 * C  */
! 	  if (PLUS_EXPR_P (arg0)
  	      && TREE_CODE (arg1) == INTEGER_CST
  	      && operand_equal_p (TREE_OPERAND (arg0, 0),
  			          TREE_OPERAND (arg0, 1), 0))


2009-03-12  Richard Guenther  <rguenther@suse.de>

	* fold-const.c (split_tree): Handle *NV_EXPR.
	(associate_trees): Likewise.
	(fold_binary): Re-enable reassociation.  Remove restriction
	for reassociating signed integers or pointers.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c.orig	2009-03-10 14:36:29.000000000 +0100
--- gcc/fold-const.c	2009-03-10 14:41:51.000000000 +0100
*************** split_tree (tree in, enum tree_code code
*** 1481,1492 ****
  		  though the C standard doesn't say so) for integers because
  		  the value is not affected.  For reals, the value might be
  		  affected, so we can't.  */
! 	       && ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR)
! 		   || (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR))))
      {
        tree op0 = TREE_OPERAND (in, 0);
        tree op1 = TREE_OPERAND (in, 1);
!       int neg1_p = TREE_CODE (in) == MINUS_EXPR;
        int neg_litp_p = 0, neg_conp_p = 0, neg_var_p = 0;
  
        /* First see if either of the operands is a literal, then a constant.  */
--- 1481,1492 ----
  		  though the C standard doesn't say so) for integers because
  		  the value is not affected.  For reals, the value might be
  		  affected, so we can't.  */
! 	       && ((PLUS_EXPR_CODE_P (code) && MINUS_EXPR_P (in))
! 		   || (MINUS_EXPR_CODE_P (code) && PLUS_EXPR_P (in)))))
      {
        tree op0 = TREE_OPERAND (in, 0);
        tree op1 = TREE_OPERAND (in, 1);
!       int neg1_p = MINUS_EXPR_P (in);
        int neg_litp_p = 0, neg_conp_p = 0, neg_var_p = 0;
  
        /* First see if either of the operands is a literal, then a constant.  */
*************** associate_trees (tree t1, tree t2, enum
*** 1552,1582 ****
    /* If either input is CODE, a PLUS_EXPR, or a MINUS_EXPR, don't
       try to fold this since we will have infinite recursion.  But do
       deal with any NEGATE_EXPRs.  */
!   if (TREE_CODE (t1) == code || TREE_CODE (t2) == code
!       || TREE_CODE (t1) == MINUS_EXPR || TREE_CODE (t2) == MINUS_EXPR)
      {
!       if (code == PLUS_EXPR)
  	{
! 	  if (TREE_CODE (t1) == NEGATE_EXPR)
  	    return build2 (MINUS_EXPR, type, fold_convert (type, t2),
  			   fold_convert (type, TREE_OPERAND (t1, 0)));
! 	  else if (TREE_CODE (t2) == NEGATE_EXPR)
  	    return build2 (MINUS_EXPR, type, fold_convert (type, t1),
  			   fold_convert (type, TREE_OPERAND (t2, 0)));
  	  else if (integer_zerop (t2))
  	    return fold_convert (type, t1);
  	}
!       else if (code == MINUS_EXPR)
  	{
  	  if (integer_zerop (t2))
  	    return fold_convert (type, t1);
  	}
  
!       return build2 (code, type, fold_convert (type, t1),
  		     fold_convert (type, t2));
      }
  
!   return fold_build2 (code, type, fold_convert (type, t1),
  		      fold_convert (type, t2));
  }
  
--- 1552,1583 ----
    /* If either input is CODE, a PLUS_EXPR, or a MINUS_EXPR, don't
       try to fold this since we will have infinite recursion.  But do
       deal with any NEGATE_EXPRs.  */
!   if (TREE_CODE (t1) == code
!       || TREE_CODE (t2) == code
!       || MINUS_EXPR_P (t1) || MINUS_EXPR_P (t2))
      {
!       if (PLUS_EXPR_CODE_P (code))
  	{
! 	  if (NEGATE_EXPR_P (t1))
  	    return build2 (MINUS_EXPR, type, fold_convert (type, t2),
  			   fold_convert (type, TREE_OPERAND (t1, 0)));
! 	  else if (NEGATE_EXPR_P (t2))
  	    return build2 (MINUS_EXPR, type, fold_convert (type, t1),
  			   fold_convert (type, TREE_OPERAND (t2, 0)));
  	  else if (integer_zerop (t2))
  	    return fold_convert (type, t1);
  	}
!       else if (MINUS_EXPR_CODE_P (code))
  	{
  	  if (integer_zerop (t2))
  	    return fold_convert (type, t1);
  	}
  
!       return build2 (strip_nv (code), type, fold_convert (type, t1),
  		     fold_convert (type, t2));
      }
  
!   return fold_build2 (strip_nv (code), type, fold_convert (type, t1),
  		      fold_convert (type, t2));
  }
  
*************** fold_binary (enum tree_code code, tree t
*** 10194,10200 ****
  	{
  	  tree var0, con0, lit0, minus_lit0;
  	  tree var1, con1, lit1, minus_lit1;
- 	  bool ok = true;
  
  	  /* Split both trees into variables, constants, and literals.  Then
  	     associate each group together, the constants with literals,
--- 10195,10200 ----
*************** fold_binary (enum tree_code code, tree t
*** 10203,10239 ****
  	     expressions for the sum of a constant and literal.  */
  	  var0 = split_tree (arg0, code, &con0, &lit0, &minus_lit0, 0);
  	  var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
! 			     code == MINUS_EXPR);
! 
! 	  /* With undefined overflow we can only associate constants
! 	     with one variable.  */
! 	  if (((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
! 	       || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
! 	      && var0 && var1)
! 	    {
! 	      tree tmp0 = var0;
! 	      tree tmp1 = var1;
! 
! 	      if (TREE_CODE (tmp0) == NEGATE_EXPR)
! 	        tmp0 = TREE_OPERAND (tmp0, 0);
! 	      if (TREE_CODE (tmp1) == NEGATE_EXPR)
! 	        tmp1 = TREE_OPERAND (tmp1, 0);
! 	      /* The only case we can still associate with two variables
! 		 is if they are the same, modulo negation.  */
! 	      if (!operand_equal_p (tmp0, tmp1, 0))
! 	        ok = false;
! 	    }
  
  	  /* Only do something if we found more than two objects.  Otherwise,
  	     nothing has changed and we risk infinite recursion.  */
! 	  if (ok
! 	      && (2 < ((var0 != 0) + (var1 != 0)
! 		       + (con0 != 0) + (con1 != 0)
! 		       + (lit0 != 0) + (lit1 != 0)
! 		       + (minus_lit0 != 0) + (minus_lit1 != 0))))
  	    {
  	      /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
! 	      if (code == MINUS_EXPR)
  		code = PLUS_EXPR;
  
  	      var0 = associate_trees (var0, var1, code, type);
--- 10203,10219 ----
  	     expressions for the sum of a constant and literal.  */
  	  var0 = split_tree (arg0, code, &con0, &lit0, &minus_lit0, 0);
  	  var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
! 			     MINUS_EXPR_CODE_P (code));
  
  	  /* Only do something if we found more than two objects.  Otherwise,
  	     nothing has changed and we risk infinite recursion.  */
! 	  if (2 < ((var0 != 0) + (var1 != 0)
! 		   + (con0 != 0) + (con1 != 0)
! 		   + (lit0 != 0) + (lit1 != 0)
! 		   + (minus_lit0 != 0) + (minus_lit1 != 0)))
  	    {
  	      /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
! 	      if (MINUS_EXPR_CODE_P (code))
  		code = PLUS_EXPR;
  
  	      var0 = associate_trees (var0, var1, code, type);


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