compiler problems with 64 bit integers

Kish Shen
2009-03-09
2013-06-06
  • Kish Shen

    Kish Shen - 2009-03-09

    Hi,

    I have been trying to port some code to Win64 using MinGW-W64 (cross compiling on a Linux box, if this matters), and I have run into 3 issues, which seem to be all related to casting/overflow of signed/unsigned 64 bit integers, when the code is compiled with -O2. I don't know if these problems are MinGW specific, but we ave been compiling the same code with gcc for various other platforms without problems, although we have not used gcc 4.4.0 before (4.4.0 is the version of gcc we are using with MinGW W64) -- I think gcc 4.1 or possibly 4.2 is the latest version we have tested extensively for our code.

    All of the problems disappears when the code is compiled without -O2 flag.

    I have tried to reproduce the problems using simple code fragments, but I have only succeeded in doing this for 2 of the problems (t1 and t3 in the following code). I cannot reproduce the other problem (t2 in the following code). Running the program (with -O2) produced the following:

    $ ~/a.exe
    w is 8000000000000000
    , V is 8000000000000000
    t1 Wrong!
    v != w
    t2 Correct!
    t3: w = 8000000000000000
    t3 Wrong!

    In our actual code corresponding to t2, we do the same comparison of
    if ((uword) w > (uword) MX_S_W))

    and the comparison fails when w was originally negative.

    For t1 and t3, I can see why some optimisation might reason away the actual tests, if it does not consider overflow of the signed word. Curiously, removing the printf before if (w <= 0) ... line in t3 cause the
    if (w <= 0) test to fail -- I don't see why this happens.

    (in our original code, we don't have the printf, but w <= 0 does succeed, it is the w == MN_S_W test that fails as in t3).

    As I said, I don't know if this is a gcc 4.4 problem or not. If people feel that this problem should be reported to gcc instead of here, please let me know. [I don't know if gcc is accepting bug reports for using gcc with MinGW?]

    Thanks in advance for any help/information!

    Kish

    =================================================

    #include <stdio.h>
    typedef long long word;
    typedef unsigned long long uword;

    #define S_B ((uword) (0x8000000000000000LL))

    #define MX_S_W ((word) ~S_B)
    #define MN_S_W ((word) S_B)

    int t1(word v) {
      word w = MN_S_W;

      if (v < 0) {
        v = -v;
      }
      w = -w;
      printf("w is %I64x\n, V is %I64x\n", w, v);
      if (v < 0) {
        printf("t1 Correct!\n");
      } else printf("t1 Wrong!\n");

      if (w == v) printf("v == w\n"); else printf("v != w\n");
    }

    int t2(word w) {
      if ((uword) w > (uword) MX_S_W) {
        printf("t2 Correct!\n");
      } else
        printf("t2 Wrong!\n");
    }

    int t3(word v) {
      word w;
      w = v + 1;
      printf("t3: w = %I64x\n", w);
      if (w <= 0) {
        if (w == MN_S_W) printf("t3 Correct!\n");
        else printf("t3 Wrong!\n");
      }
    }

    main() {

      word v, w;

      v = MN_S_W;
      w = -1;

      t1(v);
      t2(w);
      v = MX_S_W;
      t3(v);
    }

     
    • Kai Tietz

      Kai Tietz - 2009-03-09

      Thank you for this testcase. Yeah, it is a gcc 4.4 issue. It would be good to check, if this problem also appears for linux64.

      It would be kind, if you could post a bug report on gcc about this, too.

      Cheers,
      Kai

       
    • Kish Shen

      Kish Shen - 2009-03-10

      Hi,

      Thanks. Unfortunately, currently I don't have access to a x86-64 Linux platform. However, I assume that if these are gcc 4.4 optimizer problems, then they will also occur on x86 32 bit Linux as well. I will try and build gcc 4.4 for Linux with  the gcc 4.4 source that was downloaded for MinGW-W64.

      I have never reported a bug for gcc before -- would they accept a bug report for MinGW-W64 only, or do you think I need to reproduce the bug on another platform first?

      Thanks and cheers,

      Kish

       
      • Kai Tietz

        Kai Tietz - 2009-03-10

        Hi,

        the advantage of reporting it against a primary (or secondary) target is, that it'll get fixed faster. We as mingw-w64 are sadly aren't at the moment one of those, so it can take time until this problem get fixed.
        But of course you can report it only for x86_64-pc-mingw32, too.

        Cheers,
        Kai

         
        • Kai Tietz

          Kai Tietz - 2009-03-10

          Ok, tested it on linux64 and there is the same regression. I'll report it to gcc's bug-tracker.

          Cheers,
          Kai

           
          • Kai Tietz

            Kai Tietz - 2009-03-10
             
            • Kai Tietz

              Kai Tietz - 2009-03-10

              As you can see by the bug report gcc assumes (just for optimiztation) that

              if (a < 0) a = -a;

              that a is always >= 0 (which is wrong for overflow).

              If you use the switch '-fwrapv' the code works as you expected. I am a bit curious that this kind of *unsafe* optimization is done in gcc by default.

              Cheers,
              Kai

               
    • Kish Shen

      Kish Shen - 2009-03-10

      Hi Kai,

      Yes, I suspected they might say that this is not a bug, but t2 (which I was not able to produce simple code to reproduce) does not have overflow as such, although it does imply casting a negative signed integer to a large unsigned integer.
      Does this optimisation actually do anything else except for optimise away tests like a < 0? We are using such code precisely because we wanted to catch the special overflow cases, and testing for a < 0 seems the cheapest (I know it assumes two's compliment format, but this seems reasonable to me).

      Cheers,

      Kish

       
      • Kai Tietz

        Kai Tietz - 2009-03-10

        Well, if you could find a reproducable case for t2, it would be great. I spoke with them about this default overflow ignoring optimization and they simply meant that an overflow in C/C++ spec has simply undefined behaviour. That's true, so I see here no much chance as to use for your code -fwrapv. IMHO it is a bug, because it make no sense to produce in unoptimized code those checks and in optimized code not. And I don't see that much advantage in this, but well ...

        Cheers,
        Kai

         

Log in to post a comment.