aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Hayes <m.hayes@elec.canterbury.ac.nz>1999-09-03 23:58:44 +0000
committerMichael Hayes <m.hayes@gcc.gnu.org>1999-09-03 23:58:44 +0000
commit483dd5bec16a1a1acc2bc65f4f5fda522e67277d (patch)
treec34240021ac0fdbad1a2cc3daebac4be7ad0424d
parent3de900268edfcbeb0b286cc0119b778e1050a028 (diff)
downloadgcc-483dd5bec16a1a1acc2bc65f4f5fda522e67277d.zip
gcc-483dd5bec16a1a1acc2bc65f4f5fda522e67277d.tar.gz
gcc-483dd5bec16a1a1acc2bc65f4f5fda522e67277d.tar.bz2
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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/c4x/c4x.c37
-rw-r--r--gcc/config/c4x/c4x.h4
-rw-r--r--gcc/config/c4x/c4x.md136
4 files changed, 167 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f391242..2c509e3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c
index 35bd196..677c38c 100644
--- a/gcc/config/c4x/c4x.c
+++ b/gcc/config/c4x/c4x.c
@@ -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. */
diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h
index 2d019b5..14b0133 100644
--- a/gcc/config/c4x/c4x.h
+++ b/gcc/config/c4x/c4x.h
@@ -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 ();
diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md
index 7f1b0f3..3504bd3 100644
--- a/gcc/config/c4x/c4x.md
+++ b/gcc/config/c4x/c4x.md
@@ -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"