GCC 4.3 (experimental) -O2 dislikes intparam.h
When compiled with optimization -O2 and higher, the SVN trunk version of GCC miscompiles CLN's autoconf/intparam.c file. I cannot reproduce this with GCC-4.1.0 (no intermediate versions tested). The consequence of this is that the build fails very early due to #error's in the generated intparam.h file. I have reduced the difference to compiling the program below on GNU/Linux x86: $ gcc-4.3 -W -Wall -o foo foo.i $ ./foo /* Integers of type int have 32 bits. */ #define int_bitsize 32 $ gcc-4.3 -O2 -W -Wall -o foo foo.i $ ./foo #error "Integers of type int have no binary representation!!" Now, I was about to report a compiler bug ... except that I think the compiler is right here: integer overflow produces undefined behavior, so I think intparam.c should be fixed instead. With unsigned 'x', things are computed correctly. I guess you could just always use the respective unsigned variant for computing the bitsize of a type. (Using 'volatile int' helps with this GCC version, but I don't think that is guaranteed by the standard.) Next, please note that intparam.c uses exit but does not provide for a prototype. I recommend returning from main instead. Furthermore, please note that the CLN headers cause many "might break strict aliasing" warnings, and a few "will break strict aliasing" warnings. The latter are (at least) here: src/complex/ring/cl_C_ring.cc:131 src/rational/ring/cl_RA_ring.cc:129 src/real/ring/cl_R_ring.cc:133 Hope that helps. Cheers, Ralf /* foo.i */ extern int printf (__const char *__restrict __format, ...); static int int_bitsize; int main(void) { int x = 1; int bits = 0; while(1) { if (x==0) break; x = x+x; bits++; if (bits==1000) { bits = -1; break; } } int_bitsize = bits; if (int_bitsize >= 0) { printf("/* Integers of t%spe %s have %ld bits. */\n","y","int",(long)int_bitsize); if (!("int"[0] == 'u')) { printf("#define "); printf("int"); printf("_bitsize %ld\n",(long)int_bitsize); } printf("\n"); } else { printf("#error \"Integers of t%spe %s have no binary representation!!\"\n","y","int"); } return 0; }
* quoting myself:
Now, I was about to report a compiler bug ... except that I think the compiler is right here: integer overflow produces undefined behavior, so I think intparam.c should be fixed instead.
You may be interested in the thread that a similar bug again gnulib evoked: <http://thread.gmane.org/gmane.comp.lib.gnulib.bugs/8152> Cheers, Ralf
Hello Ralf, Thanks for the early gcc testing!
I have reduced the difference to compiling the program below on GNU/Linux x86:
$ gcc-4.3 -W -Wall -o foo foo.i $ ./foo /* Integers of type int have 32 bits. */ #define int_bitsize 32
$ gcc-4.3 -O2 -W -Wall -o foo foo.i $ ./foo #error "Integers of type int have no binary representation!!"
Now, I was about to report a compiler bug ... except that I think the compiler is right here: integer overflow produces undefined behavior, so I think intparam.c should be fixed instead.
There are hundreds of places in CLN where signed integers are shifted left, or where unsigned integers are added, assuming a "modulo 2^n" behaviour. Without a GCC diagnostic that points to the source code places where gcc does not follow the "modulo 2^n" behaviour, this GCC is unusable for CLN. If the GCC people don't consider it a bug in the compiler, can you please ask them for a warning that accompanies these new optimizations?
Next, please note that intparam.c uses exit but does not provide for a prototype. I recommend returning from main instead.
Exit and return from main is not the same on VMS.
Furthermore, please note that the CLN headers cause many "might break strict aliasing" warnings, and a few "will break strict aliasing" warnings. The latter are (at least) here: src/complex/ring/cl_C_ring.cc:131 src/rational/ring/cl_RA_ring.cc:129 src/real/ring/cl_R_ring.cc:133
I think you can ignore these 3 warnings; there is not much opportunity for aliasing here. Bruno
* Bruno Haible wrote on Tue, Dec 19, 2006 at 02:13:56PM CET:
There are hundreds of places in CLN where signed integers are shifted left, or where unsigned integers are added, assuming a "modulo 2^n" behaviour. Without a GCC diagnostic that points to the source code places where gcc does not follow the "modulo 2^n" behaviour, this GCC is unusable for CLN.
So you'll need -fwrapv for CLN, as well as -fno-strict-aliasing.
If the GCC people don't consider it a bug in the compiler, can you please ask them for a warning that accompanies these new optimizations?
I intend to, but I'll wade through the thread only after the storm has calmed down.
Next, please note that intparam.c uses exit but does not provide for a prototype. I recommend returning from main instead.
Exit and return from main is not the same on VMS.
But then you need a declaration for exit. FYI, the last variant Autoconf had can be inferred from this thread: <http://lists.gnu.org/archive/html/autoconf-patches/2006-04/msg00045.html>
Furthermore, please note that the CLN headers cause many "might break strict aliasing" warnings, and a few "will break strict aliasing" warnings. The latter are (at least) here: src/complex/ring/cl_C_ring.cc:131 src/rational/ring/cl_RA_ring.cc:129 src/real/ring/cl_R_ring.cc:133
I think you can ignore these 3 warnings; there is not much opportunity for aliasing here.
I don't think the "will break strict aliasing" warnings tell you about likely failures. I think they tell you about certain (in the sense of "for sure") failures, given enough optimization (IOW, without -fno-strict-aliasing). IIRC, GCC is entitled to think that the converted pointer points to uninitialized data, and fill in whatever it likes. So yes, there is aliasing involved here, between the pointer (cl_number_ring_ops<cl_number>*) &N_ops and the pointer &N_ops, but reading the former doesn't guarantee to give you the data pointed to by the latter. Cheers, Ralf
Ralf Wildenhues wrote:
* Bruno Haible wrote on Tue, Dec 19, 2006 at 02:13:56PM CET:
There are hundreds of places in CLN where signed integers are shifted left, or where unsigned integers are added, assuming a "modulo 2^n" behaviour. Without a GCC diagnostic that points to the source code places where gcc does not follow the "modulo 2^n" behaviour, this GCC is unusable for CLN.
So you'll need -fwrapv for CLN
That may well be. Thanks for digging up this solution.
as well as -fno-strict-aliasing.
I don't think this is necessary.
Next, please note that intparam.c uses exit but does not provide for a prototype. I recommend returning from main instead.
Exit and return from main is not the same on VMS.
But then you need a declaration for exit.
OK, I'm dropping VMS support and using 'return' in all cases.
I think you can ignore these 3 warnings; there is not much opportunity for aliasing here.
I don't think the "will break strict aliasing" warnings tell you about likely failures. I think they tell you about certain (in the sense of "for sure") failures, given enough optimization (IOW, without -fno-strict-aliasing). IIRC, GCC is entitled to think that the converted pointer points to uninitialized data, and fill in whatever it likes. So yes, there is aliasing involved here, between the pointer (cl_number_ring_ops<cl_number>*) &N_ops
and the pointer &N_ops, but reading the former doesn't guarantee to give you the data pointed to by the latter.
I think you are overstating the problem. GCC uses the alias analysis to decide whether reordering instructions is allowed, i.e. whether a write to a memory location may interfere with a read from a memory location. Here, N_ops is a read-only, statically initialized, memory area - no writes can happen to it, and therefore there is no problem with aliasing. If GCC were "entitled to think that the converted pointer points to uninitialized data", that would be against the rules of how reinterpret_cast<> works, IMO. Bruno
* Bruno Haible wrote on Tue, Dec 19, 2006 at 03:57:29PM CET:
Ralf Wildenhues wrote:
IIRC, GCC is entitled to think that the converted pointer points to uninitialized data, and fill in whatever it likes.
I think you are overstating the problem.
May well be that GCC isn't as mean as I portrayed it, and hopefully won't ever be. But it's not ISO C that forbids this interpretation. I'm less fluent with C++ about whether the cast there makes more guarantees. My suggestion to use the corresponding unsigned types in intparam.c was apparently flawed, as they can have more value bits. I guess you knew this already. Cheers, Ralf
participants (2)
-
Bruno Haible
-
Ralf Wildenhues