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
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: Roger Sayle <roger at eyesopen dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Mark Mitchell <mark at codesourcery dot com>
- Date: Sun, 2 Apr 2006 08:41:17 +0200
- Subject: Re: [PATCH] Fix PR middle-end/26635
- References: <Pine.LNX.4.44.0603312034220.12877-100000@www.eyesopen.com>
> If it's OK with the other maintainers I'd prefer this to just be a simple
> global variable, like flag_evaluation_order in flags.h rather than new
> command line option. It should behave identically, can get for C/C++ in
> the same way, and provides the same less intrusive workaround for the
> release branches.
Revised patch attached.
2006-04-02 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): Don't narrow the type of a
PLUS_EXPR or MINUS_EXPR if !flag_modv and the unwidened type
is signed.
* toplev.c (flag_modv): New global variable.
--
Eric Botcazou
Index: flags.h
===================================================================
--- flags.h (revision 112529)
+++ flags.h (working copy)
@@ -203,6 +203,10 @@ extern int frame_pointer_needed;
/* Nonzero if subexpressions must be evaluated from left-to-right. */
extern int flag_evaluation_order;
+/* Nonzero if conversion-to-signed overflow is reduced
+ using modulo arithmetics. */
+extern int flag_modv;
+
/* Value of the -G xx switch, and whether it was passed or not. */
extern unsigned HOST_WIDE_INT g_switch_value;
extern bool g_switch_set;
Index: c-common.c
===================================================================
--- c-common.c (revision 112529)
+++ c-common.c (working copy)
@@ -3350,6 +3350,9 @@ c_common_nodes_and_builtins (void)
/* Since builtin_types isn't gc'ed, don't export these nodes. */
memset (builtin_types, 0, sizeof (builtin_types));
+
+ /* Result of conversion-to-signed overflow is implementation-defined. */
+ flag_modv = 1;
}
/* Look up the function in built_in_decls that corresponds to DECL
Index: convert.c
===================================================================
--- convert.c (revision 112529)
+++ convert.c (working copy)
@@ -596,6 +596,17 @@ 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 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 (!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,6 +636,10 @@ 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.
+ Exception: if 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 (TREE_TYPE (expr))
@@ -635,12 +650,7 @@ 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
+ || (flag_modv && !flag_wrapv
&& (ex_form == PLUS_EXPR
|| ex_form == MINUS_EXPR)
&& (!TYPE_UNSIGNED (TREE_TYPE (arg0))
Index: toplev.c
===================================================================
--- toplev.c (revision 112529)
+++ toplev.c (working copy)
@@ -372,6 +375,10 @@ lang_independent_options;
/* Nonzero if subexpressions must be evaluated from left-to-right. */
int flag_evaluation_order = 0;
+/* Nonzero if conversion-to-signed overflow is reduced
+ using modulo arithmetics. */
+int flag_modv = 0;
+
/* The user symbol prefix after having resolved same. */
const char *user_label_prefix;