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:
parent
3de900268e
commit
483dd5bec1
4 changed files with 167 additions and 20 deletions
|
@ -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>
|
Fri Sep 3 16:22:17 1999 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
* dbxout.c (dbxout_init): Use xcalloc instead of xmalloc+bzero.
|
* dbxout.c (dbxout_init): Use xcalloc instead of xmalloc+bzero.
|
||||||
|
|
|
@ -1074,20 +1074,6 @@ c4x_emit_move_sequence (operands, mode)
|
||||||
constants... */
|
constants... */
|
||||||
op1 = force_const_mem (mode, op1);
|
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)))
|
/* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF)))
|
||||||
and emit associated (HIGH (SYMREF)) if large memory model.
|
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
|
int
|
||||||
c4x_H_constant (op)
|
c4x_H_constant (op)
|
||||||
rtx op;
|
rtx op;
|
||||||
|
@ -2760,7 +2767,7 @@ reg_operand (op, mode)
|
||||||
int
|
int
|
||||||
mixed_subreg_operand (op, mode)
|
mixed_subreg_operand (op, mode)
|
||||||
rtx op;
|
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
|
/* Allow (subreg:HF (reg:HI)) that be generated for a union of an
|
||||||
int and a long double. */
|
int and a long double. */
|
||||||
|
|
|
@ -1675,7 +1675,7 @@ extern struct rtx_def *c4x_legitimize_reload_address ();
|
||||||
|
|
||||||
#define LEGITIMATE_CONSTANT_P(X) \
|
#define LEGITIMATE_CONSTANT_P(X) \
|
||||||
((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (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) == SYMBOL_REF) \
|
||||||
|| (GET_CODE (X) == LABEL_REF) \
|
|| (GET_CODE (X) == LABEL_REF) \
|
||||||
|| (GET_CODE (X) == CONST) \
|
|| (GET_CODE (X) == CONST) \
|
||||||
|
@ -2750,6 +2750,8 @@ extern int not_rc_reg ();
|
||||||
|
|
||||||
extern int not_modify_reg ();
|
extern int not_modify_reg ();
|
||||||
|
|
||||||
|
extern int c4x_shiftable_constant ();
|
||||||
|
|
||||||
extern int c4x_H_constant ();
|
extern int c4x_H_constant ();
|
||||||
|
|
||||||
extern int c4x_I_constant ();
|
extern int c4x_I_constant ();
|
||||||
|
|
|
@ -1130,11 +1130,13 @@
|
||||||
"")
|
"")
|
||||||
|
|
||||||
(define_split
|
(define_split
|
||||||
[(set (match_operand:QI 0 "std_reg_operand" "")
|
[(set (match_operand:QI 0 "reg_operand" "")
|
||||||
(match_operand:QI 1 "const_int_operand" ""))]
|
(match_operand:QI 1 "const_int_operand" ""))]
|
||||||
"! TARGET_C3X
|
"! TARGET_C3X
|
||||||
&& (INTVAL (operands[1]) & ~0xffff) != 0
|
&& ! IS_INT16_CONST (INTVAL (operands[1]))
|
||||||
&& (INTVAL (operands[1]) & 0xffff) != 0"
|
&& ! 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) (match_dup 2))
|
||||||
(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]
|
(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);
|
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
|
; CC has been selected to load a symbolic address. We force the address
|
||||||
; into memory and then generate LDP and LDIU insns.
|
; into memory and then generate LDP and LDIU insns.
|
||||||
; This is also required for the C30 if we pretend that we can
|
; This is also required for the C30 if we pretend that we can
|
||||||
|
@ -1189,7 +1289,14 @@
|
||||||
(define_insn "load_immed_address"
|
(define_insn "load_immed_address"
|
||||||
[(set (match_operand:QI 0 "reg_operand" "=a?x?c*r")
|
[(set (match_operand:QI 0 "reg_operand" "=a?x?c*r")
|
||||||
(match_operand:QI 1 "symbolic_address_operand" ""))]
|
(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")])
|
[(set_attr "type" "multi")])
|
||||||
|
|
||||||
|
@ -1207,6 +1314,14 @@
|
||||||
"stik\\t%1,%0"
|
"stik\\t%1,%0"
|
||||||
[(set_attr "type" "store")])
|
[(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
|
; We must provide an alternative to store to memory in case we have to
|
||||||
; spill a register.
|
; spill a register.
|
||||||
(define_insn "movqi_noclobber"
|
(define_insn "movqi_noclobber"
|
||||||
|
@ -2516,6 +2631,19 @@
|
||||||
[(set_attr "type" "binarycc,binarycc,binarycc")])
|
[(set_attr "type" "binarycc,binarycc,binarycc")])
|
||||||
; Default to int16 data attr.
|
; 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
|
; This is only used by lshrhi3_reg where we need a LSH insn that will
|
||||||
; shift both ways.
|
; shift both ways.
|
||||||
(define_insn "*lshlqi3_clobber"
|
(define_insn "*lshlqi3_clobber"
|
||||||
|
|
Loading…
Add table
Reference in a new issue