c4x.c (c4x_emit_move_sequence): Do not force large constants into memory.

Sat Sep  4 11:37:15 1999  Michael Hayes  <m.hayes@elec.canterbury.ac.nz>

	* config/c4x/c4x.c (c4x_emit_move_sequence): Do not force large
	constants into memory.
	(c4x_shiftable_constant): New function.
	* config/c4x/c4x.c (LEGITIMATE_CONSTANT_P): Allow any CONST_INT.
	(c4x_shiftable_constant): Declare.
	* config/c4x/c4x.md (loadqi_big_constant, loadhi_big_constant,
 	ashlqi3_noclobber): Add new patterns and associated splitters.

From-SVN: r29092
This commit is contained in:
Michael Hayes 1999-09-03 23:58:44 +00:00 committed by Michael Hayes
parent 3de900268e
commit 483dd5bec1
4 changed files with 167 additions and 20 deletions

View File

@ -1,3 +1,13 @@
Sat Sep 4 11:37:15 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
* config/c4x/c4x.c (c4x_emit_move_sequence): Do not force large
constants into memory.
(c4x_shiftable_constant): New function.
* config/c4x/c4x.c (LEGITIMATE_CONSTANT_P): Allow any CONST_INT.
(c4x_shiftable_constant): Declare.
* config/c4x/c4x.md (loadqi_big_constant, loadhi_big_constant,
ashlqi3_noclobber): Add new patterns and associated splitters.
Fri Sep 3 16:22:17 1999 Richard Henderson <rth@cygnus.com>
* dbxout.c (dbxout_init): Use xcalloc instead of xmalloc+bzero.

View File

@ -1074,20 +1074,6 @@ c4x_emit_move_sequence (operands, mode)
constants... */
op1 = force_const_mem (mode, op1);
}
else if (mode == QImode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))
{
/* We shouldn't need this test if only emit_move_insn was called.
However, some routines call gen_move_insn which doesn't check that
the constants are legitimate. */
op1 = force_const_mem (mode, op1);
}
else if (mode == HImode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))
{
/* We could load all sorts of constants in two goes by pulling all
sorts of tricks... The tricky thing is that we cannot clobber CC
so that stifles most of the obvious methods. */
op1 = force_const_mem (mode, op1);
}
/* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF)))
and emit associated (HIGH (SYMREF)) if large memory model.
@ -2258,6 +2244,27 @@ c4x_immed_float_constant (op)
}
int
c4x_shiftable_constant (op)
rtx op;
{
int i;
int mask;
int val = INTVAL (op);
for (i = 0; i < 16; i++)
{
if (val & (1 << i))
break;
}
mask = ((0xffff >> i) << 16) | 0xffff;
if (IS_INT16_CONST (val & 0x80000000 ? (val >> i) | ~mask
: (val >> i) & mask))
return i;
return -1;
}
int
c4x_H_constant (op)
rtx op;
@ -2760,7 +2767,7 @@ reg_operand (op, mode)
int
mixed_subreg_operand (op, mode)
rtx op;
enum machine_mode mode;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
/* Allow (subreg:HF (reg:HI)) that be generated for a union of an
int and a long double. */

View File

