gcc 3.1/mips doesn't handle large stack frame.

H . J . Lu hjl@lucon.org
Thu Aug 16 08:27:00 GMT 2001


I found a large stack frame problem on Linux/mips:

# cat foo.i
static void
g(){}

f()
{
  int a[8189];

  g();
}
# gcc -O3 -S foo.i
foo.i: In function `f':
foo.i:10: Internal compiler error in propagate_one_insn, at flow.c:5312
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL: http://www.gnu.org/software/gcc/bugs.html > for instructions.

If I change it to

  int a[8188];

it works fine. You can configure gcc to mipsel-linux to see it for
yourselves. The problem is save_restore_insns in mips.c emits the
insn for the base register even if it is not used at all. It seems
to confuse propagate_one_insn in flow.c. I don't know what the right
way to fix it. But this patch seems to work for me.


H.J.
---
2001-08-16  H.J. Lu <hjl@gnu.org>

	* config/mips/mips.c (emit_base_reg_insn): New.
	(save_restore_insns): Call emit_base_reg_insn to emit the
	insn for the base register when we really use it.

--- gcc/config/mips/mips.c.base	Wed Aug 15 12:05:20 2001
+++ gcc/config/mips/mips.c	Wed Aug 15 13:16:15 2001
@@ -98,6 +98,8 @@ static void mips_emit_frame_related_stor
 							 HOST_WIDE_INT));
 static void save_restore_insns			PARAMS ((int, rtx,
 							long, FILE *));
+static void emit_base_reg_insn			PARAMS ((rtx, rtx,
+							FILE *));
 static void mips16_output_gp_offset		PARAMS ((FILE *, rtx));
 static void mips16_fp_args			PARAMS ((FILE *, int, int));
 static void build_mips16_function_stub		PARAMS ((FILE *));
@@ -6520,6 +6522,29 @@ mips_emit_frame_related_store (mem, reg,
 }
 
 static void
+emit_base_reg_insn (base_reg_rtx, large_reg, file)
+     rtx base_reg_rtx;
+     rtx large_reg;	/* register holding large offset constant or NULL */
+     FILE *file;	/* file to write instructions instead of making RTL */
+{
+  if (file == 0)
+    {
+      if (Pmode == DImode)
+	emit_insn (gen_adddi3 (base_reg_rtx, large_reg,
+				      stack_pointer_rtx));
+      else
+	emit_insn (gen_addsi3 (base_reg_rtx, large_reg,
+				      stack_pointer_rtx));
+    }
+  else
+    fprintf (file, "\t%s\t%s,%s,%s\n",
+	     Pmode == DImode ? "daddu" : "addu",
+	     reg_names[MIPS_TEMP2_REGNUM],
+	     reg_names[REGNO (large_reg)],
+	     reg_names[STACK_POINTER_REGNUM]);
+}
+
+static void
 save_restore_insns (store_p, large_reg, large_offset, file)
      int store_p;	/* true if this is prologue */
      rtx large_reg;	/* register holding large offset constant or NULL */
@@ -6530,6 +6555,7 @@ save_restore_insns (store_p, large_reg, 
   long fmask = current_frame_info.fmask;
   int regno;
   rtx base_reg_rtx;
+  int need_emit_base_reg_insn;
   HOST_WIDE_INT base_offset;
   HOST_WIDE_INT gp_offset;
   HOST_WIDE_INT fp_offset;
@@ -6557,6 +6583,7 @@ save_restore_insns (store_p, large_reg, 
 	 the constant created in the prologue/epilogue to adjust the stack
 	 frame.  */
 
+      need_emit_base_reg_insn = 0;
       gp_offset = current_frame_info.gp_sp_offset;
       end_offset
 	= gp_offset - (current_frame_info.gp_reg_size
@@ -6581,21 +6608,7 @@ save_restore_insns (store_p, large_reg, 
 	{
 	  base_reg_rtx = gen_rtx_REG (Pmode, MIPS_TEMP2_REGNUM);
 	  base_offset = large_offset;
-	  if (file == 0)
-	    {
-	      if (Pmode == DImode)
-		insn = emit_insn (gen_adddi3 (base_reg_rtx, large_reg,
-					      stack_pointer_rtx));
-	      else
-		insn = emit_insn (gen_addsi3 (base_reg_rtx, large_reg,
-					      stack_pointer_rtx));
-	    }
-	  else
-	    fprintf (file, "\t%s\t%s,%s,%s\n",
-		     Pmode == DImode ? "daddu" : "addu",
-		     reg_names[MIPS_TEMP2_REGNUM],
-		     reg_names[REGNO (large_reg)],
-		     reg_names[STACK_POINTER_REGNUM]);
+	  need_emit_base_reg_insn = 1;
 	}
       else
 	{
@@ -6654,11 +6667,26 @@ save_restore_insns (store_p, large_reg, 
 		  reg_rtx = gen_rtx (REG, gpr_mode, regno);
 
 		if (store_p)
-		  mips_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
+		  {
+		    if (need_emit_base_reg_insn)
+		      {
+		        emit_base_reg_insn (base_reg_rtx, large_reg,
+					    file);
+		        need_emit_base_reg_insn = 0;
+		      }
+		    mips_emit_frame_related_store (mem_rtx, reg_rtx,
+						   gp_offset);
+		  }
 		else if (!TARGET_ABICALLS
 			 || (mips_abi != ABI_32 && mips_abi != ABI_O64)
 			 || regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
 		  {
+		    if (need_emit_base_reg_insn)
+		      {
+		        emit_base_reg_insn (base_reg_rtx, large_reg,
+					    file);
+		        need_emit_base_reg_insn = 0;
+		      }
 		    emit_move_insn (reg_rtx, mem_rtx);
 		    if (TARGET_MIPS16
 			&& regno != GP_REG_FIRST + 31
@@ -6675,6 +6703,13 @@ save_restore_insns (store_p, large_reg, 
 		  {
 		    int r = regno;
 
+		    if (need_emit_base_reg_insn)
+		      {
+		        emit_base_reg_insn (base_reg_rtx, large_reg,
+					    file);
+		        need_emit_base_reg_insn = 0;
+		      }
+
 		    /* The mips16 does not have an instruction to
                        load $31, so we load $7 instead, and work
                        things out in the caller.  */
@@ -6723,6 +6758,8 @@ save_restore_insns (store_p, large_reg, 
       int fp_inc = (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) ? 1 : 2;
       int fp_size = fp_inc * UNITS_PER_FPREG;
 
+      need_emit_base_reg_insn = 0;
+
       /* Pick which pointer to use as a base register.  */
       fp_offset = current_frame_info.fp_sp_offset;
       end_offset = fp_offset - (current_frame_info.fp_reg_size - fp_size);
@@ -6746,22 +6783,7 @@ save_restore_insns (store_p, large_reg, 
 	{
 	  base_reg_rtx = gen_rtx_REG (Pmode, MIPS_TEMP2_REGNUM);
 	  base_offset = large_offset;
-	  if (file == 0)
-	    {
-	      if (Pmode == DImode)
-		insn = emit_insn (gen_adddi3 (base_reg_rtx, large_reg,
-					      stack_pointer_rtx));
-	      else
-		insn = emit_insn (gen_addsi3 (base_reg_rtx, large_reg,
-					      stack_pointer_rtx));
-	    }
-
-	  else
-	    fprintf (file, "\t%s\t%s,%s,%s\n",
-		     Pmode == DImode ? "daddu" : "addu",
-		     reg_names[MIPS_TEMP2_REGNUM],
-		     reg_names[REGNO (large_reg)],
-		     reg_names[STACK_POINTER_REGNUM]);
+	  need_emit_base_reg_insn = 1;
 	}
       else
 	{
@@ -6776,6 +6798,12 @@ save_restore_insns (store_p, large_reg, 
 	   regno -= fp_inc)
 	if (BITSET_P (fmask, regno - FP_REG_FIRST))
 	  {
+	    if (need_emit_base_reg_insn)
+	      {
+		emit_base_reg_insn (base_reg_rtx, large_reg, file);
+		need_emit_base_reg_insn = 0;
+	      }
+
 	    if (file == 0)
 	      {
 		enum machine_mode sz



More information about the Gcc-bugs mailing list