This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: PR target/16482: first scheduling pass on SH4
- From: Kaz Kojima <kkojima at rr dot iij4u dot or dot jp>
- To: tm_gccmail at kloo dot net
- Cc: gcc at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org, joern dot rennecke at st dot com, aoliva at redhat dot com, naveens at noida dot hcltech dot com
- Date: Fri, 15 Oct 2004 19:55:50 +0900 (JST)
- Subject: Re: PR target/16482: first scheduling pass on SH4
- References: <Pine.LNX.4.21.0410142001220.26875-100000@mail.kloo.net>
[I'd like to cc this message to gcc-patches and SH port maintainers
because it includes a patch anyway.]
tm_gccmail@kloo.net wrote:
>> Does the first insn scheduling for SH-4 take account of such insn which
>> uses R0 implicitly? Or is it a problem of the reload pass?
>
> The first instruction scheduling pass cannot extend the lifetime of
> pseudos which need r0 since there is only one r0 register.
>
> So yes, this sounds like an SH first instruction scheduling pass bug.
Thanks for your explanation. I've attached the patch which I mentioned
in http://gcc.gnu.org/ml/gcc/2004-10/msg00176.html, though it could be
overkill. It bootstraps on sh4-unknown-linux-gnu with no new regressions.
> Incidentally, I can reproduce the same problem with a small array index
> and -fPIC. Compile this with -O2 -mf -fPIC:
>
> int glob1;
>
> adrreg01limm1_set (float *p0)
> {
> p0[10] = (float) glob1;
> }
Wow, too simple :-) I've confirmed that the patch gets rid of the ICE
for it.
Regards,
kaz
--
* config/sh/sh.c (implicit_r0_use_block): New variable.
(may_use_r0_in_reload, find_implicit_r0_use): New.
(sh_md_init_global): Initialize and set implicit_r0_use_block.
(sh_md_finish_global): Cleanup implicit_r0_use_block if needed.
(implicit_r0_pressure): New.
(sh_reorder): Use implicit_r0_pressure.
(sh_reorder2): Likewise.
diff -uprN ORIG/gcc/gcc/config/sh/sh.c LOCAL/gcc/gcc/config/sh/sh.c
--- ORIG/gcc/gcc/config/sh/sh.c 2004-10-08 07:46:30.000000000 +0900
+++ LOCAL/gcc/gcc/config/sh/sh.c 2004-10-15 14:08:12.000000000 +0900
@@ -113,6 +113,10 @@ static short *regmode_weight[2];
/* Total SFmode and SImode weights of scheduled insns. */
static int curr_regmode_pressure[2];
+/* Array indexed by basic block index whose element shows that an insn in
+ this basic block may use r0 in reload. */
+static bool *implicit_r0_use_block;
+
/* If true, skip cycles for Q -> R movement. */
static int skip_cycles = 0;
@@ -8744,6 +8748,73 @@ find_regmode_weight (int b, enum machine
}
}
+/* Return true if the pattern may use r0 in reload. */
+static bool
+may_use_r0_in_reload (rtx x)
+{
+ /* The expression (mem (plus (reg) (reg))) may cause a reload with r0. */
+ if (GET_CODE (x) == SET)
+ {
+ rtx m;
+
+ if (GET_CODE (SET_SRC (x)) == MEM)
+ m = SET_SRC (x);
+ else if (GET_CODE (SET_DEST (x)) == MEM)
+ m = SET_DEST (x);
+ else
+ m = NULL_RTX;
+
+ if (m)
+ {
+ if (GET_CODE (XEXP (m, 0)) == PLUS)
+ {
+ rtx base = XEXP (XEXP (m, 0), 0);
+ rtx ofs = XEXP (XEXP (m, 0), 1);
+
+ if ((GET_CODE (base) == REG || GET_CODE (base) == SUBREG)
+ && (GET_CODE (ofs) == REG || GET_CODE (ofs) == SUBREG))
+ return true;
+ }
+ }
+ }
+
+ if (GET_CODE (x) == PARALLEL)
+ {
+ int j;
+ for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
+ {
+ rtx y = XVECEXP (x, 0, j);
+ if (may_use_r0_in_reload (y))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Set implicit_r0_use_block[B] if the basic block B includes an insn which
+ may use r0 in reload. */
+static void
+find_implicit_r0_use (int b)
+{
+ rtx insn, next_tail, head, tail;
+
+ get_block_head_tail (b, &head, &tail);
+ next_tail = NEXT_INSN (tail);
+
+ for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
+ {
+ if (!INSN_P (insn))
+ continue;
+
+ if (may_use_r0_in_reload (PATTERN (insn)))
+ {
+ implicit_r0_use_block[b] = true;
+ break;
+ }
+ }
+}
+
/* Comparison function for ready queue sorting. */
static int
rank_for_reorder (const void *x, const void *y)
@@ -8801,14 +8872,18 @@ sh_md_init_global (FILE *dump ATTRIBUTE_
int old_max_uid)
{
basic_block b;
+ int max_bb;
regmode_weight[0] = (short *) xcalloc (old_max_uid, sizeof (short));
regmode_weight[1] = (short *) xcalloc (old_max_uid, sizeof (short));
+ max_bb = VARRAY_SIZE (basic_block_info);
+ implicit_r0_use_block = (bool *) xcalloc (max_bb, sizeof (bool));
FOR_EACH_BB_REVERSE (b)
{
find_regmode_weight (b->index, SImode);
find_regmode_weight (b->index, SFmode);
+ find_implicit_r0_use (b->index);
}
CURR_REGMODE_PRESSURE (SImode) = 0;
@@ -8831,6 +8906,11 @@ sh_md_finish_global (FILE *dump ATTRIBUT
free (regmode_weight[1]);
regmode_weight[1] = NULL;
}
+ if (implicit_r0_use_block)
+ {
+ free (implicit_r0_use_block);
+ implicit_r0_use_block = NULL;
+ }
}
/* Cache the can_issue_more so that we can return it from reorder2. Also,
@@ -8890,6 +8970,20 @@ high_pressure (enum machine_mode mode)
return (CURR_REGMODE_PRESSURE (SImode) > SIMODE_MAX_WEIGHT);
}
+/* Return true if there is an insn which may use r0 in ready queue
+ and there is an explicit r0 use. */
+static bool
+implicit_r0_pressure (rtx *ready, int n ATTRIBUTE_UNUSED)
+{
+ return true;
+
+ if (REG_N_SETS (0) > 0
+ && implicit_r0_use_block[BLOCK_NUM (ready[0])])
+ return true;
+
+ return false;
+}
+
/* Reorder ready queue if register pressure is high. */
static int
sh_reorder (FILE *dump ATTRIBUTE_UNUSED,
@@ -8901,7 +8995,8 @@ sh_reorder (FILE *dump ATTRIBUTE_UNUSED,
if (reload_completed)
return sh_issue_rate ();
- if (high_pressure (SFmode) || high_pressure (SImode))
+ if (high_pressure (SFmode) || high_pressure (SImode)
+ || implicit_r0_pressure (ready, *n_readyp))
{
ready_reorder (ready, *n_readyp);
}
@@ -8920,7 +9015,8 @@ sh_reorder2 (FILE *dump ATTRIBUTE_UNUSED
if (reload_completed)
return cached_can_issue_more;
- if (high_pressure(SFmode) || high_pressure (SImode))
+ if (high_pressure (SFmode) || high_pressure (SImode)
+ || implicit_r0_pressure (ready, *n_readyp))
skip_cycles = 1;
return cached_can_issue_more;