mcore-protos.h (mcore_r15_operand_p): Declare.

* config/mcore/mcore-protos.h (mcore_r15_operand_p): Declare.
	(mcore_secondary_reload_class): Declare.
	(mcore_output_inline_const_forced): Remove.
	* config/mcore/mcore.md (movsi): Remove the code that forced
	non-inlineable constants into a register if the target was r15
	or the stack pointer.  Remove constant restrictions from the main
	define_insn.  Remove r <- I, r <- M and r <- N alternatives in favor
	of an r <- P alternative.  Remove fallback define_insn for reload.
	(movhi, movqi): Use gen_lowpart rather than gen_SUBREG.  Remove reload
	define_insn.  Use mcore_output_move in the remaining define_insn.
	Adjust condition and constraints in the way as for movsi.
	(movdi): Always split unacceptable constants into two.  Use
	simplify_gen_subreg instead of operand_subword{,_force}.
	* config/mcore/mcore.c (mcore_output_inline_const_forced): Remove.
	(mcore_output_move): Support HImode and QImode moves as well.
	(mcore_m15_operand_p): New function.
	(mcore_reload_class): Use it to detect cases where LRW_REGS are better.
	(mcore_secondary_reload_class): New function.
	* config/mcore/mcore.h (SECONDARY_RELOAD_CLASS): Redefine in
	terms of mcore_secondary_reload_class.

From-SVN: r71330
This commit is contained in:
Richard Sandiford 2003-09-12 09:57:11 +00:00 committed by Richard Sandiford
parent 70b160738b
commit f0f4da3220
5 changed files with 110 additions and 326 deletions

View File

@ -1,3 +1,26 @@
2003-09-12 Richard Sandiford <rsandifo@redhat.com>
* config/mcore/mcore-protos.h (mcore_r15_operand_p): Declare.
(mcore_secondary_reload_class): Declare.
(mcore_output_inline_const_forced): Remove.
* config/mcore/mcore.md (movsi): Remove the code that forced
non-inlineable constants into a register if the target was r15
or the stack pointer. Remove constant restrictions from the main
define_insn. Remove r <- I, r <- M and r <- N alternatives in favor
of an r <- P alternative. Remove fallback define_insn for reload.
(movhi, movqi): Use gen_lowpart rather than gen_SUBREG. Remove reload
define_insn. Use mcore_output_move in the remaining define_insn.
Adjust condition and constraints in the way as for movsi.
(movdi): Always split unacceptable constants into two. Use
simplify_gen_subreg instead of operand_subword{,_force}.
* config/mcore/mcore.c (mcore_output_inline_const_forced): Remove.
(mcore_output_move): Support HImode and QImode moves as well.
(mcore_m15_operand_p): New function.
(mcore_reload_class): Use it to detect cases where LRW_REGS are better.
(mcore_secondary_reload_class): New function.
* config/mcore/mcore.h (SECONDARY_RELOAD_CLASS): Redefine in
terms of mcore_secondary_reload_class.
2003-09-11 Mike Stump <mrs@apple.com>
* c-lex.c (fe_file_change): Don't transform to_line with SOURCE_LINE.

View File

@ -65,6 +65,8 @@ extern void mcore_print_operand_address PARAMS ((FILE *, rtx));
extern void mcore_print_operand PARAMS ((FILE *, rtx, int));
extern rtx mcore_gen_compare_reg PARAMS ((RTX_CODE));
extern int mcore_symbolic_address_p PARAMS ((rtx));
extern bool mcore_r15_operand_p PARAMS ((rtx));
extern enum reg_class mcore_secondary_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx));
extern enum reg_class mcore_reload_class PARAMS ((rtx, enum reg_class));
extern int mcore_is_same_reg PARAMS ((rtx, rtx));
extern int mcore_arith_S_operand PARAMS ((rtx));
@ -72,7 +74,6 @@ extern int mcore_arith_S_operand PARAMS ((rtx));
#ifdef HAVE_MACHINE_MODES
extern const char * mcore_output_move PARAMS ((rtx, rtx *, enum machine_mode));
extern const char * mcore_output_movedouble PARAMS ((rtx *, enum machine_mode));
extern const char * mcore_output_inline_const_forced PARAMS ((rtx, rtx *, enum machine_mode));
extern int mcore_arith_reg_operand PARAMS ((rtx, enum machine_mode));
extern int mcore_general_movsrc_operand PARAMS ((rtx, enum machine_mode));
extern int mcore_general_movdst_operand PARAMS ((rtx, enum machine_mode));

