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] Introduce force_fit_type_double, remove force_fit_type


This patch removes force_fit_type in favor of force_fit_type_double that
takes a double-int and a type argument.  This reduces intermediate types
created and cleans up the source as all uses left of force_fit_type are of
the form

  t = build_int_cst_wide (type, low, high);
  t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
                    TREE_CONSTANT_OVERFLOW (arg1));

which first creates a shared integer node (of possibly uncanonicalized form)
and then truncates it properly and propagates overflow flags.  Combining
this two steps also allows to adjust int_const_binop to produce less garbage
on overflow.

Bootstrapped and tested on i686-pc-linux-gnu, another on on
x86_64-unknown-linux-gnu for all languages still running.

Is the new name ok or should I re-use the old one, force_fit_type?
I also thought of build_and_force_fit_and_propagate_overflow_int_wide (),
but that's ugly ;)  Suggestions?

Thanks,
Richard.

2007-01-08 Richard Guenther <rguenther@suse.de>

       * tree.h (force_fit_type_double): Export.
       (force_fit_type): Remove.
       * fold-const.c (force_fit_type_double): New function.
       (force_fit_type): Remove.
       (int_const_binop): Use it.
       (fold_convert_const_int_from_int): Likewise.
       (fold_convert_const_int_from_real): Likewise.
       (fold_div_compare): Likewise.
       (fold_sign_changed_comparison): Likewise.
       (fold_unary): Likewise.
       (fold_negate_const): Likewise.
       (fold_abs_const): Likewise.
       (fold_not_const): Likewise.
       * c-common.c (shorten_compare): Use force_fit_type_double.
       * convert.c (convert_to_pointer): Likewise.
2007-01-08  Richard Guenther  <rguenther@suse.de>

	* tree.h (force_fit_type_double): Export.
	(force_fit_type): Remove.
	* fold-const.c (force_fit_type_double): New function.
	(force_fit_type): Remove.
	(int_const_binop): Use it.
	(fold_convert_const_int_from_int): Likewise.
	(fold_convert_const_int_from_real): Likewise.
	(fold_div_compare): Likewise.
	(fold_sign_changed_comparison): Likewise.
	(fold_unary): Likewise.
	(fold_negate_const): Likewise.
	(fold_abs_const): Likewise. 
	(fold_not_const): Likewise.
	* c-common.c (shorten_compare): Use force_fit_type_double.
	* convert.c (convert_to_pointer): Likewise.

