bebbo / gcc

Bebbo's gcc-6-branch for m68k-amigaos
GNU General Public License v2.0
33 stars 11 forks source link

Code generator for integer math bug? #160

Closed alexalkis closed 3 years ago

alexalkis commented 3 years ago
#include <stdio.h>
#include <time.h>

void intmath(void) {
  clock_t startTime = clock();

  printf("Start\n");
  int x = 0;
  int y = 3;
  for(short int i = 1; i<=10000; ++i) {
    x = x + ( y*y-y ) / y;
    y = y + ( x*x-x ) / x;
  }
  printf("Finish : %d\n", x);

  clock_t stopTime = clock();

  printf("Took %d  (%d)\n", stopTime-startTime, CLOCKS_PER_SEC);
}

int main(int argc, char **argv) {
    intmath();
    return 0;
}
m68k-amigaos-gcc -mcrt=nix13 -O3 -o benchint benchint.c 
alex[0]@ubvm bench$ vamos benchint
Start
Finish : -188185810
Took 20  (1000)
alex[0]@ubvm bench$ ./foo 
Start
Finish : 387150795
Took 204  (1000000)

foo is natively compiled in linux. Gives different result in final value of 'x'.

bebbo commented 3 years ago

that's a general gcc-6 bug - nothing amiga specific.

the calculation in the loop gets optimized to:

   x = (y + -1) + x;
   y = (x + -1) + y;
bebbo commented 3 years ago

and the best: that optimization is done inside the c-parser! use

#include <stdio.h>
#include <time.h>

void intmath(void) {
  int x = 0;
  int y = 3;
  short int i;
  for(i = 1; i<=10000; ++i) {
      int yy = y*y;
      x = x + ( yy-y ) / y;
      int xx = x*x;
      y = y + ( xx-x ) / x;
  }
  printf("Finish : %d\n", x);
}
alexalkis commented 3 years ago

ok. Thanks!

bebbo commented 3 years ago

https://franke.ms/cex/z/3Wefxx

bebbo commented 3 years ago

everything is ok: "by default GCC assumes there will be no overflow with integer arithmetic"

=> use -fno-strict-overflow to disable such optimizations.

it's not a bug, it's a feature.