On x32 branch, I got /export/build/gnu/gcc-x32/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/gcc-x32/build-x86_64-linux/gcc/ -S -o u.s -mx32 -O2 -g -fPIC u.c u.c: In function \u2018__frame_state_for\u2019: u.c:14:1: error: unable to find a register to spill in class \u2018DIREG\u2019 u.c:14:1: error: this is the insn: (insn 11 20 14 2 (parallel [ (set (reg:DI 2 cx [64]) (const_int 0 [0])) (set (reg/f:DI 0 ax [62]) (plus:DI (ashift:DI (reg:DI 2 cx [64]) (const_int 3 [0x3])) (reg/f:DI 1 dx [60]))) (set (mem/s/c:BLK (reg/f:DI 1 dx [60]) [0 context+0 S72 A64]) (const_int 0 [0])) (use (reg:DI 0 ax [63])) (use (reg:DI 2 cx [64])) ]) u.c:11 874 {*rep_stosdi_rex64} (expr_list:REG_DEAD (reg:DI 0 ax [63]) (expr_list:REG_UNUSED (reg:DI 2 cx [64]) (expr_list:REG_UNUSED (reg/f:DI 0 ax [62]) (nil))))) u.c:14:1: internal compiler error: in spill_failure, at reload1.c:2105 Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. make: *** [u.s] Error 1 [hjl@gnu-6 ilp32-14]$
Combine changes (insn 2 4 3 2 (set (reg/v/f:DI 59 [ pc_target ]) (zero_extend:DI (reg:SI 5 di [ pc_target ]))) u.i:9 115 {*zero_extendsidi2_rex64} (expr_list:REG_DEAD (reg:SI 5 di [ pc_target ]) (nil))) ... (insn 11 10 14 2 (parallel [ (set (reg:DI 64) (const_int 0 [0])) (set (reg/f:DI 62) (plus:DI (ashift:DI (reg:DI 64) (const_int 3 [0x3])) (reg/f:DI 60))) (set (mem/s/c:BLK (reg/f:DI 60) [0 context+0 S72 A64]) (const_int 0 [0])) (use (reg:DI 63)) (use (reg:DI 64)) ]) u.i:11 874 {*rep_stosdi_rex64} (expr_list:REG_DEAD (reg:DI 63) (expr_list:REG_UNUSED (reg:DI 64) (expr_list:REG_UNUSED (reg/f:DI 62) (nil))))) (insn 14 11 16 2 (set (mem/s/f/c:SI (plus:DI (reg/f:DI 20 frame) (const_int -8 [0xfffffffffffffff8])) [3 context.ra+0 S4 A64]) (subreg/s/u:SI (reg/v/f:DI 59 [ pc_target ]) 0)) u.i:12 64 {*movsi_internal} (expr_list:REG_DEAD (reg/v/f:DI 59 [ pc_target ]) (nil))) to (insn 11 10 14 2 (parallel [ (set (reg:DI 64) (const_int 0 [0])) (set (reg/f:DI 62) (plus:DI (ashift:DI (reg:DI 64) (const_int 3 [0x3])) (reg/f:DI 60))) (set (mem/s/c:BLK (reg/f:DI 60) [0 context+0 S72 A64]) (const_int 0 [0])) (use (reg:DI 63)) (use (reg:DI 64)) ]) u.i:11 874 {*rep_stosdi_rex64} (expr_list:REG_DEAD (reg:DI 63) (expr_list:REG_UNUSED (reg:DI 64) (expr_list:REG_UNUSED (reg/f:DI 62) (nil))))) (insn 14 11 16 2 (set (mem/s/f/c:SI (plus:DI (reg/f:DI 20 frame) (const_int -8 [0xfffffffffffffff8])) [3 context.ra+0 S4 A64]) (reg:SI 5 di [ pc_target ])) u.i:12 64 {*movsi_internal} (expr_list:REG_DEAD (reg:SI 5 di [ pc_target ]) (nil))) Since *rep_stosdi_rex64 needs the RDI register, it kills reload. Eric, should combine move hard register?
I think this is similar to PR 47449.
I am testing this patch: diff --git a/gcc/combine.c b/gcc/combine.c index 5e1236b..78f3089 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -2138,6 +2138,12 @@ cant_combine_insn_p (rtx insn) return asm_noperands (PATTERN (insn)) > 0; src = SET_SRC (set); dest = SET_DEST (set); + if (GET_CODE (src) == ZERO_EXTEND + || GET_CODE (src) == SIGN_EXTEND) + src = XEXP (src, 0); + if (GET_CODE (dest) == ZERO_EXTEND + || GET_CODE (dest) == SIGN_EXTEND) + dest = XEXP (dest, 0); if (GET_CODE (src) == SUBREG) src = SUBREG_REG (src); if (GET_CODE (dest) == SUBREG)
> --- a/gcc/combine.c > +++ b/gcc/combine.c > @@ -2138,6 +2138,12 @@ cant_combine_insn_p (rtx insn) > return asm_noperands (PATTERN (insn)) > 0; > src = SET_SRC (set); > dest = SET_DEST (set); > + if (GET_CODE (src) == ZERO_EXTEND > + || GET_CODE (src) == SIGN_EXTEND) > + src = XEXP (src, 0); > + if (GET_CODE (dest) == ZERO_EXTEND > + || GET_CODE (dest) == SIGN_EXTEND) > + dest = XEXP (dest, 0); > if (GET_CODE (src) == SUBREG) > src = SUBREG_REG (src); > if (GET_CODE (dest) == SUBREG) ZERO_EXTEND and SIGN_EXTEND are real operations (they generate code) though, so this will pessimize. Who generates insn #2? The machinery handling parameters in function.c? If so, maybe it should do the copy in the incoming mode instead: (insn 2 4 3 2 (set (reg/v/f:SI 59 [ pc_target ]) (reg:SI 5 di [ pc_target ])) (insn 3 5 4 2 (set (reg:DI 60) (zero_extend:DI (reg/v/f:SI 59 [ pc_target ])))
(In reply to comment #4) > > Who generates insn #2? The machinery handling parameters in function.c? If > so, maybe it should do the copy in the incoming mode instead: > > (insn 2 4 3 2 (set (reg/v/f:SI 59 [ pc_target ]) > (reg:SI 5 di [ pc_target ])) > > (insn 3 5 4 2 (set (reg:DI 60) > (zero_extend:DI (reg/v/f:SI 59 [ pc_target ]))) assign_parm_setup_reg has enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND; rtx insn, insns; HARD_REG_SET hardregs; start_sequence (); insn = gen_extend_insn (op0, op1, promoted_nominal_mode, data->passed_mode, unsignedp); emit_insn (insn); insns = get_insns ();
This seems to work: diff --git a/gcc/function.c b/gcc/function.c index 3f721fb..4c78407 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3000,11 +3000,15 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, && insn_data[icode].operand[1].predicate (op1, data->passed_mode)) { enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND; - rtx insn, insns; + rtx insn, insns, copy; HARD_REG_SET hardregs; start_sequence (); - insn = gen_extend_insn (op0, op1, promoted_nominal_mode, + /* We must copy the hard register first before extending it. + Otherwise, combine won't see the hard register. */ + copy = gen_reg_rtx (data->passed_mode); + emit_move_insn (copy, op1); + insn = gen_extend_insn (op0, copy, promoted_nominal_mode, data->passed_mode, unsignedp); emit_insn (insn); insns = get_insns ();
Author: hjl Date: Mon Feb 14 18:54:12 2011 New Revision: 170148 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=170148 Log: Copy the hard register first before extending it. gcc/ 2011-02-14 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * function.c (assign_parm_setup_reg): Copy the hard register first before extending it. gcc/testsuite/ 2011-02-13 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * gcc.dg/torture/pr47725.c: New. Added: branches/x32/gcc/testsuite/gcc.dg/torture/pr47725.c Modified: branches/x32/gcc/ChangeLog.x32 branches/x32/gcc/function.c branches/x32/gcc/testsuite/ChangeLog.x32
A patch is posted at http://gcc.gnu.org/ml/gcc-patches/2011-02/msg00909.html
Author: hjl Date: Tue Feb 15 16:50:43 2011 New Revision: 170179 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=170179 Log: Check zero/sign extended hard registers. gcc/ 2011-02-15 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * combine.c (cant_combine_insn_p): Check zero/sign extended hard registers. gcc/testsuite/ 2011-02-15 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * gcc.dg/torture/pr47725.c: New. Added: trunk/gcc/testsuite/gcc.dg/torture/pr47725.c Modified: trunk/gcc/ChangeLog trunk/gcc/combine.c trunk/gcc/testsuite/ChangeLog
Author: hjl Date: Tue Feb 15 19:46:26 2011 New Revision: 170197 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=170197 Log: Revert cant_combine_insn_p change. gcc/ 2011-02-15 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * combine.c (cant_combine_insn_p): Revert the last change. gcc/testsuite/ 2011-02-15 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * gcc.dg/torture/pr47725.c: Removed. Removed: trunk/gcc/testsuite/gcc.dg/torture/pr47725.c Modified: trunk/gcc/ChangeLog trunk/gcc/combine.c trunk/gcc/testsuite/ChangeLog
Author: hjl Date: Wed Feb 16 20:15:07 2011 New Revision: 170218 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=170218 Log: Check zero/sign extended hard registers in cant_combine_insn_p. 2011-02-15 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * combine.c (cant_combine_insn_p): Check zero/sign extended hard registers. Modified: branches/x32/gcc/ChangeLog.x32 branches/x32/gcc/combine.c
Author: hjl Date: Fri Mar 18 00:29:15 2011 New Revision: 171124 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=171124 Log: Check zero/sign extended hard registers. gcc/ 2011-03-17 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * combine.c (cant_combine_insn_p): Check zero/sign extended hard registers. gcc/testsuite/ 2011-03-17 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * gcc.dg/torture/pr47725.c: New. Added: trunk/gcc/testsuite/gcc.dg/torture/pr47725.c Modified: trunk/gcc/ChangeLog trunk/gcc/combine.c trunk/gcc/testsuite/ChangeLog
Author: hjl Date: Fri Mar 18 04:02:25 2011 New Revision: 171125 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=171125 Log: Revert the last change on cant_combine_insn_p. 2011-03-17 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * combine.c (cant_combine_insn_p): Don't check zero/sign extended hard registers. Modified: trunk/gcc/ChangeLog trunk/gcc/combine.c
Author: hjl Date: Sat Apr 2 06:03:52 2011 New Revision: 171877 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=171877 Log: Don't check zero/sign extended hard registers. 2011-03-29 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * combine.c (cant_combine_insn_p): Don't check zero/sign extended hard registers. Modified: branches/x32/gcc/ChangeLog.x32 branches/x32/gcc/combine.c
Author: hjl Date: Sat Apr 2 06:05:03 2011 New Revision: 171878 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=171878 Log: Promote pointer function arguments and return values to Pmode. 2011-03-29 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 PR target/48085 * calls.c (precompute_register_parameters): Convert pointer to TLS symbol if needed. * config/i386/i386.c (ix86_promote_function_mode): New. (TARGET_PROMOTE_FUNCTION_MODE): Likewise. Modified: branches/x32/gcc/ChangeLog.x32 branches/x32/gcc/calls.c branches/x32/gcc/config/i386/i386.c
Author: hjl Date: Mon Jun 20 14:53:48 2011 New Revision: 175218 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=175218 Log: Check zero/sign extended hard registers. 2011-06-20 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * combine.c (cant_combine_insn_p): Check zero/sign extended hard registers. Modified: trunk/gcc/ChangeLog trunk/gcc/combine.c
> Check zero/sign extended hard registers. > > 2011-06-20 H.J. Lu <hongjiu.lu@intel.com> > > PR middle-end/47725 > * combine.c (cant_combine_insn_p): Check zero/sign extended > hard registers. > > Modified: > trunk/gcc/ChangeLog > trunk/gcc/combine.c Why are you installing this again? The patch isn't correct and I thought it was unnecessary in the end.
Author: hjl Date: Mon Jun 20 17:03:16 2011 New Revision: 175222 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=175222 Log: Don't check zero/sign extended hard registers. 2011-06-20 H.J. Lu <hongjiu.lu@intel.com> PR middle-end/47725 * combine.c (cant_combine_insn_p): Don't check zero/sign extended hard registers. Modified: trunk/gcc/ChangeLog trunk/gcc/combine.c
I'm seeing the same problem in gcc 4.4 and 4.6, I did not test 4.5: paul@semillion:~/code/mercury-compiler-rotd-2011-06-23/compiler$ gcc-4.4 -v -c -o /tmp/out.o -O1 ml_backend.ml_closure_gen.i Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets=all --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu Thread model: posix gcc version 4.4.5 (Debian 4.4.5-8) COLLECT_GCC_OPTIONS='-v' '-c' '-o' '/tmp/out.o' '-O1' '-mtune=generic' '-march=i586' /usr/lib/gcc/i486-linux-gnu/4.4.5/cc1 -fpreprocessed ml_backend.ml_closure_gen.i -quiet -dumpbase ml_backend.ml_closure_gen.i -mtune=generic -march=i586 -auxbase-strip /tmp/out.o -O1 -version -o /tmp/ccbABR7o.s GNU C (Debian 4.4.5-8) version 4.4.5 (i486-linux-gnu) compiled by GNU C version 4.4.5, GMP version 4.3.2, MPFR version 3.0.0-p3. GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=127992 Compiler executable checksum: 0192d925385d4e6642a93c63f245f907 ml_backend.ml_closure_gen.c:32: warning: ‘mercury__ml_backend__ml_closure_gen__ml_gen_maybe_pseudo_type_info_defn_4_0’ used but never defined ml_backend.ml_closure_gen.c: In function ‘ml_backend__ml_closure_gen_module11’: ml_backend.ml_closure_gen.c:230: error: unable to find a register to spill in class ‘DIREG’ ml_backend.ml_closure_gen.c:230: error: this is the insn: (insn 123 122 124 11 ml_backend.ml_closure_gen.c:105 (parallel [ (set (mem:SI (reg/f:SI 136) [0 S4 A32]) (reg/v:SI 80 [ MR_tempr3 ])) (set (reg/v:SI 82 [ MR_tempr1 ]) (plus:SI (reg/f:SI 136) (const_int 4 [0x4]))) ]) 852 {*strsetsi_1} (expr_list:REG_DEAD (reg/f:SI 136) (nil))) ml_backend.ml_closure_gen.c:230: confused by earlier errors, bailing out Preprocessed source stored into /tmp/cccXoZX2.out file, please attach this to your bugreport. I will attach the generated test case.
Created attachment 24808 [details] Test case generated by Mercury Compiler This is a test case generated by the Mercury compiler, it has been reduced just enough code to cause the bug to occur. It can be reproduced in gcc 4.4 and 4.6 at an optimization level of -O1 but not -O0. The output of GCC is: paul@semillion:~/code/mercury-compiler-rotd-2011-06-23/compiler$ gcc-4.4 -v -c -o /tmp/out.o -O1 ml_backend.ml_closure_gen.i Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets=all --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu Thread model: posix gcc version 4.4.5 (Debian 4.4.5-8) COLLECT_GCC_OPTIONS='-v' '-c' '-o' '/tmp/out.o' '-O1' '-mtune=generic' '-march=i586' /usr/lib/gcc/i486-linux-gnu/4.4.5/cc1 -fpreprocessed ml_backend.ml_closure_gen.i -quiet -dumpbase ml_backend.ml_closure_gen.i -mtune=generic -march=i586 -auxbase-strip /tmp/out.o -O1 -version -o /tmp/ccbABR7o.s GNU C (Debian 4.4.5-8) version 4.4.5 (i486-linux-gnu) compiled by GNU C version 4.4.5, GMP version 4.3.2, MPFR version 3.0.0-p3. GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=127992 Compiler executable checksum: 0192d925385d4e6642a93c63f245f907 ml_backend.ml_closure_gen.c:32: warning: ‘mercury__ml_backend__ml_closure_gen__ml_gen_maybe_pseudo_type_info_defn_4_0’ used but never defined ml_backend.ml_closure_gen.c: In function ‘ml_backend__ml_closure_gen_module11’: ml_backend.ml_closure_gen.c:230: error: unable to find a register to spill in class ‘DIREG’ ml_backend.ml_closure_gen.c:230: error: this is the insn: (insn 123 122 124 11 ml_backend.ml_closure_gen.c:105 (parallel [ (set (mem:SI (reg/f:SI 136) [0 S4 A32]) (reg/v:SI 80 [ MR_tempr3 ])) (set (reg/v:SI 82 [ MR_tempr1 ]) (plus:SI (reg/f:SI 136) (const_int 4 [0x4]))) ]) 852 {*strsetsi_1} (expr_list:REG_DEAD (reg/f:SI 136) (nil))) ml_backend.ml_closure_gen.c:230: confused by earlier errors, bailing out Preprocessed source stored into /tmp/cccXoZX2.out file, please attach this to your bugreport.
(In reply to comment #19) > I'm seeing the same problem in gcc 4.4 and 4.6, I did not test 4.5: Please, do not hijack bug reports. Open new one, this one is for x32 (that is x86_64 with 32bit pointers) target.
The testcase, referred in Comment 0 is: struct _Unwind_Context { void *reg[17]; void *ra; }; extern void bar (struct _Unwind_Context *); void __frame_state_for (void *pc_target) { struct _Unwind_Context context; __builtin_memset (&context, 0, sizeof (struct _Unwind_Context)); context.ra = pc_target; bar (&context); } Compiling with recent mainline works OK: ~/gcc-build/gcc/cc1 -O2 -fpic -mx32 pr47725.c __frame_state_for: .LFB0: .cfi_startproc subq $88, %rsp .cfi_def_cfa_offset 96 movq %rdi, %rsi xorl %eax, %eax movq %rsp, %rdi movl $9, %ecx rep stosq movq %rsp, %rdi movl %esi, 68(%rsp) call bar@PLT addq $88, %rsp .cfi_def_cfa_offset 8 ret Fixed.