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]

Re: [patch] for PR 18529


Hello,

here is the new version of the patch, with subst renamed and the
a == b && something transformation moved out of fold.

Zdenek

	PR tree-optimization/18529
	* fold-const.c (simplify_replace_tree,
	fold_to_nonsharp_ineq_using_bound): New functions.
	(simple_operand_p): Use STRIP_NOPS.  Consider SSA names simple.
	(fold): Call fold_to_nonsharp_ineq_using_bound.
	* tree-ssa-loop-niter.c (number_of_iterations_cond): Fold the
	expressions before futher processing.
	(tree_simplify_using_condition): Handle case when cond or expr is
	an EQ_EXPR specially.
	* tree.h (simplify_replace_tree): Declare.

Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.475
diff -c -3 -p -r1.475 fold-const.c
*** fold-const.c	18 Nov 2004 12:09:36 -0000	1.475
--- fold-const.c	19 Nov 2004 11:19:47 -0000
*************** eval_subst (tree arg, tree old0, tree ne
*** 2833,2838 ****
--- 2833,2870 ----
        return arg;
      }
  }
+ 
+ /* Substitute NEW for OLD in EXPR and fold the result.  */
+ 
+ tree
+ simplify_replace_tree (tree expr, tree old, tree new)
+ {
+   unsigned i, n;
+   tree ret = NULL_TREE, e, se;
+ 
+   if (expr == old
+       || operand_equal_p (expr, old, 0))
+     return unshare_expr (new);
+ 
+   if (!EXPR_P (expr))
+     return expr;
+ 
+   n = TREE_CODE_LENGTH (TREE_CODE (expr));
+   for (i = 0; i < n; i++)
+     {
+       e = TREE_OPERAND (expr, i);
+       se = simplify_replace_tree (e, old, new);
+       if (e == se)
+ 	continue;
+ 
+       if (!ret)
+ 	ret = copy_node (expr);
+ 
+       TREE_OPERAND (ret, i) = se;
+     }
+ 
+   return (ret ? fold (ret) : expr);
+ }
  
  /* Return a tree for the case when the result of an expression is RESULT
     converted to TYPE and OMITTED was previously an operand of the expression
*************** static int
*** 3424,3436 ****
  simple_operand_p (tree exp)
  {
    /* Strip any conversions that don't change the machine mode.  */
