Commit 078c8b08 by J"orn Rennecke Committed by Joern Rennecke

sh.c (dump_table): New argument start.

	* sh.c (dump_table): New argument start.  Changed caller.
	(fixup_mova): New function.
	(find_barrier): Use it.
	(sh_reorg): Likewise.  Check for CODE_FOR_casesi_worker_2.
	If the label a mova refers to is above the mova itself, change
	the mova into a load.
	* sh.md (*casesi_worker): Rename to:
	(casesi_worker_1).
	(casesi_worker_2): New insn.

From-SVN: r82932
parent 9ef313e3
2004-06-10 J"orn Rennecke <joern.rennecke@superh.com>
* sh.c (dump_table): New argument start. Changed caller.
(fixup_mova): New function.
(find_barrier): Use it.
(sh_reorg): Likewise. Check for CODE_FOR_casesi_worker_2.
If the label a mova refers to is above the mova itself, change
the mova into a load.
* sh.md (*casesi_worker): Rename to:
(casesi_worker_1).
(casesi_worker_2): New insn.
2004-06-10 Jason Merrill <jason@redhat.com>
* target.h (struct gcc_target): Change gimplify_va_arg_expr
......
......@@ -200,7 +200,7 @@ static int branch_dest (rtx);
static void force_into (rtx, rtx);
static void print_slot (rtx);
static rtx add_constant (rtx, enum machine_mode, rtx);
static void dump_table (rtx);
static void dump_table (rtx, rtx);
static int hi_const (rtx);
static int broken_move (rtx);
static int mova_p (rtx);
......@@ -2756,11 +2756,16 @@ add_constant (rtx x, enum machine_mode mode, rtx last_value)
return lab;
}
/* Output the literal table. */
/* Output the literal table. START, if nonzero, is the first instruction
this table is needed for, and also indicates that there is at least one
casesi_worker_2 instruction; We have to emit the operand3 labels from
these insns at a 4-byte aligned position. BARRIER is the barrier
after which we are to place the table. */
static void
dump_table (rtx scan)
dump_table (rtx start, rtx barrier)
{
rtx scan = barrier;
int i;
int need_align = 1;
rtx lab, ref;
......@@ -2795,6 +2800,20 @@ dump_table (rtx scan)
need_align = 1;
if (start)
{
scan = emit_insn_after (gen_align_4 (), scan);
need_align = 0;
for (; start != barrier; start = NEXT_INSN (start))
if (GET_CODE (start) == INSN
&& recog_memoized (start) == CODE_FOR_casesi_worker_2)
{
rtx src = SET_SRC (XVECEXP (PATTERN (start), 0, 0));
rtx lab = XEXP (XVECEXP (src, 0, 3), 0);
scan = emit_label_after (lab, scan);
}
}
if (TARGET_FMOVD && TARGET_ALIGN_DOUBLE && have_df)
{
rtx align_insn = NULL_RTX;
......@@ -2995,6 +3014,46 @@ mova_p (rtx insn)
&& GET_CODE (XVECEXP (SET_SRC (PATTERN (insn)), 0, 0)) == LABEL_REF);
}
/* Fix up a mova from a switch that went out of range. */
static void
fixup_mova (rtx mova)
{
if (! flag_pic)
{
SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
INSN_CODE (mova) = -1;
}
else
{
rtx worker = mova;
rtx lab = gen_label_rtx ();
rtx wpat, wpat0, wpat1, wsrc, diff;
do
{
worker = NEXT_INSN (worker);
if (! worker
|| GET_CODE (worker) == CODE_LABEL
|| GET_CODE (worker) == JUMP_INSN)
abort ();
} while (recog_memoized (worker) != CODE_FOR_casesi_worker_1);
wpat = PATTERN (worker);
wpat0 = XVECEXP (wpat, 0, 0);
wpat1 = XVECEXP (wpat, 0, 1);
wsrc = SET_SRC (wpat0);
PATTERN (worker) = (gen_casesi_worker_2
(SET_DEST (wpat0), XVECEXP (wsrc, 0, 1),
XEXP (XVECEXP (wsrc, 0, 2), 0), lab,
XEXP (wpat1, 0)));
INSN_CODE (worker) = -1;
diff = gen_rtx_MINUS (Pmode, XVECEXP (SET_SRC (PATTERN (mova)), 0, 0),
gen_rtx_LABEL_REF (Pmode, lab));
diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, diff), UNSPEC_PIC);
SET_SRC (PATTERN (mova)) = gen_rtx_CONST (Pmode, diff);
INSN_CODE (mova) = -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. */
......@@ -3186,8 +3245,7 @@ find_barrier (int num_mova, rtx mova, rtx from)
{
/* Try as we might, the leading mova is out of range. Change
it into a load (which will become a pcload) and retry. */
SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
INSN_CODE (mova) = -1;
fixup_mova (mova);
return find_barrier (0, 0, mova);
}
else
......@@ -4099,7 +4157,20 @@ sh_reorg (void)
{
if (mova_p (insn))
{
if (! num_mova++)
/* ??? basic block reordering can move a switch table dispatch
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)))))
{
/* Change the mova into a load.
broken_move will then return true for it. */
fixup_mova (insn);
}
else if (! num_mova++)
mova = insn;
}
else if (GET_CODE (insn) == JUMP_INSN
......@@ -4124,19 +4195,20 @@ sh_reorg (void)
{
/* Change the mova into a load, and restart scanning
there. broken_move will then return true for mova. */
SET_SRC (PATTERN (mova))
= XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
INSN_CODE (mova) = -1;
fixup_mova (mova);
insn = mova;
}
}
if (broken_move (insn))
if (broken_move (insn)
|| (GET_CODE (insn) == INSN
&& recog_memoized (insn) == CODE_FOR_casesi_worker_2))
{
rtx scan;
/* Scan ahead looking for a barrier to stick the constant table
behind. */
rtx barrier = find_barrier (num_mova, mova, insn);
rtx last_float_move = NULL_RTX, last_float = 0, *last_float_addr = NULL;
int need_aligned_label = 0;
if (num_mova && ! mova_p (mova))
{
......@@ -4150,6 +4222,9 @@ sh_reorg (void)
{
if (GET_CODE (scan) == CODE_LABEL)
last_float = 0;
if (GET_CODE (scan) == INSN
&& recog_memoized (scan) == CODE_FOR_casesi_worker_2)
need_aligned_label = 1;
if (broken_move (scan))
{
rtx *patp = &PATTERN (scan), pat = *patp;
......@@ -4180,7 +4255,6 @@ sh_reorg (void)
}
dst = gen_rtx_REG (HImode, REGNO (dst) + offset);
}
if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst)))
{
/* This must be an insn that clobbers r0. */
......@@ -4257,7 +4331,7 @@ sh_reorg (void)
INSN_CODE (scan) = -1;
}
}
dump_table (barrier);
dump_table (need_aligned_label ? insn : 0, barrier);
insn = barrier;
}
}
......
......@@ -7110,7 +7110,7 @@ mov.l\\t1f,r0\\n\\
(clobber (match_dup 3))])]
"if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;")
(define_insn "*casesi_worker"
(define_insn "casesi_worker_1"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(unspec:SI [(reg:SI R0_REG)
(match_operand:SI 1 "register_operand" "0,r")
......@@ -7140,6 +7140,44 @@ mov.l\\t1f,r0\\n\\
}"
[(set_attr "length" "4")])
(define_insn "casesi_worker_2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(unspec:SI [(reg:SI R0_REG)
(match_operand:SI 1 "register_operand" "0,r")
(label_ref (match_operand 2 "" ""))
(label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))
(clobber (match_operand:SI 4 "" "=X,1"))]
"TARGET_SH2 && reload_completed && flag_pic"
"*
{
rtx diff_vec = PATTERN (next_real_insn (operands[2]));
char *load;
if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
abort ();
switch (GET_MODE (diff_vec))
{
case SImode:
output_asm_insn (\"shll2 %1\", operands);
load = \"mov.l @(r0,%1),%0\"; break;
case HImode:
output_asm_insn (\"add %1,%1\", operands);
load = \"mov.w @(r0,%1),%0\"; break;
case QImode:
if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
load = \"mov.b @(r0,%1),%0\;extu.b %0,%0\";
else
load = \"mov.b @(r0,%1),%0\";
break;
default:
abort ();
}
output_asm_insn (\"add\tr0,%1\;mova\t%O3,r0\\n\", operands);
return load;
}"
[(set_attr "length" "8")])
(define_insn "casesi_shift_media"
[(set (match_operand:DI 0 "arith_reg_operand" "=r")
(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment