This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR middle-end/26635
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 31 Mar 2006 18:52:29 +0200
- Subject: [PATCH] Fix PR middle-end/26635
Hi,
It's a regression from 4.0 present on mainline and 4.1 branch, see the
analysis at http://gcc.gnu.org/ml/gcc/2006-03/msg00719.html.
So, as per Joseph's suggestion, I'm proposing to introduce a new switch,
namely -fmodv, that would specify whether conversion-to-signed overflow is
reduced using modulo arithmetics in the middle-end, and set it to 1 for the C
family of languages.
Tested on x86_64-suse-linux. OK for mainline and 4.1 branch?
2006-03-31 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/26635
* common.opt (fmodv): New switch.
* doc/invoke.texi (Code Generation Options): Document it.
* 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.
--
Eric Botcazou
Index: common.opt
===================================================================
--- common.opt (revision 112529)
+++ common.opt (working copy)
@@ -596,6 +596,10 @@ fmodulo-sched
Common Report Var(flag_modulo_sched)
Perform SMS based modulo scheduling before the first scheduling pass
+fmodv
+Common Report Var(flag_modv)
+Assume conversion-to-signed overflow is reduced using modulo arithmetics
+
fmove-loop-invariants
Common Report Var(flag_move_loop_invariants) Init(1)
Move loop invariant computations out of loops
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi (revision 112529)
+++ doc/invoke.texi (working copy)
@@ -771,7 +771,7 @@ See S/390 and zSeries Options.
-fargument-alias -fargument-noalias @gol
-fargument-noalias-global -fargument-noalias-anything
-fleading-underscore -ftls-model=@var{model} @gol
--ftrapv -fwrapv -fbounds-check @gol
+-fmodv -ftrapv -fwrapv -fbounds-check @gol
-fvisibility -fopenmp}
@end table
@@ -13034,6 +13035,13 @@ indices used to access arrays are within
currently only supported by the Java and Fortran 77 front-ends, where
this option defaults to true and false respectively.
+@item -fmodv
+@opindex fmodv
+This option instructs the compiler to assume that conversion-to-signed
+overflow is reduced using modulo arithmetics. This flag enables some
+optimizations and disables others. This option is enabled by default
+for the C family of languages.
+
@item -ftrapv
@opindex ftrapv
This option generates traps for signed overflow on addition, subtraction,
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: 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