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