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] 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

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