[tree-ssa] fix half of builtin-ctype-N.c

Richard Henderson rth@redhat.com
Wed May 5 18:20:00 GMT 2004


Many of the builtin-ctype subtests checked that we unified calls
to pure functions.  This part is fixed here.  The new OEP_PURE_SAME
is used in dom at a place at which we also check that the VUSEs
are the same, which ensures that we won't unify if there are
changes to global memory in between the two calls.

There are still subtests that are failing; I'll get to those shortly.


r~


        * fold-const.c (operand_equal_p): Replace only_const argument with
        flags.  Allow pure functions if OEP_PURE_SAME.
        (fold, nondestructive_fold_binary_to_constant): Use OEP_ONLY_CONST.
        * tree-cfg.c (phi_alternatives_equal): Fix operand_equal_p flag type.
        * tree-ssa-dom.c (avail_expr_eq): Use OEP_PURE_SAME.
        * tree.h (enum operand_equal_flag): New.
        (operand_equal_p): Update argument list.
ada/
        * utils.c (unchecked_convert): Use OEP_ONLY_CONST.

Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.213.2.88
diff -c -p -d -u -r1.213.2.88 fold-const.c
--- fold-const.c	29 Apr 2004 19:44:26 -0000	1.213.2.88
+++ fold-const.c	5 May 2004 17:02:07 -0000
@@ -2129,16 +2129,16 @@ truth_value_p (enum tree_code code)
 
 /* Return nonzero if two operands (typically of the same tree node)
    are necessarily equal.  If either argument has side-effects this
-   function returns zero.
+   function returns zero.  FLAGS modifies behaviour as follows:
 
-   If ONLY_CONST is nonzero, only return nonzero for constants.
+   If OEP_ONLY_CONST is set, only return nonzero for constants.
    This function tests whether the operands are indistinguishable;
    it does not test whether they are equal using C's == operation.
    The distinction is important for IEEE floating point, because
    (1) -0.0 and 0.0 are distinguishable, but -0.0==0.0, and
    (2) two NaNs may be indistinguishable, but NaN!=NaN.
 
-   If ONLY_CONST is zero, a VAR_DECL is considered equal to itself
+   If OEP_ONLY_CONST is unset, a VAR_DECL is considered equal to itself
    even though it may hold multiple values during a function.
    This is because a GCC tree node guarantees that nothing else is
    executed between the evaluation of its "operands" (which may often
@@ -2147,13 +2147,15 @@ truth_value_p (enum tree_code code)
    same value in each operand/subexpression.  Hence a zero value for
    ONLY_CONST assumes isochronic (or instantaneous) tree equivalence.
    If comparing arbitrary expression trees, such as from different
-   statements, ONLY_CONST must usually be nonzero.  */
+   statements, ONLY_CONST must usually be nonzero.
+
+   If OEP_PURE_SAME is set, then pure functions with identical arguments
+   are considered the same.  It is used when the caller has other ways
+   to ensure that global memory is unchanged in between.  */
 
 int
