diff options
author | Michael Meissner <meissner@redhat.com> | 2000-07-15 14:58:53 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 2000-07-15 14:58:53 +0000 |
commit | 4d06bcc527aca789f9282167528aa02f77cdd6ca (patch) | |
tree | cc186924767d7116187ea8c5addebe72555b7ae8 | |
parent | bbed132f325e85bb0ee7cdfeac9c4504278e99d6 (diff) | |
download | gcc-4d06bcc527aca789f9282167528aa02f77cdd6ca.zip gcc-4d06bcc527aca789f9282167528aa02f77cdd6ca.tar.gz gcc-4d06bcc527aca789f9282167528aa02f77cdd6ca.tar.bz2 |
Fix (<cond> ? FOO++ : BAR++) == 2 from misoptimizing FOO++ into ++FOO without bumping up the comparison value
From-SVN: r35046
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/fold-const.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20000715-1.c | 118 |
4 files changed, 152 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7199aea..45b1d54 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 26ac5d2..f259115 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1f94bdb..e778d70 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..43af114 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20000715-1.c @@ -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); +} |