c4x.c (c4x_emit_move_sequence): Do not force large constants into memory.
authorMichael Hayes <m.hayes@elec.canterbury.ac.nz>
Fri, 3 Sep 1999 23:58:44 +0000 (23:58 +0000)
committerMichael Hayes <m.hayes@gcc.gnu.org>
Fri, 3 Sep 1999 23:58:44 +0000 (23:58 +0000)
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

gcc/ChangeLog
gcc/config/c4x/c4x.c
gcc/config/c4x/c4x.h
gcc/config/c4x/c4x.md

index f391242..2c509e3 100644 (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.
index 35bd196..677c38c 100644 (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.  
@@ -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.  */
index 2d019b5..14b0133 100644 (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 ();
index 7f1b0f3..3504bd3 100644 (file)
   "")
 
 (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)))]
   "
    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 
 (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")])
 
   "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"
   [(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"