-operand_equal_p (tree arg0, tree arg1, int only_const)
+operand_equal_p (tree arg0, tree arg1, unsigned int flags)
 {
-  tree fndecl;
-
   /* If either is ERROR_MARK, they aren't equal.  */
   if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
     return 0;
@@ -2182,7 +2184,7 @@ operand_equal_p (tree arg0, tree arg1, i
      expressions with side effects that should be treated the same due
      to the only side effects being identical SAVE_EXPR's, that will
      be detected in the recursive calls below.  */
-  if (arg0 == arg1 && ! only_const
+  if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST)
       && (TREE_CODE (arg0) == SAVE_EXPR
 	  || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
     return 1;
@@ -2216,7 +2218,7 @@ operand_equal_p (tree arg0, tree arg1, i
 	  while (v1 && v2)
 	    {
 	      if (!operand_equal_p (TREE_VALUE (v1), TREE_VALUE (v2),
-				    only_const))
+				    flags))
 		return 0;
 	      v1 = TREE_CHAIN (v1);
 	      v2 = TREE_CHAIN (v2);
@@ -2227,9 +2229,9 @@ operand_equal_p (tree arg0, tree arg1, i
 
       case COMPLEX_CST:
 	return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1),
-				 only_const)
+				 flags)
 		&& operand_equal_p (TREE_IMAGPART (arg0), TREE_IMAGPART (arg1),
-				    only_const));
+				    flags));
 
       case STRING_CST:
 	return (TREE_STRING_LENGTH (arg0) == TREE_STRING_LENGTH (arg1)
@@ -2244,7 +2246,7 @@ operand_equal_p (tree arg0, tree arg1, i
 	break;
       }
 
-  if (only_const)
+  if (flags & OEP_ONLY_CONST)
     return 0;
 
   switch (TREE_CODE_CLASS (TREE_CODE (arg0)))
@@ -2257,7 +2259,7 @@ operand_equal_p (tree arg0, tree arg1, i
 	return 0;
 
       return operand_equal_p (TREE_OPERAND (arg0, 0),
-			      TREE_OPERAND (arg1, 0), 0);
+			      TREE_OPERAND (arg1, 0), flags);
 
     case '<':
     case '2':
@@ -2269,9 +2271,9 @@ operand_equal_p (tree arg0, tree arg1, i
       /* For commutative ops, allow the other order.  */
       return (commutative_tree_code (TREE_CODE (arg0))
 	      && operand_equal_p (TREE_OPERAND (arg0, 0),
-				  TREE_OPERAND (arg1, 1), 0)
+				  TREE_OPERAND (arg1, 1), flags)
 	      && operand_equal_p (TREE_OPERAND (arg0, 1),
-				  TREE_OPERAND (arg1, 0), 0));
+				  TREE_OPERAND (arg1, 0), flags));
 
     case 'r':
       /* If either of the pointer (or reference) expressions we are
@@ -2284,23 +2286,23 @@ operand_equal_p (tree arg0, tree arg1, i
 	{
 	case INDIRECT_REF:
 	  return operand_equal_p (TREE_OPERAND (arg0, 0),
-				  TREE_OPERAND (arg1, 0), 0);
+				  TREE_OPERAND (arg1, 0), flags);
 
 	case COMPONENT_REF:
 	case ARRAY_REF:
 	case ARRAY_RANGE_REF:
 	  return (operand_equal_p (TREE_OPERAND (arg0, 0),
-				   TREE_OPERAND (arg1, 0), 0)
+				   TREE_OPERAND (arg1, 0), flags)
 		  && operand_equal_p (TREE_OPERAND (arg0, 1),
-				      TREE_OPERAND (arg1, 1), 0));
+				      TREE_OPERAND (arg1, 1), flags));
 
 	case BIT_FIELD_REF:
 	  return (operand_equal_p (TREE_OPERAND (arg0, 0),
-				   TREE_OPERAND (arg1, 0), 0)
+				   TREE_OPERAND (arg1, 0), flags)
 		  && operand_equal_p (TREE_OPERAND (arg0, 1),
-				      TREE_OPERAND (arg1, 1), 0)
+				      TREE_OPERAND (arg1, 1), flags)
 		  && operand_equal_p (TREE_OPERAND (arg0, 2),
-				      TREE_OPERAND (arg1, 2), 0));
+				      TREE_OPERAND (arg1, 2), flags));
 	default:
 	  return 0;
 	}
@@ -2311,7 +2313,7 @@ operand_equal_p (tree arg0, tree arg1, i
 	case ADDR_EXPR:
 	case TRUTH_NOT_EXPR:
 	  return operand_equal_p (TREE_OPERAND (arg0, 0),
-				  TREE_OPERAND (arg1, 0), 0);
+				  TREE_OPERAND (arg1, 0), flags);
 
 	case RTL_EXPR:
 	  return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
@@ -2320,14 +2322,18 @@ operand_equal_p (tree arg0, tree arg1, i
 	  /* If the CALL_EXPRs call different functions, then they
 	     clearly can not be equal.  */
 	  if (! operand_equal_p (TREE_OPERAND (arg0, 0),
-				 TREE_OPERAND (arg1, 0), 0))
+				 TREE_OPERAND (arg1, 0), flags))
 	    return 0;
 
-	  /* Only consider const functions equivalent.  */
-	  fndecl = get_callee_fndecl (arg0);
-	  if (fndecl == NULL_TREE
-	      || ! (flags_from_decl_or_type (fndecl) & ECF_CONST))
-	    return 0;
+	  {
+	    unsigned int cef = call_expr_flags (arg0);
+	    if (flags & OEP_PURE_SAME)
+	      cef &= ECF_CONST | ECF_PURE;
+	    else
+	      cef &= ECF_CONST;
+	    if (!cef)
+	      return 0;
+	  }
 
 	  /* Now see if all the arguments are the same.  operand_equal_p
 	     does not handle TREE_LIST, so we walk the operands here
@@ -2336,7 +2342,8 @@ operand_equal_p (tree arg0, tree arg1, i
 	  arg1 = TREE_OPERAND (arg1, 1);
 	  while (arg0 && arg1)
 	    {
-	      if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1), 0))
+	      if (! operand_equal_p (TREE_VALUE (arg0), TREE_VALUE (arg1),
+				     flags))
 		return 0;
 
 	      arg0 = TREE_CHAIN (arg0);
@@ -2352,11 +2359,11 @@ operand_equal_p (tree arg0, tree arg1, i
 	}
 
     case 'd':
-	/* Consider __builtin_sqrt equal to sqrt.  */
-	return TREE_CODE (arg0) == FUNCTION_DECL
-	       && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
-	       && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
-	       && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1);
+      /* Consider __builtin_sqrt equal to sqrt.  */
+      return (TREE_CODE (arg0) == FUNCTION_DECL
+	      && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
+	      && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
+	      && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1));
 
     default:
       return 0;
@@ -5801,7 +5808,7 @@ fold (tree expr)
 	  tree s0 = TYPE_SIZE (tt0);
 	  tree s1 = TYPE_SIZE (tt1);
 
-	  if (s0 && s1 && operand_equal_p (s0, s1, 1))
+	  if (s0 && s1 && operand_equal_p (s0, s1, OEP_ONLY_CONST))
 	    return build (TREE_CODE (arg0), t0, convert (t0, arg00),
 		          TREE_OPERAND (arg0, 1));
 	}
@@ -7006,7 +7013,7 @@ fold (tree expr)
       if (operand_equal_p (arg0, arg1, 0))
 	return omit_one_operand (type, arg0, arg1);
       if (INTEGRAL_TYPE_P (type)
-	  && operand_equal_p (arg1, TYPE_MIN_VALUE (type), 1))
+	  && operand_equal_p (arg1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
 	return omit_one_operand (type, arg1, arg0);
       goto associate;
 
@@ -7015,7 +7022,7 @@ fold (tree expr)
 	return omit_one_operand (type, arg0, arg1);
       if (INTEGRAL_TYPE_P (type)
 	  && TYPE_MAX_VALUE (type)
-	  && operand_equal_p (arg1, TYPE_MAX_VALUE (type), 1))
+	  && operand_equal_p (arg1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
 	return omit_one_operand (type, arg1, arg0);
       goto associate;
 
@@ -8128,40 +8135,48 @@ fold (tree expr)
 
 	      case LT_EXPR:
 		/* If C1 is C2 + 1, this is min(A, C2).  */
-		if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), 1)
+		if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+				       OEP_ONLY_CONST)
 		    && operand_equal_p (TREE_OPERAND (arg0, 1),
 					const_binop (PLUS_EXPR, arg2,
-						     integer_one_node, 0), 1))
+						     integer_one_node, 0),
+					OEP_ONLY_CONST))
 		  return pedantic_non_lvalue
 		    (fold (build (MIN_EXPR, type, arg1, arg2)));
 		break;
 
 	      case LE_EXPR:
 		/* If C1 is C2 - 1, this is min(A, C2).  */
-		if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), 1)
+		if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+				       OEP_ONLY_CONST)
 		    && operand_equal_p (TREE_OPERAND (arg0, 1),
 					const_binop (MINUS_EXPR, arg2,
-						     integer_one_node, 0), 1))
+						     integer_one_node, 0),
+					OEP_ONLY_CONST))
 		  return pedantic_non_lvalue
 		    (fold (build (MIN_EXPR, type, arg1, arg2)));
 		break;
 
 	      case GT_EXPR:
 		/* If C1 is C2 - 1, this is max(A, C2).  */
-		if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), 1)
+		if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+				       OEP_ONLY_CONST)
 		    && operand_equal_p (TREE_OPERAND (arg0, 1),
 					const_binop (MINUS_EXPR, arg2,
-						     integer_one_node, 0), 1))
+						     integer_one_node, 0),
+					OEP_ONLY_CONST))
 		  return pedantic_non_lvalue
 		    (fold (build (MAX_EXPR, type, arg1, arg2)));
 		break;
 
 	      case GE_EXPR:
 		/* If C1 is C2 + 1, this is max(A, C2).  */
-		if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), 1)
+		if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+				       OEP_ONLY_CONST)
 		    && operand_equal_p (TREE_OPERAND (arg0, 1),
 					const_binop (PLUS_EXPR, arg2,
-						     integer_one_node, 0), 1))
+						     integer_one_node, 0),
+					OEP_ONLY_CONST))
 		  return pedantic_non_lvalue
 		    (fold (build (MAX_EXPR, type, arg1, arg2)));
 		break;
