re PR rtl-optimization/28636 (Miscompiled loop)
authorEric Botcazou <ebotcazou@libertysurf.fr>
Sun, 10 Sep 2006 21:27:36 +0000 (23:27 +0200)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sun, 10 Sep 2006 21:27:36 +0000 (21:27 +0000)
PR rtl-optimization/28636
* combine.c (force_to_mode): Test for side-effects before
substituting by zero.
(simplify_shift_const): Likewise for zero or other constants.

From-SVN: r116827

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20060910-1.c [new file with mode: 0644]

index c4066f353b2ccdd7454820d6b8af60cc751671b6..bbf36261fb9463a14354946122a839509710375f 100644 (file)
@@ -1,3 +1,10 @@
+2006-09-10  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR rtl-optimization/28636
+       * combine.c (force_to_mode): Test for side-effects before
+       substituting by zero.
+       (simplify_shift_const): Likewise for zero or other constants.
+
 2006-09-10  Steven Bosscher  <steven@gcc.gnu.org>
 
        PR middle-end/26983
index 727e625ae2ca8d5a68658845d804fcbe47ed9da1..0f4ea02970f15c62893bfc49e6b0f5a04238f669 100644 (file)
@@ -6860,7 +6860,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
   nonzero = nonzero_bits (x, mode);
 
   /* If none of the bits in X are needed, return a zero.  */
-  if (! just_select && (nonzero & mask) == 0)
+  if (!just_select && (nonzero & mask) == 0 && !side_effects_p (x))
     x = const0_rtx;
 
   /* If X is a CONST_INT, return a new one.  Do this here since the
@@ -8637,14 +8637,14 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
              == 0))
        code = LSHIFTRT;
 
-      if (code == LSHIFTRT
-         && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
-         && !(nonzero_bits (varop, shift_mode) >> count))
-       varop = const0_rtx;
-      if (code == ASHIFT
-         && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
-         && !((nonzero_bits (varop, shift_mode) << count)
-              & GET_MODE_MASK (shift_mode)))
+      if (((code == LSHIFTRT
+           && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
+           && !(nonzero_bits (varop, shift_mode) >> count))
+          || (code == ASHIFT
+              && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
+              && !((nonzero_bits (varop, shift_mode) << count)
+                   & GET_MODE_MASK (shift_mode))))
+         && !side_effects_p (varop))
        varop = const0_rtx;
 
       switch (GET_CODE (varop))
@@ -9229,9 +9229,12 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
       if (outer_op == AND)
        x = simplify_and_const_int (NULL_RTX, result_mode, x, outer_const);
       else if (outer_op == SET)
-       /* This means that we have determined that the result is
-          equivalent to a constant.  This should be rare.  */
-       x = GEN_INT (outer_const);
+       {
+         /* This means that we have determined that the result is
+            equivalent to a constant.  This should be rare.  */
+         if (!side_effects_p (x))
+           x = GEN_INT (outer_const);
+       }
       else if (GET_RTX_CLASS (outer_op) == RTX_UNARY)
        x = simplify_gen_unary (outer_op, result_mode, x, result_mode);
       else
index 55eee6b150554cea8f42db828409a3aff0ce7cd2..45bd6ed94b21635e9c519194aa2ba92746068300 100644 (file)
@@ -1,3 +1,7 @@
+2006-09-10  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * gcc.c-torture/execute/20060910-1.c: New test.
+
 2006-09-10  Steven Bosscher  <steven@gcc.gnu.org>
 
        PR middle-end/26983
diff --git a/gcc/testsuite/gcc.c-torture/execute/20060910-1.c b/gcc/testsuite/gcc.c-torture/execute/20060910-1.c
new file mode 100644 (file)
index 0000000..78bf301
--- /dev/null
@@ -0,0 +1,37 @@
+/* PR rtl-optimization/28636 */
+/* Origin: Andreas Schwab <schwab@suse.de> */
+
+extern void abort(void);
+
+struct input_ty
+{
+  unsigned char *buffer_position;
+  unsigned char *buffer_end;
+};
+
+int input_getc_complicated (struct input_ty *x) { return 0; }
+
+int check_header (struct input_ty *deeper)
+{
+  unsigned len;
+  for (len = 0; len < 6; len++)
+    if (((deeper)->buffer_position < (deeper)->buffer_end
+         ? *((deeper)->buffer_position)++
+         : input_getc_complicated((deeper))) < 0)
+      return 0;
+  return 1;
+}
+
+struct input_ty s;
+unsigned char b[6];
+
+int main (void)
+{
+  s.buffer_position = b;
+  s.buffer_end = b + sizeof b;
+  if (!check_header(&s))
+    abort();
+  if (s.buffer_position != s.buffer_end)
+    abort();
+  return 0;
+}