View File

@ -1270,7 +1270,17 @@ mcore_output_move (insn, operands, mode)
if (GET_CODE (XEXP (src, 0)) == LABEL_REF)
return "lrw\t%0,[%1]"; /* a-R */
else
return "ldw\t%0,%1"; /* r-m */
switch (GET_MODE (src)) /* r-m */
{
case SImode:
return "ldw\t%0,%1";
case HImode:
return "ld.h\t%0,%1";
case QImode:
return "ld.b\t%0,%1";
default:
abort ();
}
}
else if (GET_CODE (src) == CONST_INT)
{
@ -1291,100 +1301,21 @@ mcore_output_move (insn, operands, mode)
return "lrw\t%0, %1"; /* Into the literal pool. */
}
else if (GET_CODE (dst) == MEM) /* m-r */
return "stw\t%1,%0";
switch (GET_MODE (dst))
{
case SImode:
return "stw\t%1,%0";
case HImode:
return "st.h\t%1,%0";
case QImode:
return "st.b\t%1,%0";
default:
abort ();
}
abort ();
}
/* Outputs a constant inline -- regardless of the cost.
Useful for things where we've gotten into trouble and think we'd
be doing an lrw into r15 (forbidden). This lets us get out of
that pickle even after register allocation. */
const char *
mcore_output_inline_const_forced (insn, operands, mode)
rtx insn ATTRIBUTE_UNUSED;
rtx operands[];
enum machine_mode mode ATTRIBUTE_UNUSED;
{
unsigned long value = INTVAL (operands[1]);
unsigned long ovalue = value;
struct piece
{
int low;
int shift;
}
part[6];
int i;
if (mcore_const_ok_for_inline (value))
return output_inline_const (SImode, operands);
for (i = 0; (unsigned) i < ARRAY_SIZE (part); i++)
{
part[i].shift = 0;
part[i].low = (value & 0x1F);
value -= part[i].low;
if (mcore_const_ok_for_inline (value))
break;
else
{
value >>= 5;
part[i].shift = 5;
while ((value & 1) == 0)
{
part[i].shift++;
value >>= 1;
}
if (mcore_const_ok_for_inline (value))
break;
}
}
/* 5 bits per iteration, a maximum of 5 times == 25 bits and leaves
7 bits left in the constant -- which we know we can cover with
a movi. The final value can't be zero otherwise we'd have stopped
in the previous iteration. */
if (value == 0 || ! mcore_const_ok_for_inline (value))
abort ();
/* Now, work our way backwards emitting the constant. */
/* Emit the value that remains -- it will be nonzero. */
operands[1] = GEN_INT (value);
output_asm_insn (output_inline_const (SImode, operands), operands);
while (i >= 0)
{
/* Shift anything we've already loaded. */
if (part[i].shift)
{
operands[2] = GEN_INT (part[i].shift);
output_asm_insn ("lsli %0,%2", operands);
value <<= part[i].shift;
}
/* Add anything we need into the low 5 bits. */
if (part[i].low != 0)
{
operands[2] = GEN_INT (part[i].low);
output_asm_insn ("addi %0,%2", operands);
value += part[i].low;
}
i--;
}
if (value != ovalue) /* sanity */
abort ();
/* We've output all the instructions. */
return "";
}
/* Return a sequence of instructions to perform DI or DF move.
Since the MCORE cannot move a DI or DF in one instruction, we have
to take care when we see overlapping source and dest registers. */
@ -3064,36 +2995,53 @@ mcore_reorg ()
}
/* Return true if X is something that can be moved directly into r15. */
bool
mcore_r15_operand_p (x)
rtx x;
{
switch (GET_CODE (x))
{
case CONST_INT:
return mcore_const_ok_for_inline (INTVAL (x));
case REG:
case SUBREG:
case MEM:
return 1;
default:
return 0;
}
}
/* Implement SECONDARY_RELOAD_CLASS. If CLASS contains r15, and we can't
directly move X into it, use r1-r14 as a temporary. */
enum reg_class
mcore_secondary_reload_class (class, mode, x)
enum reg_class class;
enum machine_mode mode ATTRIBUTE_UNUSED;
rtx x;
{
if (TEST_HARD_REG_BIT (reg_class_contents[class], 15)
&& !mcore_r15_operand_p (x))
return LRW_REGS;
return NO_REGS;
}
/* Return the reg_class to use when reloading the rtx X into the class
CLASS. */
/* If the input is (PLUS REG CONSTANT) representing a stack slot address,
then we want to restrict the class to LRW_REGS since that ensures that
will be able to safely load the constant.
If the input is a constant that should be loaded with mvir1, then use
ONLYR1_REGS.
??? We don't handle the case where we have (PLUS REG CONSTANT) and
the constant should be loaded with mvir1, because that can lead to cases
where an instruction needs two ONLYR1_REGS reloads. */
CLASS. If X is too complex to move directly into r15, prefer to
use LRW_REGS instead. */
enum reg_class
mcore_reload_class (x, class)
rtx x;
enum reg_class class;
{
enum reg_class new_class;
if (reg_class_subset_p (LRW_REGS, class) && !mcore_r15_operand_p (x))
return LRW_REGS;
if (class == GENERAL_REGS && CONSTANT_P (x)
&& (GET_CODE (x) != CONST_INT
|| ( ! CONST_OK_FOR_I (INTVAL (x))
&& ! CONST_OK_FOR_M (INTVAL (x))
&& ! CONST_OK_FOR_N (INTVAL (x)))))
new_class = LRW_REGS;
else
new_class = class;
return new_class;
return class;
}
/* Tell me if a pair of reg/subreg rtx's actually refer to the same

View File

@ -603,7 +603,8 @@ extern const enum reg_class reg_class_from_letter[];
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) NO_REGS
#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \
mcore_secondary_reload_class (CLASS, MODE, X)
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.

View File

@ -1226,101 +1226,20 @@
{
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SImode, operands[1]);
else if (CONSTANT_P (operands[1])
&& (GET_CODE (operands[1]) != CONST_INT
|| ( ! CONST_OK_FOR_I (INTVAL (operands[1]))
&& ! CONST_OK_FOR_M (INTVAL (operands[1]))
&& ! CONST_OK_FOR_N (INTVAL (operands[1]))
&& (! TARGET_HARDLIT ||
! mcore_const_ok_for_inline (INTVAL (operands[1])))))
&& ! reload_completed
&& ! reload_in_progress
&& GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
&& (REGNO (operands[0]) == STACK_POINTER_REGNUM
|| REGNO (operands[0]) == LK_REG))
operands[1] = force_reg (SImode, operands[1]);
}")
;;; Must put a/i before r/r so that it will be preferred when the dest is
;;; a hard register. Must put a/R before r/m.
;;; DO WE NEED a/i ANYMORE?
(define_insn ""
[(set (match_operand:SI 0 "mcore_general_movdst_operand" "=r,r,r,a,r,r,a,r,m")
(match_operand:SI 1 "mcore_general_movsrc_operand" "I,M,N,i,r,c,R,m,r"))]
[(set (match_operand:SI 0 "mcore_general_movdst_operand" "=r,r,a,r,a,r,m")
(match_operand:SI 1 "mcore_general_movsrc_operand" "r,P,i,c,R,m,r"))]
"(register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))
&& ! (CONSTANT_P (operands[1])
&& (GET_CODE (operands[1]) != CONST_INT
|| ( ! CONST_OK_FOR_I (INTVAL (operands[1]))
&& ! CONST_OK_FOR_M (INTVAL (operands[1]))
&& ! CONST_OK_FOR_N (INTVAL (operands[1]))))
&& GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
&& (REGNO (operands[0]) == STACK_POINTER_REGNUM
|| REGNO (operands[0]) == LK_REG))"
|| register_operand (operands[1], SImode))"
"* return mcore_output_move (insn, operands, SImode);"
[(set_attr "type" "move,move,move,move,move,move,load,load,store")])
[(set_attr "type" "move,move,move,move,load,load,store")])
;; This is to work around a bug in reload.
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "immediate_operand" "i"))]
"((reload_in_progress || reload_completed)
&& CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) == CONST_INT
&& ! CONST_OK_FOR_I (INTVAL (operands[1]))
&& ! CONST_OK_FOR_M (INTVAL (operands[1]))
&& ! CONST_OK_FOR_N (INTVAL (operands[1]))
&& GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) == LK_REG)"
"* return mcore_output_inline_const_forced (insn, operands, SImode);"
[(set_attr "type" "load")])
;; (define_expand "reload_insi"
;; [(parallel [(match_operand:SI 0 "register_operand" "=r")
;; (match_operand:SI 1 "general_operand" "")
;; (match_operand:DI 2 "register_operand" "=&r")])]
;; ""
;; "
;; {
;; if (CONSTANT_P (operands[1])
;; && GET_CODE (operands[1]) == CONST_INT
;; && ! CONST_OK_FOR_I (INTVAL (operands[1]))
;; && ! CONST_OK_FOR_M (INTVAL (operands[1]))
;; && ! CONST_OK_FOR_N (INTVAL (operands[1]))
;; && GET_CODE (operands[0]) == REG
;; && (REGNO (operands[0]) == STACK_POINTER_REGNUM
;; || REGNO (operands[0]) == LK_REG))
;; {
;; rtx tmp;
;;
;; if ( REGNO (operands[2]) == REGNO (operands[0])
;; || REGNO (operands[2]) == STACK_POINTER_REGNUM
;; || REGNO (operands[2]) == LK_REG)
;; tmp = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
;; else
;; tmp = gen_rtx_REG (SImode, REGNO (operands[2]));
;;
;; emit_insn (gen_movsi (tmp, operands[1]));
;; emit_insn (gen_movsi (operands[0], tmp));
;; DONE;
;; }
;; emit_insn (gen_movsi (operands[0], operands[1]));
;; DONE;
;; }"
;; )
;;
;; HImode
;;
;;; ??? This isn't guaranteed to work. It should be more like the SImode
;;; patterns.
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
@ -1338,73 +1257,17 @@
{
rtx reg = gen_reg_rtx (SImode);
emit_insn (gen_movsi (reg, operands[1]));
operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
operands[1] = gen_lowpart (HImode, reg);
}
}")
(define_insn ""
[(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,r,r,r,r,r,m")
(match_operand:HI 1 "mcore_general_movsrc_operand" "r,I,M,N,c,m,r"))]
[(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m")
(match_operand:HI 1 "mcore_general_movsrc_operand" "r,P,i,c,m,r"))]
"(register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))
&& (GET_CODE (operands[1]) != CONST_INT
|| CONST_OK_FOR_M (INTVAL (operands[1]))
|| CONST_OK_FOR_N (INTVAL (operands[1]))
|| CONST_OK_FOR_I (INTVAL (operands[1])))"
"@
mov %0,%1
movi %0,%1
bgeni %0,%P1
bmaski %0,%N1
mvc %0
ld.h %0,%1
st.h %1,%0"
[(set_attr "type" "move,move,move,move,move,load,store")])
;; Like movhi, but the const_int source can't be synthesized in
;; a single-instruction. Fall back to the same things that
;; are done for movsi in such cases. Presumes that we can
;; modify any parts of the register that we wish.
(define_insn ""
[(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,a")
(match_operand:HI 1 "const_int_operand" "P,i"))]
"GET_CODE (operands[1]) == CONST_INT
&& INTVAL (operands[1]) > 127 && INTVAL (operands[1]) < 65536"
"*
{
if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15
&& !mcore_const_ok_for_inline (INTVAL (operands[1])))
{
/* mcore_output_move would generate lrw r15 -- a forbidden combo */
return mcore_output_inline_const_forced (insn, operands, SImode);
}
else
return mcore_output_move (insn, operands, SImode);
}"
[(set_attr "type" "move")])
;; if we're still looking around for things to use, here's a last
;; ditch effort that just calls the move. We only let this happen
;; if we're in the reload pass.
;;
(define_insn ""
[(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,a")
(match_operand:HI 1 "const_int_operand" "P,i"))]
"reload_in_progress || reload_completed"
"*
{
if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15
&& !mcore_const_ok_for_inline (INTVAL (operands[1])))
{
/* mcore_output_move would generate lrw r15 -- a forbidden combo */
return mcore_output_inline_const_forced (insn, operands, SImode);
}
else
return mcore_output_move (insn, operands, HImode);
}"
[(set_attr "type" "move")])
|| register_operand (operands[1], HImode))"
"* return mcore_output_move (insn, operands, HImode);"
[(set_attr "type" "move,move,move,move,load,store")])
;;
;; QImode
@ -1427,67 +1290,18 @@
{
rtx reg = gen_reg_rtx (SImode);
emit_insn (gen_movsi (reg, operands[1]));
operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
operands[1] = gen_lowpart (QImode, reg);
}
}")
(define_insn ""
[(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,r,r,r,r,r,m")
(match_operand:QI 1 "mcore_general_movsrc_operand" "r,I,M,N,c,m,r"))]
[(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m")
(match_operand:QI 1 "mcore_general_movsrc_operand" "r,P,i,c,m,r"))]
"(register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))
&& (GET_CODE (operands[1]) != CONST_INT
|| CONST_OK_FOR_M (INTVAL (operands[1]))
|| CONST_OK_FOR_N (INTVAL (operands[1]))
|| CONST_OK_FOR_I (INTVAL (operands[1])))"
"@
mov %0,%1
movi %0,%1
bgeni %0,%P1
bmaski %0,%N1
mvc %0
ld.b %0,%1
st.b %1,%0"
[(set_attr "type" "move,move,move,move,move,load,store")])
|| register_operand (operands[1], QImode))"
"* return mcore_output_move (insn, operands, QImode);"
[(set_attr "type" "move,move,move,move,load,store")])
;; cover the case where the constant is 128..255; this isn't handled
;; in the above case. We could if we wanted to mess with adding a
;; new constraint class like M,N,I.
(define_insn ""
[(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r")
(match_operand:QI 1 "const_int_operand" ""))]
"GET_CODE (operands[1]) == CONST_INT
&& INTVAL (operands[1]) > 127 && INTVAL (operands[1]) < 256"
"*
{
/* have a constant in range 128..255; have to do 2 insns; we can
* do this with a movi followed by a bseti
*/
operands[2] = GEN_INT (INTVAL (operands[1]) & 0x7f);
return \"movi\\t%0,%2\;bseti\\t%0,7\";
}"
[(set_attr "type" "move")])
;; if we're still looking around for things to use, here's a last
;; ditch effort that just calls the move. We only let this happen
;; if we're in the reload pass.
;;
(define_insn ""
[(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,a")
(match_operand:QI 1 "const_int_operand" "P,i"))]
"(reload_in_progress || reload_completed)"
"*
{
if (GET_CODE (operands[0])== REG && REGNO (operands[0]) == 15
&& ! mcore_const_ok_for_inline (INTVAL (operands[1])))
{
/* mcore_output_move would generate lrw r15 -- a forbidden combo */
return mcore_output_inline_const_forced (insn, operands, SImode);
}
else
return mcore_output_move (insn, operands, QImode);
}"
[(set_attr "type" "move")])
;; DImode
@ -1502,15 +1316,12 @@
else if (GET_CODE (operands[1]) == CONST_INT
&& ! CONST_OK_FOR_I (INTVAL (operands[1]))
&& ! CONST_OK_FOR_M (INTVAL (operands[1]))
&& ! CONST_OK_FOR_N (INTVAL (operands[1]))
&& ! reload_completed
&& ! reload_in_progress
&& GET_CODE (operands[0]) == REG)
&& ! CONST_OK_FOR_N (INTVAL (operands[1])))
{
emit_move_insn (operand_subword (operands[0], 0, 1, DImode),
operand_subword_force (operands[1], 0, DImode));
emit_move_insn (operand_subword (operands[0], 1, 1, DImode),
operand_subword_force (operands[1], 1, DImode));
int i;
for (i = 0; i < UNITS_PER_WORD * 2; i += UNITS_PER_WORD)
emit_move_insn (simplify_gen_subreg (SImode, operands[0], DImode, i),
simplify_gen_subreg (SImode, operands[1], DImode, i));
DONE;
}
}")