------- Comment #6 from uros at kss-loka dot si 2005-11-09 15:27 ------- The problem is caused by the combination of (1) x86_64 parameter passing convention, (2) x86 instructions that _require_ parameters in specific registers and (3) sched1 scheduling pass.
ad 1) x86_64 passes function parameters in registers in the order, defined in x86_64_int_parameter_registers[] array. 5 /*RDI*/, 4 /*RSI*/, 1 /*RDX*/, 2 /*RCX*/, FIRST_REX_INT_REG /*R8 */, FIRST_REX_INT_REG + 1 /*R9 */ Additionally, RAX is used as a hidden argument register. In original example, call sequence to "memory_to_string" is constructed as: (insn 17 15 18 0 (set (reg:DI 4 si) (reg:DI 61)) 81 {*movdi_1_rex64} (insn_list:REG_DEP_TRUE 15 (nil)) (expr_list:REG_DEAD (reg:DI 61) (nil))) (insn 18 17 19 0 (set (reg:DI 5 di [ c_string ]) (reg/v/f:DI 60 [ c_string ])) 81 {*movdi_1_rex64} (nil) (expr_list:REG_DEAD (reg/v/f:DI 60 [ c_string ]) (nil))) (call_insn 19 18 20 0 (set (reg:DI 0 ax) (call (mem:QI (symbol_ref:DI ("memory_to_string") [flags 0x3] <function_decl 0x4044f080 memory_to_string>) [0 S1 A8]) (const_int 0 [0x0]))) 732 {*call_value_0_rex64} (insn_list:REG_DEP_TRUE 17 (insn_list:REG_DEP_TRUE 18 (nil))) (expr_list:REG_DEAD (reg:DI 4 si) (expr_list:REG_DEAD (reg:DI 5 di [ c_string ]) (expr_list:REG_EH_REGION (const_int 0 [0x0]) (nil)))) (expr_list:REG_DEP_TRUE (use (reg:DI 5 di [ c_string ])) (expr_list:REG_DEP_TRUE (use (reg:DI 4 si)) (nil)))) ad 2) Please note, that this sequence can be found just after *strlenqi_rex_1 mega-pattern. This pattern requires parameters to be put in excactly defined registers: (define_insn "*strlenqi_rex_1" [(set (match_operand:DI 0 "register_operand" "=&c") (unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1")) (match_operand:QI 2 "register_operand" "a") (match_operand:DI 3 "immediate_operand" "i") (match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS)) (use (reg:SI DIRFLAG_REG)) (clobber (match_operand:DI 1 "register_operand" "=D")) (clobber (reg:CC FLAGS_REG))] However, at the time of sched1 pass (before reload) hard registers are not known yet. We have following RTL pattern just above "memory_to_string" call sequence (reg_notes are not shown for clarity): (insn 13 12 14 0 (parallel [ (set (reg:DI 63) (unspec:DI [ (mem:BLK (reg/f:DI 65 [ c_string ]) [0 A8]) (reg:QI 67) (const_int 1 [0x1]) (reg:DI 66) ] 20)) (use (reg:SI 19 dirflag)) (clobber (reg/f:DI 65 [ c_string ])) (clobber (reg:CC 17 flags)) ]) 511 {*strlenqi_rex_1} ad 3) Sched1 pass is free to move (insn 17) and (insn 18) before (insn 13) as it doesn't recognize register allocating conflicts between these instructions. Following that move, reload has no registers to spill and ICEs. The testcase from comment #3 ICEs with: error: unable to find a register to spill in class âAREGâ Here, the same problem could be observed. As "foo" is missing a prototype, hidden RAX register gets allocated in addition to RDI: (insn 20 18 21 0 (set (reg:DI 5 di) (reg:DI 61)) 81 {*movdi_1_rex64} (insn_list:REG_DEP_TRUE 18 (nil)) (expr_list:REG_DEAD (reg:DI 61) (nil))) (insn 21 20 22 0 (set (reg:QI 0 ax) (const_int 0 [0x0])) 55 {*movqi_1} (nil) (nil)) (call_insn 22 21 23 0 (set (reg:SI 0 ax) (call (mem:QI (symbol_ref:DI ("foo") [flags 0x41] <function_decl 0x402cbd80 foo>) [0 S1 A8]) (const_int 0 [0x0]))) 732 {*call_value_0_rex64} (insn_list:REG_DEP_TRUE 20 (insn_list:REG_DEP_TRUE 21 (nil))) (expr_list:REG_DEAD (reg:DI 5 di) (nil)) (expr_list:REG_DEP_TRUE (use (reg:QI 0 ax)) (expr_list:REG_DEP_TRUE (use (reg:DI 5 di)) (nil)))) This AX register is then moved before "strlenqi_rex_1" pattern and this blocks the AX register. (BTW: If prototype of "foo" is added, this particular testcase compiles OK.) One possible fix to this problem would be not to schedule instructions that have assigned hard registers (move insns in above case). Considering the number of x86 instructions, that require fixed registers I would suggest bugmasters to raise the priority of this bug. The x86 backend should not have these problems, but using -mregparm=X I think it could also be tricked to this sort of ICEs. (BTW: I have added Jim Wilson to CC of this bug as he is current maintaine of insn scheduling pass code. Perhaps he has some ideas on how to solve this problem.) -- uros at kss-loka dot si changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |wilson at gcc dot gnu dot | |org, uros at kss-loka dot si http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24319