Commit 483dd5be by Michael Hayes Committed by Michael Hayes

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
parent 3de90026
No preview for this file type
......@@ -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.
......@@ -2259,6 +2245,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. */
......
......@@ -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 ();
......
......@@ -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"
......
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