Index: gcc/c-common.c
===================================================================
*** gcc.orig/c-common.c	2007-01-08 20:43:56.000000000 +0100
--- gcc/c-common.c	2007-01-08 20:49:13.000000000 +0100
*************** shorten_compare (tree *op0_ptr, tree *op
*** 2316,2327 ****
  	{
  	  /* Convert primop1 to target type, but do not introduce
  	     additional overflow.  We know primop1 is an int_cst.  */
! 	  tree tmp = build_int_cst_wide (*restype_ptr,
! 					 TREE_INT_CST_LOW (primop1),
! 					 TREE_INT_CST_HIGH (primop1));
! 
! 	  primop1 = force_fit_type (tmp, 0, TREE_OVERFLOW (primop1),
! 				    TREE_CONSTANT_OVERFLOW (primop1));
  	}
        if (type != *restype_ptr)
  	{
--- 2316,2326 ----
  	{
  	  /* Convert primop1 to target type, but do not introduce
  	     additional overflow.  We know primop1 is an int_cst.  */
! 	  primop1 = force_fit_type_double (*restype_ptr,
! 					   TREE_INT_CST_LOW (primop1),
! 					   TREE_INT_CST_HIGH (primop1), 0,
! 					   TREE_OVERFLOW (primop1),
! 					   TREE_CONSTANT_OVERFLOW (primop1));
  	}
        if (type != *restype_ptr)
  	{
Index: gcc/convert.c
===================================================================
*** gcc.orig/convert.c	2007-01-08 20:43:56.000000000 +0100
--- gcc/convert.c	2007-01-08 20:49:13.000000000 +0100
*************** convert_to_pointer (tree type, tree expr
*** 44,57 ****
    if (TREE_TYPE (expr) == type)
      return expr;
  
    if (integer_zerop (expr))
!     {
!       tree t = build_int_cst (type, 0);
!       if (TREE_OVERFLOW (expr) || TREE_CONSTANT_OVERFLOW (expr))
! 	t = force_fit_type (t, 0, TREE_OVERFLOW (expr),
! 			    TREE_CONSTANT_OVERFLOW (expr));
!       return t;
!     }
  
    switch (TREE_CODE (TREE_TYPE (expr)))
      {
--- 44,53 ----
    if (TREE_TYPE (expr) == type)
      return expr;
  
+   /* Propagate overflow to the NULL pointer.  */
    if (integer_zerop (expr))
!     return force_fit_type_double (type, 0, 0, 0, TREE_OVERFLOW (expr),
! 				  TREE_CONSTANT_OVERFLOW (expr));
  
    switch (TREE_CODE (TREE_TYPE (expr)))
      {
Index: gcc/fold-const.c
===================================================================
*** gcc.orig/fold-const.c	2007-01-08 20:43:56.000000000 +0100
--- gcc/fold-const.c	2007-01-08 20:54:29.000000000 +0100
*************** fit_double_type (unsigned HOST_WIDE_INT 
*** 263,268 ****
--- 263,333 ----
    return l1 != low0 || h1 != high0;
  }
  
+ /* We force the double-int HIGH:LOW to the range of the type TYPE by
+    sign or zero extending it.
+    OVERFLOWABLE indicates if we are interested
+    in overflow of the value, when >0 we are only interested in signed
+    overflow, for <0 we are interested in any overflow.  OVERFLOWED
+    indicates whether overflow has already occurred.  CONST_OVERFLOWED
+    indicates whether constant overflow has already occurred.  We force
+    T's value to be within range of T's type (by setting to 0 or 1 all
+    the bits outside the type's range).  We set TREE_OVERFLOWED if,
+   	OVERFLOWED is nonzero,
+ 	or OVERFLOWABLE is >0 and signed overflow occurs
+ 	or OVERFLOWABLE is <0 and any overflow occurs
+    We set TREE_CONSTANT_OVERFLOWED if,
+         CONST_OVERFLOWED is nonzero
+ 	or we set TREE_OVERFLOWED.
+    We return a new tree node for the extended double-int.  The node
+    is shared if no overflow flags are set.  */
+ 
+ tree
+ force_fit_type_double (tree type, unsigned HOST_WIDE_INT low,
+ 		       HOST_WIDE_INT high, int overflowable,
+ 		       bool overflowed, bool overflowed_const)
+ {
+   int sign_extended_type;
+   bool overflow;
+ 
+   /* Size types *are* sign extended.  */
+   sign_extended_type = (!TYPE_UNSIGNED (type)
+ 			|| (TREE_CODE (type) == INTEGER_TYPE
+ 			    && TYPE_IS_SIZETYPE (type)));
+ 
+   overflow = fit_double_type (low, high, &low, &high, type);
+ 
+   /* If we need to set overflow flags, return a new unshared node.  */
+   if (overflowed || overflowed_const || overflow)
+     {
+       if (overflowed
+ 	  || overflowable < 0
+ 	  || (overflowable > 0 && sign_extended_type))
+ 	{
+           tree t = make_node (INTEGER_CST);
+           TREE_INT_CST_LOW (t) = low;
+           TREE_INT_CST_HIGH (t) = high;
+           TREE_TYPE (t) = type;
+ 	  TREE_OVERFLOW (t) = 1;
+ 	  TREE_CONSTANT_OVERFLOW (t) = 1;
+ 
+ 	  return t;
+ 	}
+       else if (overflowed_const)
+ 	{
+           tree t = make_node (INTEGER_CST);
+           TREE_INT_CST_LOW (t) = low;
+           TREE_INT_CST_HIGH (t) = high;
+           TREE_TYPE (t) = type;
+ 	  TREE_CONSTANT_OVERFLOW (t) = 1;
+ 
+ 	  return t;
+ 	}
+     }
+ 
+   /* Else build a shared node.  */
+   return build_int_cst_wide (type, low, high);
+ }
+ #if 0
  /* T is an INT_CST node.  OVERFLOWABLE indicates if we are interested
     in overflow of the value, when >0 we are only interested in signed
     overflow, for <0 we are interested in any overflow.  OVERFLOWED
*************** force_fit_type (tree t, int overflowable
*** 321,326 ****
--- 386,392 ----
  
    return t;
  }
+ #endif
  
  /* Add two doubleword integers with doubleword result.
     Return nonzero if the operation overflows according to UNSIGNED_P.
*************** int_const_binop (enum tree_code code, tr
*** 1601,1610 ****
        return NULL_TREE;
      }
  
-   t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
- 
    if (notrunc)
      {
        /* Propagate overflow flags ourselves.  */
        if (((!uns || is_sizetype) && overflow)
  	  | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
--- 1667,1676 ----
        return NULL_TREE;
      }
  
    if (notrunc)
      {
+       t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
+ 
        /* Propagate overflow flags ourselves.  */
        if (((!uns || is_sizetype) && overflow)
  	  | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
*************** int_const_binop (enum tree_code code, tr
*** 1620,1630 ****
  	}
      }
    else
!     t = force_fit_type (t, 1,
! 			((!uns || is_sizetype) && overflow)
! 			| TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2),
! 			TREE_CONSTANT_OVERFLOW (arg1)
! 			| TREE_CONSTANT_OVERFLOW (arg2));
  
    return t;
  }
--- 1686,1696 ----
  	}
      }
    else
!     t = force_fit_type_double (TREE_TYPE (arg1), low, hi, 1,
! 			       ((!uns || is_sizetype) && overflow)
! 			       | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2),
! 			       TREE_CONSTANT_OVERFLOW (arg1)
! 			       | TREE_CONSTANT_OVERFLOW (arg2));
  
    return t;
  }
*************** fold_convert_const_int_from_int (tree ty
*** 1896,1913 ****
  
    /* Given an integer constant, make new constant with new type,
       appropriately sign-extended or truncated.  */
!   t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1),
! 			  TREE_INT_CST_HIGH (arg1));
! 
!   t = force_fit_type (t,
! 		      /* Don't set the overflow when
! 		      	 converting a pointer  */
! 		      !POINTER_TYPE_P (TREE_TYPE (arg1)),
! 		      (TREE_INT_CST_HIGH (arg1) < 0
! 		       && (TYPE_UNSIGNED (type)
! 			   < TYPE_UNSIGNED (TREE_TYPE (arg1))))
! 		      | TREE_OVERFLOW (arg1),
! 		      TREE_CONSTANT_OVERFLOW (arg1));
  
    return t;
  }
