Hi! Preface: this seems to be a bug in the GCC compiler/optimizer, but it could easily be solved by changing the Apache 2.4 source code, so you may want to consider to integrate it. Also the workaround I found may help others, therfore I'm posting it here. The compilation of Apache 2.4.1 on Solaris 10 SPARC with GCC 4.6.3 and 64 bit mode fails with an assembler error: /var/tmp//cc8T9vzx.s: Assembler messages: /var/tmp//cc8T9vzx.s:12254: Error: Illegal operands The line stated contains fdtox %f8, %f9 which - as far as some research indicates - is an illegal operation in 64 bit mode with an odd numbered register. Details are available if needed. Anyway. Some analysis revealed that the root cause is an optimization (?) to use apr_uint16_t in ap_random_pick in core.c. Removing this solves the problem. --- httpd-2.4.1/server/core.c 2012-02-04 11:04:59.000000000 +0100 +++ patched_core.c 2012-03-12 15:22:27.075035399 +0100 @@ -4722,16 +4722,20 @@ AP_DECLARE(void) ap_random_insecure_byte AP_DECLARE(apr_uint32_t) ap_random_pick(apr_uint32_t min, apr_uint32_t max) { apr_uint32_t number; - if (max < 16384) { - apr_uint16_t num16; - ap_random_insecure_bytes(&num16, sizeof(num16)); - RAND_RANGE(num16, min, max, APR_UINT16_MAX); - number = num16; - } - else { +/* Workaround for GCC 4.6.x producing illegal assembler code on SPARC + * if (max < 16384) { + * apr_uint16_t num16; + * ap_random_insecure_bytes(&num16, sizeof(num16)); + * RAND_RANGE(num16, min, max, APR_UINT16_MAX); + * number = num16; + * } + * else { + */ ap_random_insecure_bytes(&number, sizeof(number)); RAND_RANGE(number, min, max, APR_UINT32_MAX); - } +/* + * } + */ return number; } I don't think this could have any negative side effects, but would appreciate your feedback. Cheers, Martin
I'm having the same problem on FreeBSD/sparc64. NetBSD is affected, too: http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=47025
Has someone tested this with a more recent version of gcc? If it is fixed there, we could add some #ifdef magic to apply the workaround only on older gcc's. If it isn't fixed, then a bug should be filed on gcc. Always using the 32bit type uses more output from the RNG than necessary. And the RNG is relatively expensive (it uses sha256 internally).
I tried to reproduce on Solaris 10 Sparc, using the following compilers: gcc-4.1.2 gcc-4.5.4 gcc-4.6.3 gcc-4.7.1 gcc-4.7.2 and CFLAGS "-mcpu=v9 -m64 -O2" source code was httpd 2.4.4. Unfortunately in my tests compilation succeeds for gcc-4.1.2, gcc-4.5.4 and gcc-4.6.3. For the two 4.7 versions I get a failure in as: /usr/ccs/bin/as -V -Qy -s -xarch=v9 -o core.o /var/tmp//cclu5H3f.s /usr/ccs/bin/as: SunOS 5.10 118683-08 Patch 07/05/2012 /usr/ccs/bin/as: "/var/tmp//cclu5H3f.s", line 10402: error: invalid (misaligned) register The assembler line number varies depending on the exact compilation flags. When using CFLAGS only "-m64" there's no problem. 32 Bit compilations always succeed. Here's an excerpt from the assembler code, error is in line 10402: 10378 .LL1698: 10379 add %fp, 2041, %o0 10380 call ap_random_insecure_bytes, 0 10381 mov 2, %o1 10382 sub %i1, %i0, %i1 10383 lduh [%fp+2041], %g1 10384 srl %i1, 0, %i1 10385 st %g1, [%fp+2011] 10386 stx %i1, [%fp+2023] 10387 mov 1023, %g1 10388 ldd [%fp+2023], %f10 10389 sllx %g1, 52, %g1 10390 fxtod %f10, %f12 10391 stx %g1, [%fp+1999] 10392 mov 1007, %g1 10393 ldd [%fp+1999], %f10 10394 sllx %g1, 52, %g1 10395 faddd %f12, %f10, %f10 10396 ld [%fp+2011], %f8 10397 stx %g1, [%fp+1999] 10398 fitod %f8, %f8 10399 ldd [%fp+1999], %f12 10400 fmuld %f8, %f12, %f8 10401 fmuld %f10, %f8, %f8 10402 fdtox %f8, %f9 <=========== 10403 st %f10, [%fp+2011] 10404 lduw [%fp+2011], %g1 10405 add %g1, %i0, %i0 10406 sll %i0, 16, %i0 10407 srl %i0, 16, %i0 10408 return %i7+8 10409 srl %o0, 0, %o0 10410 .size ap_random_pick, .-ap_random_pick 10411 .global core_module 10412 .section ".data" 10413 .align 8 10414 .type core_module, #object 10415 .size core_module, 104 10416 core_module: This looks like an old bug that was fixed in gcc 3.x times. Although my Solaris assembler gives another error text, the problematic assembler line is the same as reported by the OP. Strange that it compiles for me with 4.6 but not with 4.6. Unfortunately we don't know the exact flags used by the OP. Regards, Rainer
Since there's not a strict relation with the compiler version, maybe it is one of the helper libs, like gmp, which also contains assembler. My gcc 4.7 was build using gmp 5.0.5.
> and CFLAGS "-mcpu=v9 -m64 -O2" source code was httpd 2.4.4. My CFLAGS were "-m64 -O3 -mcpu=niagara -pthreads -fexceptions -fstack-protector --param=ssp-buffer-size=4" The build succeeds if I omit the optimization flag, which matches Rainer's findings. If I remember correctly the optimization level does not matter, even with O1 the error occurs. Maybe even the bintuils version matters, so maybe we should post these versions as well. I'm currently running a test with gcc 4.7.2, GMP 5.1.1 and binutils 2.23.1 and will post the result. Trying gcc 4.8.0 will take a day or two more. Cheers, Martin
> I'm currently running a test with gcc 4.7.2, GMP 5.1.1 and > binutils 2.23.1 and will post the result. /var/tmp//ccMYi3X2.s: Assembler messages: /var/tmp//ccMYi3X2.s:12710: Error: Illegal operands Bug still there. Cheers, Martin
Created attachment 30163 [details] add workaround on sparc/64 We could disable the if block on gcc/sparc/64bit explicitly. This patch should do that. But it would still be good if someone with a sparc machine would also file a bug report with gcc and add its URL here.
Created attachment 30164 [details] Minimal test case Minimal test case showing gcc bug. Compilation on Sparc with gcc 4.7 (for some builds also 4.6) fails for -m64 when any optimization is enabled.
Created attachment 30165 [details] Slightly bigger test case, showing errors even with O1 on Sparc 64 Bits.
The minimal test case and the slightly larger one fail with -O2 when compiling for 64 Bits on Sparc with recent GCC (4.7.1 and 4.7.2 for me, *not* 4.6.3 for me, but likely also 4.6.3 for the OP, maybe due to the version of GMP, MPC or MPFR used?). Error is error: invalid (misaligned) register due to the line fdtox %f8, %f9 It seems the second register must have an even number. The slightly bigger test case also fails for O1 and for simple -O with a different error: test.c: In function 'buggy': test.c:13:1: error: insn does not satisfy its constraints: (insn 126 42 43 3 (set (reg:HI 40 %f8 [orig:120 D.1367 ] [120]) (reg:HI 42 %f10)) test.c:6 58 {*movhi_insn} (nil)) test.c:13:1: internal compiler error: in reload_cse_simplify_operands, at postreload.c:403 Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. This minimal test case does not fail with "-O1" or "-O", probably because of another register allocation strategy due to the missing second code path. I'll open a GCC bug report.
Filed GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56890
(In reply to comment #5) > Trying gcc 4.8.0 will take a day or two more. Compilation of 2.4.4 with gcc 4.8.0 and CFLAGS including "-m64 -O3 -mcpu=niagara" works without any patch. Cheers, Martin
Could you please try gcc 4.8.0 with my two very simple to compile test cases, once with only "-m64 -O" and once with "-m64 -O2" so that we get comparable results? I will then rpeort back to the gcc bug. Thanks!
(In reply to comment #13) > Could you please try gcc 4.8.0 with my two very simple to compile test > cases, once with only "-m64 -O" and once with "-m64 -O2" so that we get > comparable results? I will then rpeort back to the gcc bug. Done. Added a tarball to the gcc bug. Bottom line: gcc 4.8.0 compiles the source fine, most likely any older version would need a workaround if CFLAGS include -m64 and -Ox (x>=1) . Cheers, Martin
I have not yet checked httpd compilation, but I can confirm, that the test cases compile fine with GCC 4.8.0. Problem still exists with 4.7.3.
A patch has been applied to gcc trunk and 4.7 and 4.8 branches. I tried the patch on top of gcc 4.7.3 and it does compile then. So: - we didn't see a problem with 4.8 - we had a problem with 4.7 which should be fixed in 4.7.4 (not yet released) - some of us had a problem in 4.6.3.No patch was applied to that branch. - It seems there was no problem before 4.6. Rainer
> - It seems there was no problem before 4.6. I can't confirm that. On FreeBSD/sparc64 we're using: gcc version 4.2.1 20070831 patched [FreeBSD] and I ran into the problem.
Created attachment 30217 [details] Workaround for sparc/64 on gcc < 4.8 So, since we don't know an exact version where the bug was introduced, I think we should simply add the workaround for all gccs < 4.8. Can someone verify that this patch does the trick?
Works for me[tm] :)
thanks. trunk commit: r1470183
Backported to 2.4.x as r1470183.