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]

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

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