--- 1962,1977 ----
  
    /* Given an integer constant, make new constant with new type,
       appropriately sign-extended or truncated.  */
!   t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1),
! 			     TREE_INT_CST_HIGH (arg1),
! 		             /* Don't set the overflow when
! 		      		converting a pointer  */
! 			     !POINTER_TYPE_P (TREE_TYPE (arg1)),
! 			     (TREE_INT_CST_HIGH (arg1) < 0
! 		 	      && (TYPE_UNSIGNED (type)
! 				  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
! 			     | TREE_OVERFLOW (arg1),
! 			     TREE_CONSTANT_OVERFLOW (arg1));
  
    return t;
  }
*************** fold_convert_const_int_from_real (enum t
*** 1985,1994 ****
    if (! overflow)
      REAL_VALUE_TO_INT (&low, &high, r);
  
!   t = build_int_cst_wide (type, low, high);
! 
!   t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
! 		      TREE_CONSTANT_OVERFLOW (arg1));
    return t;
  }
  
--- 2049,2057 ----
    if (! overflow)
      REAL_VALUE_TO_INT (&low, &high, r);
  
!   t = force_fit_type_double (type, low, high, -1,
! 			     overflow | TREE_OVERFLOW (arg1),
! 			     TREE_CONSTANT_OVERFLOW (arg1));
    return t;
  }
  
*************** fold_div_compare (enum tree_code code, t
*** 6172,6179 ****
  				   TREE_INT_CST_LOW (arg1),
  				   TREE_INT_CST_HIGH (arg1),
  				   &lpart, &hpart, unsigned_p);
!   prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
!   prod = force_fit_type (prod, -1, overflow, false);
    neg_overflow = false;
  
    if (unsigned_p)
--- 6235,6242 ----
  				   TREE_INT_CST_LOW (arg1),
  				   TREE_INT_CST_HIGH (arg1),
  				   &lpart, &hpart, unsigned_p);
!   prod = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart,
! 				-1, overflow, false);
    neg_overflow = false;
  
    if (unsigned_p)
*************** fold_div_compare (enum tree_code code, t
*** 6188,6196 ****
  				       TREE_INT_CST_LOW (tmp),
  				       TREE_INT_CST_HIGH (tmp),
  				       &lpart, &hpart, unsigned_p);
!       hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
!       hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod),
! 			   TREE_CONSTANT_OVERFLOW (prod));
      }
    else if (tree_int_cst_sgn (arg01) >= 0)
      {
--- 6251,6259 ----
  				       TREE_INT_CST_LOW (tmp),
  				       TREE_INT_CST_HIGH (tmp),
  				       &lpart, &hpart, unsigned_p);
!       hi = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart,
! 				  -1, overflow | TREE_OVERFLOW (prod),
! 				  TREE_CONSTANT_OVERFLOW (prod));
      }
    else if (tree_int_cst_sgn (arg01) >= 0)
      {
*************** static tree
*** 6589,6595 ****
  fold_sign_changed_comparison (enum tree_code code, tree type,
  			      tree arg0, tree arg1)
  {
!   tree arg0_inner, tmp;
    tree inner_type, outer_type;
  
    if (TREE_CODE (arg0) != NOP_EXPR
--- 6652,6658 ----
  fold_sign_changed_comparison (enum tree_code code, tree type,
  			      tree arg0, tree arg1)
  {
!   tree arg0_inner;
    tree inner_type, outer_type;
  
    if (TREE_CODE (arg0) != NOP_EXPR
*************** fold_sign_changed_comparison (enum tree_
*** 6624,6637 ****
      return NULL_TREE;
  
    if (TREE_CODE (arg1) == INTEGER_CST)
!     {
!       tmp = build_int_cst_wide (inner_type,
! 				TREE_INT_CST_LOW (arg1),
! 				TREE_INT_CST_HIGH (arg1));
!       arg1 = force_fit_type (tmp, 0,
! 			     TREE_OVERFLOW (arg1),
! 			     TREE_CONSTANT_OVERFLOW (arg1));
!     }
    else
      arg1 = fold_convert (inner_type, arg1);
  
--- 6687,6696 ----
      return NULL_TREE;
  
    if (TREE_CODE (arg1) == INTEGER_CST)
!     arg1 = force_fit_type_double (inner_type, TREE_INT_CST_LOW (arg1),
! 				  TREE_INT_CST_HIGH (arg1), 0,
! 				  TREE_OVERFLOW (arg1),
! 				  TREE_CONSTANT_OVERFLOW (arg1));
    else
      arg1 = fold_convert (inner_type, arg1);
  
*************** fold_unary (enum tree_code code, tree ty
*** 7563,7572 ****
  	    }
  	  if (change)
  	    {
! 	      tem = build_int_cst_wide (type, TREE_INT_CST_LOW (and1),
! 					TREE_INT_CST_HIGH (and1));
! 	      tem = force_fit_type (tem, 0, TREE_OVERFLOW (and1),
! 				    TREE_CONSTANT_OVERFLOW (and1));
  	      return fold_build2 (BIT_AND_EXPR, type,
  				  fold_convert (type, and0), tem);
  	    }
--- 7622,7631 ----
  	    }
  	  if (change)
  	    {
! 	      tem = force_fit_type_double (type, TREE_INT_CST_LOW (and1),
! 					   TREE_INT_CST_HIGH (and1), 0,
! 					   TREE_OVERFLOW (and1),
! 					   TREE_CONSTANT_OVERFLOW (and1));
  	      return fold_build2 (BIT_AND_EXPR, type,
  				  fold_convert (type, and0), tem);
  	    }
*************** fold_negate_const (tree arg0, tree type)
*** 13056,13066 ****
  	int overflow = neg_double (TREE_INT_CST_LOW (arg0),
  				   TREE_INT_CST_HIGH (arg0),
  				   &low, &high);
! 	t = build_int_cst_wide (type, low, high);
! 	t = force_fit_type (t, 1,
! 			    (overflow | TREE_OVERFLOW (arg0))
! 			    && !TYPE_UNSIGNED (type),
! 			    TREE_CONSTANT_OVERFLOW (arg0));
  	break;
        }
  
--- 13115,13124 ----
  	int overflow = neg_double (TREE_INT_CST_LOW (arg0),
  				   TREE_INT_CST_HIGH (arg0),
  				   &low, &high);
! 	t = force_fit_type_double (type, low, high, 1,
! 				   (overflow | TREE_OVERFLOW (arg0))
! 				   && !TYPE_UNSIGNED (type),
! 				   TREE_CONSTANT_OVERFLOW (arg0));
  	break;
        }
  
*************** fold_abs_const (tree arg0, tree type)
*** 13104,13112 ****
  	  int overflow = neg_double (TREE_INT_CST_LOW (arg0),
  				     TREE_INT_CST_HIGH (arg0),
  				     &low, &high);
! 	  t = build_int_cst_wide (type, low, high);
! 	  t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg0),
! 			      TREE_CONSTANT_OVERFLOW (arg0));
  	}
        break;
  
