This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
proposed cse patch for incorrect divide by constant simplication
- From: Jim Wilson <wilson at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 04 Oct 2002 14:55:53 -0400
- Subject: proposed cse patch for incorrect divide by constant simplication
This testcase fails on a v850 target when compiled with -O -mv850e.
#include <limits.h>
int
sub ()
{
int dummy = 0, a = 16;
if (a / INT_MAX / 16 == 0)
return 0;
else
return a / INT_MAX / 16;
}
int
main ()
{
if (sub () != 0)
abort ();
exit (0);
}
The sub routine is optimized to return -1 instead of 0. This happens as
follows
16 / INT_MAX / 16
16 / (INT_MAX * 16)
16 / -16
-1
The flaw here is that INT_MAX * 16 overflows changing the final result,
and there is no code to check for this overflow case. This optimization is
done in cse. It is trivial to disable it. I haven't checked in this patch
in case someone wants to suggest a different solution, such as removing the
optimization, or trying to make it work by checking for overflow. I don't
think there is any easy way to check for RTL operation overflow though.
If we created trees and folded the trees, we would get an overflow indication,
but that is a lot of trouble to go to here. If we widened the arguments to
a double-wide mode, performed the multiply, and truncated back to the original
mode, then we could check to see if bits were lost in the truncation, but again
that seems like a lot of trouble to for this optimization. This is essentially
what happens if we use trees for the multiply. I had trouble writting a small
testcase for this problem, so I am skeptical about the usefulness of this
optimization inside cse. This optimization problem has been present since
gcc-2.0.
Er, actually, I guess I should be disabling the UDIV case also. That is an
oversight that is easy to fix.
2002-10-04 Jim Wilson <wilson@redhat.com>
* cse.c (fold_rtx): In associative op code, add break if code is DIV.
Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.238
diff -p -r1.238 cse.c
*** cse.c 1 Oct 2002 12:19:36 -0000 1.238
--- cse.c 4 Oct 2002 18:38:09 -0000
*************** fold_rtx (x, insn)
*** 4262,4267 ****
--- 4262,4272 ----
/* Compute the code used to compose the constants. For example,
A/C1/C2 is A/(C1 * C2), so if CODE == DIV, we want MULT. */
+ /* ??? This optimization fails for the DIV case if C1 * C2
+ overflows. */
+ if (code == DIV)
+ break;
+
associate_code
= (code == MULT || code == DIV || code == UDIV ? MULT
: is_shift || code == PLUS || code == MINUS ? PLUS : code);