function.c fix for 920723-1.c ICE

Joseph S. Myers joseph@codesourcery.com
Fri Nov 17 13:14:00 GMT 2006


Testing on powerpc-none-linux-gnuspe --enable-e500_double shows an ICE on 
gcc.c-torture/compile/920723-1.c at -O0.  This is a regression from 4.0 
that is present in 4.1, 4.2 and mainline.

The analysis (dumps shown from the 4.1 toolchain) is thus.

920723-1.c:30: error: insn does not satisfy its constraints:
(insn 188 239 189 (set (reg:SI 211)
        (const_int 24512 [0x5fc0])) 234 {*movsi_internal1} (nil)
    (nil))
920723-1.c:30: internal compiler error: in extract_constrain_insn_cached, at recog.c:2011

(note that no hard register has been allocated here; we still have (reg:SI 
211))

Problems seem to appear much earlier, in the 07.vregs dump, where we have 
at the end of the dump

;; Insn is not within a basic block
(insn 188 181 189 (set (reg:SI 211)
        (const_int 24512 [0x5fc0])) 234 {*movsi_internal1} (nil)
    (nil))

among five such insns not in a basic block (indeed, the 4.3 testing gives 
the ICE at this point with "error: insn outside basic block").  The code 
using the registers set by these insns is somewhere else entirely, i.e. it 
appears they have not been inserted at the right point in the function.  
The insn in the .06.unshare dump the above appears to be part of the 
expansion of was

(insn 88 87 89 7 (set (reg:DF 171)
        (mem/c/i:DF (plus:SI (reg/f:SI 115 virtual-stack-vars)
                (const_int 90040 [0x15fb8])) [0 r+0 S8 A64])) -1 (nil)
    (nil))

which has become

(insn 88 187 89 7 (set (reg:DF 171)
        (reg:DF 210)) 916 {*movdf_e500_double} (nil)
    (nil))

(in its right place in the .07 dump) and

;; Insn is not within a basic block
(insn 188 181 189 (set (reg:SI 211)
        (const_int 24512 [0x5fc0])) 234 {*movsi_internal1} (nil)
    (nil))

;; Insn is not within a basic block
(insn 189 188 0 (set (reg:DF 210)
        (mem/c/i:DF (plus:SI (reg/f:SI 209)
                (reg:SI 211)) [0 r+0 S8 A64])) 916 {*movdf_e500_double} 
(nil)
    (nil))

at the end of the .07 dump (with (reg/f:SI 209) set up earlier:

(insn 187 87 88 7 (set (reg/f:SI 209)
        (plus:SI (reg/f:SI 113 sfp)
            (const_int 65536 [0x10000]))) -1 (nil)
    (nil))

).

Examination of the 07.vregs pass shows code that could generate such insns 
in the wrong place, leading to this patch to fix it.  Tested with no 
regressions with a cross to powerpc-none-linux-gnuspe, mainline, 4.2 and 
4.1.  Bootstrapped with no regressions on i686-pc-linux-gnu, mainline.  
OK to commit to mainline, 4.2, 4.1?

2006-11-16  Joseph Myers  <joseph@codesourcery.com>

	gcc/
	* function.c (instantiate_virtual_regs_in_insn): Call force_reg
	inside start_sequence / end_sequence pair.

Index: function.c
===================================================================
--- function.c	(revision 118892)
+++ function.c	(working copy)
@@ -1524,7 +1524,14 @@
 	 Validate the new value vs the insn predicate.  Note that
 	 asm insns will have insn_code -1 here.  */
       if (!safe_insn_predicate (insn_code, i, x))
-	x = force_reg (insn_data[insn_code].operand[i].mode, x);
+	{
+	  start_sequence ();
+	  x = force_reg (insn_data[insn_code].operand[i].mode, x);
+	  seq = get_insns ();
+	  end_sequence ();
+	  if (seq)
+	    emit_insn_before (seq, insn);
+	}
 
       *recog_data.operand_loc[i] = recog_data.operand[i] = x;
       any_change = true;

-- 
Joseph S. Myers
joseph@codesourcery.com



More information about the Gcc-patches mailing list