OSDN Git Service

Fix (<cond> ? FOO++ : BAR++) == 2 from misoptimizing FOO++ into ++FOO without bumping...
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jul 2000 14:58:53 +0000 (14:58 +0000)
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jul 2000 14:58:53 +0000 (14:58 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@35046 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20000715-1.c [new file with mode: 0644]

index 7199aea..45b1d54 100644 (file)
@@ -1,3 +1,9 @@
+2000-07-15  Michael Meissner  <meissner@redhat.com>
+
+       * fold-const.c (fold): When optimizing FOO++ == CONST into ++FOO
+       == CONST + INCREMENT, don't overwrite the tree node for FOO++,
+       create a new node instead.
+
 2000-07-15  Neil Booth  <NeilB@earthling.net>
 
        * README.Portability: Correct example about calling a function
index 26ac5d2..f259115 100644 (file)
@@ -6136,7 +6136,15 @@ fold (expr)
                tree newconst
                  = fold (build (PLUS_EXPR, TREE_TYPE (varop),
                                 constop, TREE_OPERAND (varop, 1)));
-               TREE_SET_CODE (varop, PREINCREMENT_EXPR);
+
+               /* Do not overwrite the current varop to be a preincrement,
+                  create a new node so that we won't confuse our caller who
+                  might create trees and throw them away, reusing the
+                  arguments that they passed to build.  This shows up in
+                  the THEN or ELSE parts of ?: being postincrements.  */
+               varop = build (PREINCREMENT_EXPR, TREE_TYPE (varop),
+                              TREE_OPERAND (varop, 0),
+                              TREE_OPERAND (varop, 1));
 
                /* If VAROP is a reference to a bitfield, we must mask
                   the constant by the width of the field.  */
@@ -6180,9 +6188,9 @@ fold (expr)
                  }
                                                         
 
-               t = build (code, type, TREE_OPERAND (t, 0),
-                          TREE_OPERAND (t, 1));
-               TREE_OPERAND (t, constopnum) = newconst;
+               t = build (code, type,
+                          (constopnum == 0) ? newconst : varop,
+                          (constopnum == 1) ? newconst : varop);
                return t;
              }
          }
@@ -6195,7 +6203,15 @@ fold (expr)
                tree newconst
                  = fold (build (MINUS_EXPR, TREE_TYPE (varop),
                                 constop, TREE_OPERAND (varop, 1)));
-               TREE_SET_CODE (varop, PREDECREMENT_EXPR);
+
+               /* Do not overwrite the current varop to be a predecrement,
+                  create a new node so that we won't confuse our caller who
+                  might create trees and throw them away, reusing the
+                  arguments that they passed to build.  This shows up in
+                  the THEN or ELSE parts of ?: being postdecrements.  */
+               varop = build (PREDECREMENT_EXPR, TREE_TYPE (varop),
+                              TREE_OPERAND (varop, 0),
+                              TREE_OPERAND (varop, 1));
 
                if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
                    && DECL_BIT_FIELD(TREE_OPERAND
@@ -6234,9 +6250,9 @@ fold (expr)
                  }
                                                         
 
-               t = build (code, type, TREE_OPERAND (t, 0),
-                          TREE_OPERAND (t, 1));
-               TREE_OPERAND (t, constopnum) = newconst;
+               t = build (code, type,
+                          (constopnum == 0) ? newconst : varop,
+                          (constopnum == 1) ? newconst : varop);
                return t;
              }
          }
index 1f94bdb..e778d70 100644 (file)
@@ -1,3 +1,7 @@
+2000-07-15  Michael Meissner  <meissner@redhat.com>
+
+       * gcc.c-torture/execute/20000715-1.c: New test.
+
 2000-07-13  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.c-torture/execute/20000707-1.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20000715-1.c b/gcc/testsuite/gcc.c-torture/execute/20000715-1.c
new file mode 100644 (file)
index 0000000..43af114
--- /dev/null
@@ -0,0 +1,118 @@
+void abort(void);
+void exit(int);
+
+void
+test1(void)
+{
+  int x = 3, y = 2;
+
+  if ((x < y ? x++ : y++) != 2)
+    abort ();
+
+  if (x != 3)
+    abort ();
+
+  if (y != 3)
+    abort ();
+}
+
+void
+test2(void)
+{
+  int x = 3, y = 2, z;
+
+  z = (x < y) ? x++ : y++;
+  if (z != 2)
+    abort ();
+
+  if (x != 3)
+    abort ();
+
+  if (y != 3)
+    abort ();
+}
+
+void
+test3(void)
+{
+  int x = 3, y = 2;
+  int xx = 3, yy = 2;
+
+  if ((xx < yy ? x++ : y++) != 2)
+    abort ();
+
+  if (x != 3)
+    abort ();
+
+  if (y != 3)
+    abort ();
+}
+
+int x, y;
+
+static void
+init_xy(void)
+{
+  x = 3;
+  y = 2;
+}
+
+void
+test4(void)
+{
+  init_xy();
+  if ((x < y ? x++ : y++) != 2)
+    abort ();
+
+  if (x != 3)
+    abort ();
+
+  if (y != 3)
+    abort ();
+}
+
+void
+test5(void)
+{
+  int z;
+
+  init_xy();
+  z = (x < y) ? x++ : y++;
+  if (z != 2)
+    abort ();
+
+  if (x != 3)
+    abort ();
+
+  if (y != 3)
+    abort ();
+}
+
+void
+test6(void)
+{
+  int xx = 3, yy = 2;
+  int z;
+
+  init_xy();
+  z = (xx < y) ? x++ : y++;
+  if (z != 2)
+    abort ();
+
+  if (x != 3)
+    abort ();
+
+  if (y != 3)
+    abort ();
+}
+
+int
+main(){
+  test1 ();
+  test2 ();
+  test3 ();
+  test4 ();
+  test5 ();
+  test6 ();
+  exit (0);
+}