aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2004-05-31 17:01:17 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2004-05-31 17:01:17 +0000
commit1f7a8dccd4056be197e8f79fe7bbf2b8bd89c53b (patch)
treeeac927b74d933af84e28ee45cd568925d8de1411
parent1027314a211e7b0e2b05b6bd8f179c12f784517e (diff)
downloadgcc-1f7a8dccd4056be197e8f79fe7bbf2b8bd89c53b.zip
gcc-1f7a8dccd4056be197e8f79fe7bbf2b8bd89c53b.tar.gz
gcc-1f7a8dccd4056be197e8f79fe7bbf2b8bd89c53b.tar.bz2
re PR c++/15069 (a bit test on a variable of enum type is miscompiled)
PR middle-end/15069 * fold-const.c (fold_single_bit_test): Only perform "(X & C) != 0" into "X < 0" (where C is the signbit) if X's type is a full mode. * g++.dg/opt/fold3.C: New test case. From-SVN: r82490
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/fold-const.c10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/opt/fold3.C21
4 files changed, 37 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c639b56..cea33d1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2004-05-31 Roger Sayle <roger@eyesopen.com>
+
+ PR middle-end/15069
+ * fold-const.c (fold_single_bit_test): Only perform "(X & C) != 0"
+ into "X < 0" (where C is the signbit) if X's type is a full mode.
+
2004-05-31 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* pa.md: Disable the peephole2 patterns that generate indexed
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index d2e333e..b0d1db2 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -5413,7 +5413,11 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
/* If we have (A & C) != 0 where C is the sign bit of A, convert
this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
- if (arg00 != NULL_TREE)
+ if (arg00 != NULL_TREE
+ /* This is only a win if casting to a signed type is cheap,
+ i.e. when arg00's type is not a partial mode. */
+ && TYPE_PRECISION (TREE_TYPE (arg00))
+ == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg00))))
{
tree stype = lang_hooks.types.signed_type (TREE_TYPE (arg00));
return fold (build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
@@ -5421,10 +5425,6 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
fold_convert (stype, integer_zero_node)));
}
- /* At this point, we know that arg0 is not testing the sign bit. */
- if (TYPE_PRECISION (type) - 1 == bitnum)
- abort ();
-
/* Otherwise we have (A & C) != 0 where C is a single bit,
convert that into ((A >> C2) & 1). Where C2 = log2(C).
Similarly for (A & C) == 0. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6d5e0a5..47ed126 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2004-05-31 Roger Sayle <roger@eyesopen.com>
+
+ PR middle-end/15069
+ * g++.dg/opt/fold3.C: New test case.
+
2004-05-30 Graham Stott <graham.stott@btinternet.com>
* lib/target-supports.exp (check_iconv_available): Fix fallout
diff --git a/gcc/testsuite/g++.dg/opt/fold3.C b/gcc/testsuite/g++.dg/opt/fold3.C
new file mode 100644
index 0000000..87a36b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/fold3.C
@@ -0,0 +1,21 @@
+// PR middle-end/15069
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort (void);
+
+typedef enum {
+ FOUR = 4,
+ FIVE = 5
+} direction_t;
+
+int main ()
+{
+ direction_t four = FOUR;
+ int flags = (four & 4L) ? (32L | 128L) : 0;
+ flags &= 32L;
+
+ if (flags == 0)
+ abort ();
+}
+