This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]