[tree-ssa/mainline PATCH] fold "test"==0 into constant

Jan Hubicka jh@suse.cz
Thu Nov 6 10:11:00 GMT 2003


Hi,
another problem I noticed debugging RTL expansion is that do_jump is able to
simplify if ("test"==0) into 0, while fold_const is not able to do so.  This
match several thousdant times during GCC boostrap to my surprise.

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.

Bootstrapped/regtested tree-SSA branch, mainline testing in progress (i386-unknown-linux).
OK for mainline/tree-SSA?
Honza

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 10:05:36 -0000
*************** tree_expr_nonnegative_p (tree t)
*** 8605,8610 ****
--- 8605,8719 ----
    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)
+ {
+   switch (TREE_CODE (t))
+     {
+     case ABS_EXPR:
+       return ((FLOAT_TYPE_P (t) || !TREE_OVERFLOW (t))
+ 	      && 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 (!TREE_OVERFLOW (t) && !FLOAT_TYPE_P (t))
+ 	{
+ 	  if (tree_expr_nonzero_p (TREE_OPERAND (t, 0)))
+ 	    return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ 	  if (tree_expr_nonzero_p (TREE_OPERAND (t, 1)))
+ 	    return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ 	  return false;
+ 	}
+       break;
+ 
+     case MULT_EXPR:
+       if (!TREE_OVERFLOW (t) && !FLOAT_TYPE_P (t))
+ 	{
+ 	  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 ****
--- 8896,8908 ----
  			   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)
      {



More information about the Gcc-patches mailing list