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> 2004-06-10 Jason Merrill <jason@redhat.com>
* target.h (struct gcc_target): Change gimplify_va_arg_expr * target.h (struct gcc_target): Change gimplify_va_arg_expr
......
...@@ -200,7 +200,7 @@ static int branch_dest (rtx); ...@@ -200,7 +200,7 @@ static int branch_dest (rtx);
static void force_into (rtx, rtx); static void force_into (rtx, rtx);
static void print_slot (rtx); static void print_slot (rtx);
static rtx add_constant (rtx, enum machine_mode, 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 hi_const (rtx);
static int broken_move (rtx); static int broken_move (rtx);
static int mova_p (rtx); static int mova_p (rtx);
...@@ -2756,11 +2756,16 @@ add_constant (rtx x, enum machine_mode mode, rtx last_value) ...@@ -2756,11 +2756,16 @@ add_constant (rtx x, enum machine_mode mode, rtx last_value)
return lab; 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 static void
dump_table (rtx scan) dump_table (rtx start, rtx barrier)
{ {
rtx scan = barrier;
int i; int i;
int need_align = 1; int need_align = 1;
rtx lab, ref; rtx lab, ref;
...@@ -2795,6 +2800,20 @@ dump_table (rtx scan) ...@@ -2795,6 +2800,20 @@ dump_table (rtx scan)
need_align = 1; 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) if (TARGET_FMOVD && TARGET_ALIGN_DOUBLE && have_df)
{ {
rtx align_insn = NULL_RTX; rtx align_insn = NULL_RTX;
...@@ -2995,6 +3014,46 @@ mova_p (rtx insn) ...@@ -2995,6 +3014,46 @@ mova_p (rtx insn)
&& GET_CODE (XVECEXP (SET_SRC (PATTERN (insn)), 0, 0)) == LABEL_REF); && 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 /* 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 constant pool. If we can't find one, then create one near the end of
the range. */ the range. */
...@@ -3186,8 +3245,7 @@ find_barrier (int num_mova, rtx mova, rtx from) ...@@ -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 /* Try as we might, the leading mova is out of range. Change
it into a load (which will become a pcload) and retry. */ it into a load (which will become a pcload) and retry. */
SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0); fixup_mova (mova);
INSN_CODE (mova) = -1;
return find_barrier (0, 0, mova); return find_barrier (0, 0, mova);
} }
else else
...@@ -4099,7 +4157,20 @@ sh_reorg (void) ...@@ -4099,7 +4157,20 @@ sh_reorg (void)
{ {
if (mova_p (insn)) 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; mova = insn;
} }
else if (GET_CODE (insn) == JUMP_INSN else if (GET_CODE (insn) == JUMP_INSN
...@@ -4124,19 +4195,20 @@ sh_reorg (void) ...@@ -4124,19 +4195,20 @@ sh_reorg (void)
{ {
/* Change the mova into a load, and restart scanning /* Change the mova into a load, and restart scanning
there. broken_move will then return true for mova. */ there. broken_move will then return true for mova. */
SET_SRC (PATTERN (mova)) fixup_mova (mova);
= XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
INSN_CODE (mova) = -1;
insn = 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; rtx scan;
/* Scan ahead looking for a barrier to stick the constant table /* Scan ahead looking for a barrier to stick the constant table
behind. */ behind. */
rtx barrier = find_barrier (num_mova, mova, insn); rtx barrier = find_barrier (num_mova, mova, insn);
rtx last_float_move = NULL_RTX, last_float = 0, *last_float_addr = NULL; rtx last_float_move = NULL_RTX, last_float = 0, *last_float_addr = NULL;
int need_aligned_label = 0;
if (num_mova && ! mova_p (mova)) if (num_mova && ! mova_p (mova))
{ {
...@@ -4150,6 +4222,9 @@ sh_reorg (void) ...@@ -4150,6 +4222,9 @@ sh_reorg (void)
{ {
if (GET_CODE (scan) == CODE_LABEL) if (GET_CODE (scan) == CODE_LABEL)
last_float = 0; last_float = 0;
if (GET_CODE (scan) == INSN
&& recog_memoized (scan) == CODE_FOR_casesi_worker_2)
need_aligned_label = 1;
if (broken_move (scan)) if (broken_move (scan))
{ {
rtx *patp = &PATTERN (scan), pat = *patp; rtx *patp = &PATTERN (scan), pat = *patp;
...@@ -4180,7 +4255,6 @@ sh_reorg (void) ...@@ -4180,7 +4255,6 @@ sh_reorg (void)
} }
dst = gen_rtx_REG (HImode, REGNO (dst) + offset); dst = gen_rtx_REG (HImode, REGNO (dst) + offset);
} }
if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst))) if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst)))
{ {
/* This must be an insn that clobbers r0. */ /* This must be an insn that clobbers r0. */
...@@ -4257,7 +4331,7 @@ sh_reorg (void) ...@@ -4257,7 +4331,7 @@ sh_reorg (void)
INSN_CODE (scan) = -1; INSN_CODE (scan) = -1;
} }
} }
dump_table (barrier); dump_table (need_aligned_label ? insn : 0, barrier);
insn = barrier; insn = barrier;
} }
} }
......
...@@ -7110,7 +7110,7 @@ mov.l\\t1f,r0\\n\\ ...@@ -7110,7 +7110,7 @@ mov.l\\t1f,r0\\n\\
(clobber (match_dup 3))])] (clobber (match_dup 3))])]
"if (GET_CODE (operands[2]) == CODE_LABEL) LABEL_NUSES (operands[2])++;") "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") [(set (match_operand:SI 0 "register_operand" "=r,r")
(unspec:SI [(reg:SI R0_REG) (unspec:SI [(reg:SI R0_REG)
(match_operand:SI 1 "register_operand" "0,r") (match_operand:SI 1 "register_operand" "0,r")
...@@ -7140,6 +7140,44 @@ mov.l\\t1f,r0\\n\\ ...@@ -7140,6 +7140,44 @@ mov.l\\t1f,r0\\n\\
}" }"
[(set_attr "length" "4")]) [(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" (define_insn "casesi_shift_media"
[(set (match_operand:DI 0 "arith_reg_operand" "=r") [(set (match_operand:DI 0 "arith_reg_operand" "=r")
(ashift:DI (match_operand:DI 1 "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