--- 13162,13170 ----
  	  int overflow = neg_double (TREE_INT_CST_LOW (arg0),
  				     TREE_INT_CST_HIGH (arg0),
  				     &low, &high);
! 	  t = force_fit_type_double (type, low, high, -1,
! 				     overflow | TREE_OVERFLOW (arg0),
! 				     TREE_CONSTANT_OVERFLOW (arg0));
  	}
        break;
  
*************** fold_not_const (tree arg0, tree type)
*** 13134,13144 ****
  
    gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
  
!   t = build_int_cst_wide (type,
! 			  ~ TREE_INT_CST_LOW (arg0),
! 			  ~ TREE_INT_CST_HIGH (arg0));
!   t = force_fit_type (t, 0, TREE_OVERFLOW (arg0),
! 		      TREE_CONSTANT_OVERFLOW (arg0));
  
    return t;
  }
--- 13192,13201 ----
  
    gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
  
!   t = force_fit_type_double (type, ~TREE_INT_CST_LOW (arg0),
! 			     ~TREE_INT_CST_HIGH (arg0), 0,
! 			     TREE_OVERFLOW (arg0),
! 			     TREE_CONSTANT_OVERFLOW (arg0));
  
    return t;
  }
Index: gcc/tree.h
===================================================================
*** gcc.orig/tree.h	2007-01-08 20:49:25.000000000 +0100
--- gcc/tree.h	2007-01-08 20:50:03.000000000 +0100
*************** extern tree fold_ignored_result (tree);
*** 4321,4327 ****
  extern tree fold_abs_const (tree, tree);
  extern tree fold_indirect_ref_1 (tree, tree);
  
! extern tree force_fit_type (tree, int, bool, bool);
  
  extern int fit_double_type (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
  			    unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, tree);
--- 4321,4328 ----
  extern tree fold_abs_const (tree, tree);
  extern tree fold_indirect_ref_1 (tree, tree);
  
! extern tree force_fit_type_double (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT,
! 				   int, bool, bool);
  
  extern int fit_double_type (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
  			    unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, tree);

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