@ -1675,7 +1675,7 @@ extern struct rtx_def *c4x_legitimize_reload_address ();
#define LEGITIMATE_CONSTANT_P(X) \
((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \
|| (GET_CODE (X) == CONST_INT && c4x_I_constant (X)) \
|| (GET_CODE (X) == CONST_INT) \
|| (GET_CODE (X) == SYMBOL_REF) \
|| (GET_CODE (X) == LABEL_REF) \
|| (GET_CODE (X) == CONST) \
@ -2750,6 +2750,8 @@ extern int not_rc_reg ();
extern int not_modify_reg ();
extern int c4x_shiftable_constant ();
extern int c4x_H_constant ();
extern int c4x_I_constant ();

View File

@ -1130,11 +1130,13 @@
"")
(define_split
[(set (match_operand:QI 0 "std_reg_operand" "")
[(set (match_operand:QI 0 "reg_operand" "")
(match_operand:QI 1 "const_int_operand" ""))]
"! TARGET_C3X
&& (INTVAL (operands[1]) & ~0xffff) != 0
&& (INTVAL (operands[1]) & 0xffff) != 0"
&& ! IS_INT16_CONST (INTVAL (operands[1]))
&& ! IS_HIGH_CONST (INTVAL (operands[1]))
&& reload_completed
&& std_reg_operand (operands[0], QImode)"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]
"
@ -1143,6 +1145,104 @@
operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);
}")
(define_split
[(set (match_operand:QI 0 "reg_operand" "")
(match_operand:QI 1 "const_int_operand" ""))]
"TARGET_C3X && ! TARGET_SMALL
&& ! IS_INT16_CONST (INTVAL (operands[1]))
&& reload_completed
&& std_reg_operand (operands[0], QImode)
&& c4x_shiftable_constant (operands[1]) < 0"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 4)))
(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]
"
{
/* Generate two's complement value of 16 MSBs. */
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(((INTVAL (operands[1]) >> 16) & 0xffff)
- 0x8000) ^ ~0x7fff);
operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);
operands[4] = gen_rtx (CONST_INT, VOIDmode, 16);
}")
(define_split
[(set (match_operand:QI 0 "reg_operand" "")
(match_operand:QI 1 "const_int_operand" ""))]
"TARGET_C3X
&& ! IS_INT16_CONST (INTVAL (operands[1]))
&& reload_completed
&& std_reg_operand (operands[0], QImode)
&& c4x_shiftable_constant (operands[1]) >= 0"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 3)))]
"
{
/* Generate two's complement value of MSBs. */
int shift = c4x_shiftable_constant (operands[1]);
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(((INTVAL (operands[1]) >> shift) & 0xffff)
- 0x8000) ^ ~0x7fff);
operands[3] = gen_rtx (CONST_INT, VOIDmode, shift);
}")
(define_split
[(set (match_operand:QI 0 "reg_operand" "")
(match_operand:QI 1 "const_int_operand" ""))]
"! TARGET_SMALL
&& ! IS_INT16_CONST (INTVAL (operands[1]))
&& ! IS_HIGH_CONST (INTVAL (operands[1]))
&& reload_completed
&& ! std_reg_operand (operands[0], QImode)"
[(set (match_dup 2) (high:QI (match_dup 3)))
(set (match_dup 0) (match_dup 4))
(use (match_dup 1))]
"
{
rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
operands[2] = dp_reg;
operands[3] = force_const_mem (Pmode, operands[1]);
operands[4] = change_address (operands[3], QImode,
gen_rtx_LO_SUM (Pmode, dp_reg,
XEXP (operands[3], 0)));
operands[3] = XEXP (operands[3], 0);
}")
(define_split
[(set (match_operand:QI 0 "reg_operand" "")
(match_operand:QI 1 "const_int_operand" ""))]
"TARGET_SMALL
&& ! IS_INT16_CONST (INTVAL (operands[1]))
&& ! IS_HIGH_CONST (INTVAL (operands[1]))
&& reload_completed
&& (TARGET_C3X && c4x_shiftable_constant (operands[1]) < 0
|| ! std_reg_operand (operands[0], QImode))"
[(set (match_dup 0) (match_dup 2))
(use (match_dup 1))]
"
{
rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
operands[2] = force_const_mem (Pmode, operands[1]);
operands[2] = change_address (operands[2], QImode,
gen_rtx_LO_SUM (Pmode, dp_reg,
XEXP (operands[2], 0)));
}")
(define_split
[(set (match_operand:HI 0 "reg_operand" "")
(match_operand:HI 1 "const_int_operand" ""))]
"reload_completed"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"
{
operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode);
operands[3] = c4x_operand_subword (operands[0], 1, 1, HImode);
operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode);
operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);
}")
; CC has been selected to load a symbolic address. We force the address
; into memory and then generate LDP and LDIU insns.
; This is also required for the C30 if we pretend that we can
@ -1189,7 +1289,14 @@
(define_insn "load_immed_address"
[(set (match_operand:QI 0 "reg_operand" "=a?x?c*r")
(match_operand:QI 1 "symbolic_address_operand" ""))]
"TARGET_LOAD_ADDRESS"
"TARGET_LOAD_ADDRESS"
"#"
[(set_attr "type" "multi")])
(define_insn "loadhi_big_constant"
[(set (match_operand:HI 0 "reg_operand" "=c*d")
(match_operand:HI 1 "const_int_operand" ""))]
""
"#"
[(set_attr "type" "multi")])
@ -1207,6 +1314,14 @@
"stik\\t%1,%0"
[(set_attr "type" "store")])
(define_insn "loadqi_big_constant"
[(set (match_operand:QI 0 "reg_operand" "=c*d")
(match_operand:QI 1 "const_int_operand" ""))]
"! IS_INT16_CONST (INTVAL (operands[1]))
&& ! IS_HIGH_CONST (INTVAL (operands[1]))"
"#"
[(set_attr "type" "multi")])
; We must provide an alternative to store to memory in case we have to
; spill a register.
(define_insn "movqi_noclobber"
@ -2516,6 +2631,19 @@
[(set_attr "type" "binarycc,binarycc,binarycc")])
; Default to int16 data attr.
(define_insn "ashlqi3_noclobber"
[(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c")
(ashift:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>")
(match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))]
"valid_operands (ASHIFT, operands, QImode)"
"@
ash\\t%2,%0
ash3\\t%2,%1,%0
ash3\\t%2,%1,%0"
[(set_attr "type" "binary,binary,binary")])
; Default to int16 data attr.
; This is only used by lshrhi3_reg where we need a LSH insn that will
; shift both ways.
(define_insn "*lshlqi3_clobber"