This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug optimization/14669] [3.4/3.5 Regression] Wrong code with -O for enum values expression E4 <= t && t <= E6
- From: "kazu at cs dot umass dot edu" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 22 Mar 2004 00:52:14 -0000
- Subject: [Bug optimization/14669] [3.4/3.5 Regression] Wrong code with -O for enum values expression E4 <= t && t <= E6
- References: <20040321141018.14669.wanderer@rsu.ru>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Additional Comments From kazu at cs dot umass dot edu 2004-03-22 00:52 -------
This bug now seems to be a latent one.
Here is an except from a part of fold() that folds comparisons.
/* If we are widening one operand of an integer comparison,
see if the other operand is similarly being widened. Perhaps we
can do the comparison in the narrower type. */
else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
&& TREE_CODE (arg0) == NOP_EXPR
&& (tem = get_unwidened (arg0, NULL_TREE)) != arg0
&& (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
&& (TREE_TYPE (t1) == TREE_TYPE (tem)
|| (TREE_CODE (t1) == INTEGER_CST
&& int_fits_type_p (t1, TREE_TYPE (tem)))))
return fold (build (code, type, tem,
fold_convert (TREE_TYPE (tem), t1)));
Note that the first call to get_unwidened does not preserve signedness.
So if code == LE_EXPR, for example, the meaning of the comparison changes.
I've worked around the problem with the following patch, but this approach
seems lossy, though. That is, if get_unwidened changes the signdness,
we can restore the signedness back.
Index: fold-const.c
===================================================================
RCS file: /home/kazu/nobackup/gcc-cvs/gcc/gcc/fold-const.c,v
retrieving revision 1.328
diff -u -r1.328 fold-const.c
--- fold-const.c 7 Feb 2004 18:57:29 -0000 1.328
+++ fold-const.c 22 Mar 2004 00:44:15 -0000
@@ -7599,6 +7599,9 @@
else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
&& TREE_CODE (arg0) == NOP_EXPR
&& (tem = get_unwidened (arg0, NULL_TREE)) != arg0
+ && (code == EQ_EXPR || code == NE_EXPR
+ || (TREE_UNSIGNED (TREE_TYPE (arg0))
+ == TREE_UNSIGNED (TREE_TYPE (tem))))
&& (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
&& (TREE_TYPE (t1) == TREE_TYPE (tem)
|| (TREE_CODE (t1) == INTEGER_CST
To address the above issue, I wrote another patch like so
Index: fold-const.c
===================================================================
RCS file: /home/kazu/nobackup/gcc-cvs/gcc/gcc/fold-const.c,v
retrieving revision 1.328
diff -u -r1.328 fold-const.c
--- fold-const.c 7 Feb 2004 18:57:29 -0000 1.328
+++ fold-const.c 22 Mar 2004 00:40:23 -0000
@@ -7599,6 +7599,9 @@
else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
&& TREE_CODE (arg0) == NOP_EXPR
&& (tem = get_unwidened (arg0, NULL_TREE)) != arg0
+ && (tem = (TREE_UNSIGNED (TREE_TYPE (arg0))
+ ? fold_convert (lang_hooks.types.unsigned_type (TREE_TYPE (tem)), tem)
+ : fold_convert (lang_hooks.types.signed_type (TREE_TYPE (tem)), tem)))
&& (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
&& (TREE_TYPE (t1) == TREE_TYPE (tem)
|| (TREE_CODE (t1) == INTEGER_CST
But GCC with this patch segfaults. Seems like it goes into an infinite
recursion or something.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14669