* [PATCH] Introduce force_fit_type_double, remove force_fit_type
@ 2007-01-08 20:38 Richard Guenther
2007-01-08 23:08 ` Richard Guenther
0 siblings, 1 reply; 2+ messages in thread
From: Richard Guenther @ 2007-01-08 20:38 UTC (permalink / raw)
To: Gcc Patch List
[-- Attachment #1: Type: text/plain, Size: 1669 bytes --]
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.
[-- Attachment #2: p4.diff --]
[-- Type: text/x-patch, Size: 15164 bytes --]
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
\f
/* 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);
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] Introduce force_fit_type_double, remove force_fit_type
2007-01-08 20:38 [PATCH] Introduce force_fit_type_double, remove force_fit_type Richard Guenther
@ 2007-01-08 23:08 ` Richard Guenther
0 siblings, 0 replies; 2+ messages in thread
From: Richard Guenther @ 2007-01-08 23:08 UTC (permalink / raw)
To: Gcc Patch List
On 1/8/07, Richard Guenther <richard.guenther@gmail.com> wrote:
> 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.
Finished and applied to mainline (with the #if 0 / #endif block removed
- thanks Ian ;)
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.
>
>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-01-08 23:08 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-08 20:38 [PATCH] Introduce force_fit_type_double, remove force_fit_type Richard Guenther
2007-01-08 23:08 ` Richard Guenther
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).