This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH COMMITTED: Fix for PR 42099
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 29 Dec 2009 20:31:25 -0800
- Subject: PATCH COMMITTED: Fix for PR 42099
PR 42099 is about a bug in the handling of division by a constant in a
mode larger than HOST_WIDE_INT. When the constant fits in
HOST_WIDE_INT, and appears to look like the minimum integer value, gcc
does an invalid shift. On x86, this leads gcc to conclude that the
value is in fact the minimum integer value. The fix is simple.
The comment says "This case is not handled correctly below" but that
comment is irrelevant when working in a mode which is larger than
HOST_WIDE_INT. The rest of the code handles the case correctly.
Bootstrapped on i686-pc-linux-gnu. Committed to mainline.
Ian
gcc/:
2009-12-29 Ian Lance Taylor <iant@google.com>
PR middle-end/42099
* expmed.c (expand_divmod): Don't shift HOST_WIDE_INT value more
than HOST_BITS_PER_WIDE_INT.
gcc/testsuite/:
2009-12-29 Ian Lance Taylor <iant@google.com>
PR middle-end/42099
* gcc.c-torture/execute/20091229-1.c: New test.
Index: expmed.c
===================================================================
--- expmed.c (revision 155510)
+++ expmed.c (working copy)
@@ -4194,7 +4194,8 @@ expand_divmod (int rem_flag, enum tree_c
else if (d == -1)
quotient = expand_unop (compute_mode, neg_optab, op0,
tquotient, 0);
- else if (abs_d == (unsigned HOST_WIDE_INT) 1 << (size - 1))
+ else if (HOST_BITS_PER_WIDE_INT >= size
+ && abs_d == (unsigned HOST_WIDE_INT) 1 << (size - 1))
{
/* This case is not handled correctly below. */
quotient = emit_store_flag (tquotient, EQ, op0, op1,
Index: testsuite/gcc.c-torture/execute/20091229-1.c
===================================================================
--- testsuite/gcc.c-torture/execute/20091229-1.c (revision 0)
+++ testsuite/gcc.c-torture/execute/20091229-1.c (revision 0)
@@ -0,0 +1,2 @@
+long long foo(long long v) { return v / -0x080000000LL; }
+void main() { if (foo(0x080000000LL) != -1) abort(); exit (0); }