@@ -8214,7 +8229,7 @@ fold (tree expr)
 	  && integer_pow2p (arg1)
 	  && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
 	  && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
-			      arg1, 1))
+			      arg1, OEP_ONLY_CONST))
 	return pedantic_non_lvalue (fold_convert (type,
 						  TREE_OPERAND (arg0, 0)));
 
@@ -9345,7 +9360,7 @@ nondestructive_fold_binary_to_constant (
 
     case MIN_EXPR:
       if (INTEGRAL_TYPE_P (type)
-	  && operand_equal_p (op1, TYPE_MIN_VALUE (type), 1))
+	  && operand_equal_p (op1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
 	return omit_one_operand (type, op1, op0);
 
       goto binary;
@@ -9353,7 +9368,7 @@ nondestructive_fold_binary_to_constant (
     case MAX_EXPR:
       if (INTEGRAL_TYPE_P (type)
 	  && TYPE_MAX_VALUE (type)
-	  && operand_equal_p (op1, TYPE_MAX_VALUE (type), 1))
+	  && operand_equal_p (op1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
 	return omit_one_operand (type, op1, op0);
 
       goto binary;
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.282
diff -c -p -d -u -r1.1.4.282 tree-cfg.c
--- tree-cfg.c	4 May 2004 05:03:31 -0000	1.1.4.282
+++ tree-cfg.c	5 May 2004 17:02:07 -0000
@@ -2000,7 +2000,7 @@ phi_alternatives_equal (basic_block dest
       val1 = PHI_ARG_DEF (phi, n1);
       val2 = PHI_ARG_DEF (phi, n2);
 
-      if (!operand_equal_p (val1, val2, false))
+      if (!operand_equal_p (val1, val2, 0))
 	return false;
     }
 
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.160
diff -c -p -d -u -r1.1.2.160 tree-ssa-dom.c
--- tree-ssa-dom.c	22 Apr 2004 16:41:14 -0000	1.1.2.160
+++ tree-ssa-dom.c	5 May 2004 17:02:07 -0000
@@ -3048,7 +3048,7 @@ avail_expr_eq (const void *p1, const voi
      same VUSE operands.  */
   if ((TREE_TYPE (rhs1) == TREE_TYPE (rhs2)
        || lang_hooks.types_compatible_p (TREE_TYPE (rhs1), TREE_TYPE (rhs2)))
-      && operand_equal_p (rhs1, rhs2, 0))
+      && operand_equal_p (rhs1, rhs2, OEP_PURE_SAME))
     {
       vuse_optype ops1 = NULL;
       vuse_optype ops2 = NULL;
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.187
diff -c -p -d -u -r1.342.2.187 tree.h
--- tree.h	4 May 2004 05:03:31 -0000	1.342.2.187
+++ tree.h	5 May 2004 17:02:07 -0000
@@ -3468,7 +3468,14 @@ extern int div_and_round_double (enum tr
 				 HOST_WIDE_INT *, unsigned HOST_WIDE_INT *,
 				 HOST_WIDE_INT *);
 
-extern int operand_equal_p (tree, tree, int);
+enum operand_equal_flag
+{
+  OEP_ONLY_CONST = 1,
+  OEP_PURE_SAME = 2
+};
+
+extern int operand_equal_p (tree, tree, unsigned int);
+
 extern tree omit_one_operand (tree, tree, tree);
 extern tree invert_truthvalue (tree);
 extern tree nondestructive_fold_unary_to_constant (enum tree_code, tree, tree);
Index: ada/utils.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ada/utils.c,v
retrieving revision 1.19.2.21
diff -c -p -d -u -r1.19.2.21 utils.c
--- ada/utils.c	29 Apr 2004 19:44:57 -0000	1.19.2.21
+++ ada/utils.c	5 May 2004 17:02:08 -0000
@@ -3434,7 +3434,8 @@ unchecked_convert (tree type, tree expr,
   /* If the sizes of the types differ and this is an VIEW_CONVERT_EXPR,
      show no longer constant.  */
   if (TREE_CODE (expr) == VIEW_CONVERT_EXPR
-      && ! operand_equal_p (TYPE_SIZE_UNIT (type), TYPE_SIZE_UNIT (etype), 1))
+      && ! operand_equal_p (TYPE_SIZE_UNIT (type), TYPE_SIZE_UNIT (etype),
+			    OEP_ONLY_CONST))
     TREE_CONSTANT (expr) = 0;
 
   return expr;



More information about the Gcc-patches mailing list