This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patches applied to sh.c: fix mova handling during sh_reorg
- From: Joern RENNECKE <joern dot rennecke at st dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 17 Mar 2006 14:31:03 +0000
- Subject: Patches applied to sh.c: fix mova handling during sh_reorg
Regression tested on i686-pc-linux-gnu X sh-elf.
2005-06-02 J"orn Rennecke <joern.rennecke@st.com>
* sh.c (max_labelno_before_reorg): New variable.
(sh_reorg): Initialize it.
(find_barrier): Check max_labelno_before_reorg before using
label_to_alignment. Take length of explicit alignment insns
into account. When seeing a UNSPECV_CONST_END, return it.
* sh.c (fixup_mova): Set mode of affected label to QImode.
(untangle_mova): New function.
(find_barrier): Use it. Check mode of label before decrementing
num_mova.
(sh_reorg): Likewise.
Set mode of all insns back to VOIDmode.
* sh.c (MOVA_LABELREF): New macro.
(mova_p, fixup_mova, sh_reorg): Use it.
(find_barrier, sh_reorg): Don't count num_mova back to 0 unless
ADDR_DIFF_VEC matches mova.
Index: sh.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L sh.c (revision 112083) -L sh.c (working copy) .svn/text-base/sh.c.svn-base sh.c
--- sh.c (revision 112083)
+++ sh.c (working copy)
@@ -3048,6 +3048,8 @@ static int pool_size;
static rtx pool_window_label;
static int pool_window_last;
+static int max_labelno_before_reorg;
+
/* ??? If we need a constant in HImode which is the truncated value of a
constant we need in SImode, we could combine the two entries thus saving
two bytes. Is this common enough to be worth the effort of implementing
@@ -3332,6 +3334,8 @@ hi_const (rtx src)
&& INTVAL (src) <= 32767);
}
+#define MOVA_LABELREF(mova) XVECEXP (SET_SRC (PATTERN (mova)), 0, 0)
+
/* Nonzero if the insn is a move instruction which needs to be fixed. */
/* ??? For a DImode/DFmode moves, we don't need to fix it if each half of the
@@ -3391,16 +3395,17 @@ mova_p (rtx insn)
&& GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC
&& XINT (SET_SRC (PATTERN (insn)), 1) == UNSPEC_MOVA
/* Don't match mova_const. */
- && GET_CODE (XVECEXP (SET_SRC (PATTERN (insn)), 0, 0)) == LABEL_REF);
+ && GET_CODE (MOVA_LABELREF (insn)) == LABEL_REF);
}
/* Fix up a mova from a switch that went out of range. */
static void
fixup_mova (rtx mova)
{
+ PUT_MODE (XEXP (MOVA_LABELREF (mova), 0), QImode);
if (! flag_pic)
{
- SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
+ SET_SRC (PATTERN (mova)) = MOVA_LABELREF (mova);
INSN_CODE (mova) = -1;
}
else
@@ -3434,6 +3439,53 @@ fixup_mova (rtx mova)
}
}
+/* NEW_MOVA is a mova we've just encountered while scanning forward. Update
+ *num_mova, and check if the new mova is not nested within the first one.
+ return 0 if *first_mova was replaced, 1 if new_mova was replaced,
+ 2 if new_mova has been assigned to *first_mova, -1 otherwise.. */
+static int
+untangle_mova (int *num_mova, rtx *first_mova, rtx new_mova)
+{
+ int n_addr;
+ int f_target, n_target;
+
+ if (optimize)
+ {
+ n_addr = INSN_ADDRESSES (INSN_UID (new_mova));
+ n_target = INSN_ADDRESSES (INSN_UID (XEXP (MOVA_LABELREF (new_mova), 0)));
+ if (n_addr > n_target || n_addr + 1022 < n_target)
+ {
+ /* Change the mova into a load.
+ broken_move will then return true for it. */
+ fixup_mova (new_mova);
+ return 1;
+ }
+ }
+ if (!(*num_mova)++)
+ {
+ *first_mova = new_mova;
+ return 2;
+ }
+ if (!optimize
+ || ((f_target
+ = INSN_ADDRESSES (INSN_UID (XEXP (MOVA_LABELREF (*first_mova), 0))))
+ >= n_target))
+ return -1;
+
+ (*num_mova)--;
+ if (f_target - INSN_ADDRESSES (INSN_UID (*first_mova))
+ > n_target - n_addr)
+ {
+ fixup_mova (*first_mova);
+ return 0;
+ }
+ else
+ {
+ fixup_mova (new_mova);
+ return 1;
+ }
+}
+
/* Find the last barrier from insn FROM which is close enough to hold the
constant pool. If we can't find one, then create one near the end of
the range. */
@@ -3477,7 +3529,12 @@ find_barrier (int num_mova, rtx mova, rt
int inc = get_attr_length (from);
int new_align = 1;
- if (GET_CODE (from) == CODE_LABEL)
+ /* If this is a label that existed at the time of the compute_alignments
+ call, determine the alignment. N.B. When find_barrier recurses for
+ an out-of-reach mova, we might see labels at the start of previously
+ inserted constant tables. */
+ if (GET_CODE (from) == CODE_LABEL
+ && CODE_LABEL_NUMBER (from) <= max_labelno_before_reorg)
{
if (optimize)
new_align = 1 << label_to_alignment (from);
@@ -3487,6 +3544,22 @@ find_barrier (int num_mova, rtx mova, rt
new_align = 1;
inc = 0;
}
+ /* In case we are scanning a constant table because of recursion, check
+ for explicit alignments. If the table is long, we might be forced
+ to emit the new table in front of it; the length of the alignment
+ might be the last straw. */
+ else if (GET_CODE (from) == INSN
+ && GET_CODE (PATTERN (from)) == UNSPEC_VOLATILE
+ && XINT (PATTERN (from), 1) == UNSPECV_ALIGN)
+ new_align = INTVAL (XVECEXP (PATTERN (from), 0, 0));
+ /* When we find the end of a constant table, paste the new constant
+ at the end. That is better than putting it in front because
+ this way, we don't need extra alignment for adding a 4-byte-aligned
+ mov(a) label to a 2/4 or 8/4 byte aligned table. */
+ else if (GET_CODE (from) == INSN
+ && GET_CODE (PATTERN (from)) == UNSPEC_VOLATILE
+ && XINT (PATTERN (from), 1) == UNSPECV_CONST_END)
+ return from;
if (GET_CODE (from) == BARRIER)
{
@@ -3551,11 +3624,16 @@ find_barrier (int num_mova, rtx mova, rt
if (mova_p (from))
{
- if (! num_mova++)
+ switch (untangle_mova (&num_mova, &mova, from))
{
- leading_mova = 0;
- mova = from;
- barrier_before_mova = good_barrier ? good_barrier : found_barrier;
+ case 0: return find_barrier (0, 0, mova);
+ case 2:
+ {
+ leading_mova = 0;
+ barrier_before_mova
+ = good_barrier ? good_barrier : found_barrier;
+ }
+ default: break;
}
if (found_si > count_si)
count_si = found_si;
@@ -3564,7 +3642,10 @@ find_barrier (int num_mova, rtx mova, rt
&& (GET_CODE (PATTERN (from)) == ADDR_VEC
|| GET_CODE (PATTERN (from)) == ADDR_DIFF_VEC))
{
- if (num_mova)
+ if ((num_mova > 1 && GET_MODE (prev_nonnote_insn (from)) == VOIDmode)
+ || (num_mova
+ && (prev_nonnote_insn (from)
+ == XEXP (MOVA_LABELREF (mova), 0))))
num_mova--;
if (barrier_align (next_real_insn (from)) == align_jumps_log)
{
@@ -4284,6 +4365,7 @@ sh_reorg (void)
rtx r0_inc_rtx = gen_rtx_POST_INC (Pmode, r0_rtx);
first = get_insns ();
+ max_labelno_before_reorg = max_label_num ();
/* We must split call insns before introducing `mova's. If we're
optimizing, they'll have already been split. Otherwise, make
@@ -4545,21 +4627,23 @@ sh_reorg (void)
below the switch table. Check if that has happened.
We only have the addresses available when optimizing; but then,
this check shouldn't be needed when not optimizing. */
- rtx label_ref = XVECEXP (SET_SRC (PATTERN (insn)), 0, 0);
- if (optimize
- && (INSN_ADDRESSES (INSN_UID (insn))
- > INSN_ADDRESSES (INSN_UID (XEXP (label_ref, 0)))))
+ if (!untangle_mova (&num_mova, &mova, insn))
{
- /* Change the mova into a load.
- broken_move will then return true for it. */
- fixup_mova (insn);
+ insn = mova;
+ num_mova = 0;
}
- else if (! num_mova++)
- mova = insn;
}
else if (GET_CODE (insn) == JUMP_INSN
&& GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
- && num_mova)
+ && num_mova
+ /* ??? loop invariant motion can also move a mova out of a
+ loop. Since loop does this code motion anyway, maybe we
+ should wrap UNSPEC_MOVA into a CONST, so that reload can
+ move it back. */
+ && ((num_mova > 1
+ && GET_MODE (prev_nonnote_insn (insn)) == VOIDmode)
+ || (prev_nonnote_insn (insn)
+ == XEXP (MOVA_LABELREF (mova), 0))))
{
rtx scan;
int total;
@@ -4717,7 +4801,9 @@ sh_reorg (void)
}
}
free_alloc_pool (label_ref_list_pool);
-
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ PUT_MODE (insn, VOIDmode);
+
mdep_reorg_phase = SH_SHORTEN_BRANCHES1;
INSN_ADDRESSES_FREE ();
split_branches (first);