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: [tree-ssa/mainline PATCH] fold "test"==0 into constant


> > 
> > Hi Jan,
> > > The patch bellow is based on merging tree_expr_nonnegative_p and RTL
> > > nonzero_address implementation so it catch these and slightly more
> > > sophisficated cases.
> > 
> > You need to guard some of these cases with checks for "! flag_wrapv".
> > The code in rtlanal.c's nonzero_address_p is valid only because it is
> > only used for addressing arithmetic which has undefined overflow.  In
> > Java, for example, "max (x, 1) + max (y, 1)" can still be zero, even
> > though each term must be greater than zero.  [p.s. it looks like
> 
> Isn't it what TREE_OVERFLOW flag is used for?

Hmm, I see it is not.
The attached patch adds code for your example, adds flag_wrapv checks
(hope I got them right now) and empty lines.
I am testing it now, OK if it passes?


2003-11-06  Jan Hubicka  <jh@suse.cz>
	* fold-const.c (tree_expr_nonzero_p): New function.
	(fold_relational_const): Use it.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.213.2.55
diff -c -3 -p -r1.213.2.55 fold-const.c
*** fold-const.c	30 Oct 2003 02:27:40 -0000	1.213.2.55
--- fold-const.c	6 Nov 2003 14:32:36 -0000
*************** tree_expr_nonnegative_p (tree t)
*** 8605,8610 ****
--- 8605,8735 ----
    return 0;
  }
  
+ /* Return true when T is an address and is known to be nonzero.
+    For floating point we further ensure that T is not denormal.
+    Similar logic is present in nonzero_address in rtlanal.h  */
+ static bool
+ tree_expr_nonzero_p (tree t)
+ {
+   tree type = TREE_TYPE (t);
+ 
+   switch (TREE_CODE (t))
+     {
+     case ABS_EXPR:
+       return ((FLOAT_TYPE_P (type) || (! TREE_UNSIGNED (type) && !flag_wrapv))
+ 	      && tree_expr_nonzero_p (t));
+ 
+     case INTEGER_CST:
+       return !integer_zerop (t);
+ 
+     case REAL_CST:
+       /* ??? We should check !real_zerop (t) && not-denormal.  */
+       return false;
+ 
+     case PLUS_EXPR:
+       if (FLOAT_TYPE_P (type) || (! TREE_UNSIGNED (type) && !flag_wrapv))
+ 	{
+ 	  if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)))
+ 	    return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ 	  else if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)))
+ 	    return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ 	  else return false;
+ 	  /* We know that at least one operand is nonzero.
+ 	     If both are positive, we win.  */
+ 	  if (tree_expr_nonnegative_p (TREE_OPERAND (t, 0)
+ 				       && TREE_OPERAND (1, 1)))
+ 	    return true;
+ 	  return false;
+ 	}
+       break;
+ 
+     case MULT_EXPR:
+       if (FLOAT_TYPE_P (type) || (! TREE_UNSIGNED (type) && !flag_wrapv))
+ 	{
+ 	  return (tree_expr_nonzero_p (TREE_OPERAND (t, 0))
+ 	          && tree_expr_nonzero_p (TREE_OPERAND (t, 1)));
+ 	}
+       break;
+ 
+     case NOP_EXPR:
+       {
+ 	tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
+ 	tree outer_type = TREE_TYPE (t);
+ 
+ 	return (TYPE_PRECISION (inner_type) >= TYPE_PRECISION (outer_type)
+ 		&& tree_expr_nonzero_p (TREE_OPERAND (t, 0)));
+ 	if (TREE_CODE (outer_type) == REAL_TYPE)
+ 	  {
+ 	    if (TREE_CODE (inner_type) == REAL_TYPE)
+ 	      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ 	    if (TREE_CODE (inner_type) == INTEGER_TYPE)
+ 	      {
+ 		if (TREE_UNSIGNED (inner_type))
+ 		  return 1;
+ 		return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ 	      }
+ 	  }
+ 	else if (TREE_CODE (outer_type) == INTEGER_TYPE)
+ 	  {
+ 	    if (TREE_CODE (inner_type) == REAL_TYPE)
+ 	      return tree_expr_nonnegative_p (TREE_OPERAND (t,0));
+ 	    if (TREE_CODE (inner_type) == INTEGER_TYPE)
+ 	      return TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type)
+ 		      && TREE_UNSIGNED (inner_type);
+ 	  }
+       }
+       break;
+ 
+    case ADDR_EXPR:
+       /* Weak declarations may link to NULL.  */
+       if (DECL_P (TREE_OPERAND (t, 0)))
+ 	return !DECL_WEAK (TREE_OPERAND (t, 0));
+       /* Constants and all other cases are never weak.  */
+       return true;
+ 
+     case COND_EXPR:
+       return (tree_expr_nonzero_p (TREE_OPERAND (t, 1))
+ 	      && tree_expr_nonzero_p (TREE_OPERAND (t, 2)));
+ 
+     case MIN_EXPR:
+       return (tree_expr_nonzero_p (TREE_OPERAND (t, 0))
+ 	      && tree_expr_nonzero_p (TREE_OPERAND (t, 1)));
+ 
+     case COMPOUND_EXPR:
+     case MODIFY_EXPR:
+     case BIND_EXPR:
+       return tree_expr_nonzero_p (TREE_OPERAND (t, 1));
+ 
+     case MAX_EXPR:
+       if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)))
+ 	{
+ 	  if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)))
+ 	    return true;
+ 	  return (tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ 	          && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)));
+ 	}
+       else if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)))
+ 	{
+ 	  if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)))
+ 	    return true;
+ 	  return (tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ 	          && tree_expr_nonnegative_p (TREE_OPERAND (t, 1)));
+ 	}
+       break;
+ 
+     case SAVE_EXPR:
+     case NON_LVALUE_EXPR:
+       return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
+ 
+     case RTL_EXPR:
+       return nonzero_address_p (RTL_EXPR_RTL (t));
+ 
+     default:
+       break;
+     }
+   return false;
+ }
+ 
  /* Return true if `r' is known to be non-negative.
     Only handles constants at the moment.  */
  
*************** fold_relational_const (enum tree_code co
*** 8787,8792 ****
--- 8912,8924 ----
  			   0);
      }
  
+   else if (code == EQ_EXPR
+            && integer_zerop (op1) && tree_expr_nonzero_p (op0))
+     tem = build_int_2 (0, 0);
+   else if (code == NE_EXPR
+            && integer_zerop (op1) && tree_expr_nonzero_p (op0))
+     tem = build_int_2 (1, 0);
+ 
    /* Two real constants can be compared explicitly.  */
    else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
      {


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