This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR middle-end/26635
> Revised patch attached.
It turns out that totally disabling the optimization proves detrimental to the
Ada compiler, especially for size expressions of variable-sized types that
are not as simplified as they used to be.
So I'm proposing to re-enable it for TYPE_IS_SIZETYPE types. The revised
patch has been tested on x86_64-suse-linux.
2006-04-04 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/26635
* flags.h (flag_modv): Declare.
* c-common.c (c_common_nodes_and_builtins): Set flag_modv to 1.
* convert.c (convert_to_integer): Do not narrow the type of PLUS_EXPR
or MINUS_EXPR if it is signed but not a sizetype and !flag_modv and
the unwidened type is signed.
* toplev.c (flag_modv): New global variable.
--
Eric Botcazou
Index: convert.c
===================================================================
--- convert.c (revision 112529)
+++ convert.c (working copy)
@@ -596,6 +596,19 @@ convert_to_integer (tree type, tree expr
tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type);
tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);
+ /* If the type of the expression is signed but not a sizetype
+ and we have neither flag_modv nor flag_wrapv, and either
+ operand is of a signed type, we cannot narrow PLUS_EXPR
+ or MINUS_EXPR because we would transform an overflow-proof
+ expression in the wider type into an expression in the
+ narrower type whose overflow behavior is undefined. */
+ if (!TYPE_UNSIGNED (intype) && !TYPE_IS_SIZETYPE (intype)
+ && !flag_modv && !flag_wrapv
+ && (ex_form == PLUS_EXPR || ex_form == MINUS_EXPR)
+ && (!TYPE_UNSIGNED (TREE_TYPE (arg0))
+ || !TYPE_UNSIGNED (TREE_TYPE (arg1))))
+ break;
+
if (outprec >= BITS_PER_WORD
|| TRULY_NOOP_TRUNCATION (outprec, inprec)
|| inprec > TYPE_PRECISION (TREE_TYPE (arg0))
@@ -625,9 +638,14 @@ convert_to_integer (tree type, tree expr
Exception: the LSHIFT_EXPR case above requires that
we perform this operation unsigned lest we produce
signed-overflow undefinedness.
- And we may need to do it as unsigned
- if we truncate to the original size. */
- if (TYPE_UNSIGNED (TREE_TYPE (expr))
+ Exception: if the type of the expression is signed but
+ not a sizetype and we have flag_modv but !flag_wrapv,
+ and either operand is of a signed type, we have to do
+ PLUS_EXPR or MINUS_EXPR in an unsigned type lest we
+ produce signed-overflow undefinedness.
+ And we may need to do it as unsigned if we truncate
+ to the original size. */
+ if (TYPE_UNSIGNED (intype)
|| (TYPE_UNSIGNED (TREE_TYPE (arg0))
&& (TYPE_UNSIGNED (TREE_TYPE (arg1))
|| ex_form == LSHIFT_EXPR
@@ -635,12 +653,8 @@ convert_to_integer (tree type, tree expr
|| ex_form == LROTATE_EXPR
|| ex_form == RROTATE_EXPR))
|| ex_form == LSHIFT_EXPR
- /* If we have !flag_wrapv, and either ARG0 or
- ARG1 is of a signed type, we have to do
- PLUS_EXPR or MINUS_EXPR in an unsigned
- type. Otherwise, we would introduce
- signed-overflow undefinedness. */
- || (!flag_wrapv
+ || (!TYPE_IS_SIZETYPE (intype)
+ && flag_modv && !flag_wrapv
&& (ex_form == PLUS_EXPR
|| ex_form == MINUS_EXPR)
&& (!TYPE_UNSIGNED (TREE_TYPE (arg0))