!   while ((TREE_CODE (exp) == NOP_EXPR
! 	  || TREE_CODE (exp) == CONVERT_EXPR)
! 	 && (TYPE_MODE (TREE_TYPE (exp))
! 	     == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
!     exp = TREE_OPERAND (exp, 0);
  
    return (CONSTANT_CLASS_P (exp)
  	  || (DECL_P (exp)
  	      && ! TREE_ADDRESSABLE (exp)
  	      && ! TREE_THIS_VOLATILE (exp)
--- 3456,3465 ----
  simple_operand_p (tree exp)
  {
    /* Strip any conversions that don't change the machine mode.  */
!   STRIP_NOPS (exp);
  
    return (CONSTANT_CLASS_P (exp)
+ 	  || TREE_CODE (exp) == SSA_NAME
  	  || (DECL_P (exp)
  	      && ! TREE_ADDRESSABLE (exp)
  	      && ! TREE_THIS_VOLATILE (exp)
*************** try_move_mult_to_index (tree type, enum 
*** 6180,6185 ****
--- 6209,6260 ----
    return build1 (ADDR_EXPR, type, ret);
  }
  
+ 
+ /* Fold A < X && A + 1 > Y to A < X && A >= Y.  Normally A + 1 > Y
+    means A >= Y && A != MAX, but in this case we know that
+    A < X <= MAX.  INEQ is A + 1 > Y, BOUND is A < X.  */
+ 
+ static tree
+ fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
+ {
+   tree a, typea, type = TREE_TYPE (ineq), a1, y;
+ 
+   if (TREE_CODE (bound) == LT_EXPR)
+     a = TREE_OPERAND (bound, 0);
+   else if (TREE_CODE (bound) == GT_EXPR)
+     a = TREE_OPERAND (bound, 1);
+   else
+     return NULL_TREE;
+ 
+   typea = TREE_TYPE (a);
+   if (!INTEGRAL_TYPE_P (typea)
+       && !POINTER_TYPE_P (typea))
+     return NULL_TREE;
+ 
+   if (TREE_CODE (ineq) == LT_EXPR)
+     {
+       a1 = TREE_OPERAND (ineq, 1);
+       y = TREE_OPERAND (ineq, 0);
+     }
+   else if (TREE_CODE (ineq) == GT_EXPR)
+     {
+       a1 = TREE_OPERAND (ineq, 0);
+       y = TREE_OPERAND (ineq, 1);
+     }
+   else
+     return NULL_TREE;
+ 
+   if (TREE_TYPE (a1) != typea)
+     return NULL_TREE;
+ 
+   if (!operand_equal_p (a1,
+ 			build2 (PLUS_EXPR, typea, a,
+ 				build_int_cst_type (typea, 1)), 0))
+     return NULL_TREE;
+ 
+   return fold (build2 (GE_EXPR, type, a, y));
+ }
+ 
  /* Perform constant folding and related simplification of EXPR.
     The related simplifications include x*1 => x, x*0 => 0, etc.,
     and application of the associative law.
*************** fold (tree expr)
*** 8023,8028 ****
--- 8098,8119 ----
  	  && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
  	return omit_one_operand (type, integer_zero_node, arg0);
  
+       /* A < X && A + 1 > Y ==> A < X && A >= Y.  Normally A + 1 > Y
+ 	 means A >= Y && A != MAX, but in this case we know that
+ 	 A < X <= MAX.  */
+ 
+       if (!TREE_SIDE_EFFECTS (arg0)
+ 	  && !TREE_SIDE_EFFECTS (arg1))
+ 	{
+ 	  tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1);
+ 	  if (tem)
+ 	    return fold (build2 (code, type, tem, arg1));
+ 
+ 	  tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0);
+ 	  if (tem)
+ 	    return fold (build2 (code, type, arg0, tem));
+ 	}
+ 
      truth_andor:
        /* We only do these simplifications if we are optimizing.  */
        if (!optimize)
Index: tree-ssa-loop-niter.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-niter.c,v
retrieving revision 2.16
diff -c -3 -p -r2.16 tree-ssa-loop-niter.c
*** tree-ssa-loop-niter.c	15 Nov 2004 00:18:33 -0000	2.16
--- tree-ssa-loop-niter.c	19 Nov 2004 11:19:47 -0000
*************** number_of_iterations_cond (tree type, tr
*** 372,383 ****
  
  	  if (zero_p (step0))
  	    {
! 	      base0 = build2 (PLUS_EXPR, type, base0, delta);
  	      base0 = fold (build2 (MINUS_EXPR, type, base0, step));
  	    }
  	  else
  	    {
! 	      base1 = build2 (MINUS_EXPR, type, base1, delta);
  	      base1 = fold (build2 (PLUS_EXPR, type, base1, step));
  	    }
  
--- 372,383 ----
  
  	  if (zero_p (step0))
  	    {
! 	      base0 = fold (build2 (PLUS_EXPR, type, base0, delta));
  	      base0 = fold (build2 (MINUS_EXPR, type, base0, step));
  	    }
  	  else
  	    {
! 	      base1 = fold (build2 (MINUS_EXPR, type, base1, delta));
  	      base1 = fold (build2 (PLUS_EXPR, type, base1, step));
  	    }
  
*************** tree_simplify_using_condition (tree cond
*** 603,608 ****
--- 603,653 ----
        return expr;
      }
  
+   /* In case COND is equality, we may be able to simplify EXPR by copy/constant
+      propagation, and vice versa.  Fold does not handle this, since it is
+      considered too expensive.  */
+   if (TREE_CODE (cond) == EQ_EXPR)
+     {
+       e0 = TREE_OPERAND (cond, 0);
+       e1 = TREE_OPERAND (cond, 1);
+ 
+       /* We know that e0 == e1.  Check whether we cannot simplify expr
+ 	 using this fact.  */
+       e = simplify_replace_tree (expr, e0, e1);
+       if (zero_p (e) || nonzero_p (e))
+ 	return e;
+ 
+       e = simplify_replace_tree (expr, e1, e0);
+       if (zero_p (e) || nonzero_p (e))
+ 	return e;
+     }
+   if (TREE_CODE (expr) == EQ_EXPR)
+     {
+       e0 = TREE_OPERAND (expr, 0);
+       e1 = TREE_OPERAND (expr, 1);
+ 
+       /* If e0 == e1 (EXPR) implies !COND, then EXPR cannot be true.  */
+       e = simplify_replace_tree (cond, e0, e1);
+       if (zero_p (e))
+ 	return e;
+       e = simplify_replace_tree (cond, e1, e0);
+       if (zero_p (e))
+ 	return e;
+     }
+   if (TREE_CODE (expr) == NE_EXPR)
+     {
+       e0 = TREE_OPERAND (expr, 0);
+       e1 = TREE_OPERAND (expr, 1);
+ 
+       /* If e0 == e1 (!EXPR) implies !COND, then EXPR must be true.  */
+       e = simplify_replace_tree (cond, e0, e1);
+       if (zero_p (e))
+ 	return boolean_true_node;
+       e = simplify_replace_tree (cond, e1, e0);
+       if (zero_p (e))
+ 	return boolean_true_node;
+     }
+ 
    /* Check whether COND ==> EXPR.  */
    notcond = invert_truthvalue (cond);
    e = fold (build2 (TRUTH_OR_EXPR, boolean_type_node,
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.657
diff -c -3 -p -r1.657 tree.h
*** tree.h	17 Nov 2004 22:06:00 -0000	1.657
--- tree.h	19 Nov 2004 11:19:47 -0000
*************** extern bool tree_swap_operands_p (tree, 
*** 3540,3545 ****
--- 3540,3546 ----
  extern enum tree_code swap_tree_comparison (enum tree_code);
  
  extern bool ptr_difference_const (tree, tree, HOST_WIDE_INT *);
+ extern tree simplify_replace_tree (tree, tree, tree);
  
  /* In builtins.c */
  extern tree fold_builtin (tree, bool);


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