OSDN Git Service

* arm.c (arm_override_options): Use arm_ld_sched rather than testing
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 20 Nov 2004 11:21:55 +0000 (11:21 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 20 Nov 2004 11:21:55 +0000 (11:21 +0000)
a bit in tune_flags.
(const_double_needs_minipool): Likewise.  Split most of the code out
into ...
(arm_const_double_inline_cost): ... new function here.
* arm-protos.h (arm_const_double_inline_cost): Add prototype.
* arm.h (EXTRA_CONSTRAINT_STR_ARM): Add D[abc] constraints for double-
word constants of length 2, 3 and 4 insns respectively.
(CONSTRAINT_LEN): The 'D' prefix is a 2-letter constraint.
* arm.md (arm_movdi, movdf_soft_insn): Add alternatives for D[abc]
constraints.  Set insn lenghts accordingly.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@90962 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/arm.md

index 4ad29a7..361a031 100644 (file)
@@ -1,3 +1,17 @@
+2004-11-20  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm.c (arm_override_options): Use arm_ld_sched rather than testing
+       a bit in tune_flags.
+       (const_double_needs_minipool): Likewise.  Split most of the code out
+       into ...
+       (arm_const_double_inline_cost): ... new function here.
+       * arm-protos.h (arm_const_double_inline_cost): Add prototype.
+       * arm.h (EXTRA_CONSTRAINT_STR_ARM): Add D[abc] constraints for double-
+       word constants of length 2, 3 and 4 insns respectively.
+       (CONSTRAINT_LEN): The 'D' prefix is a 2-letter constraint.
+       * arm.md (arm_movdi, movdf_soft_insn): Add alternatives for D[abc]
+       constraints.  Set insn lenghts accordingly.
+
 2004-11-19  Kazu Hirata  <kazu@cs.umass.edu>
 
        * basic-block.h (edge_def): Add dest_idx.
index 44a259f..c46ce82 100644 (file)
@@ -89,6 +89,7 @@ extern rtx arm_gen_compare_reg (RTX_CODE, rtx, rtx);
 extern rtx arm_gen_return_addr_mask (void);
 extern void arm_reload_in_hi (rtx *);
 extern void arm_reload_out_hi (rtx *);
+extern int arm_const_double_inline_cost (rtx);
 extern const char *fp_immediate_constant (rtx);
 extern const char *output_call (rtx *);
 extern const char *output_call_mem (rtx *);
index 192fdb4..0667613 100644 (file)
@@ -1163,7 +1163,7 @@ arm_override_options (void)
       /* For processors with load scheduling, it never costs more than
          2 cycles to load a constant, and the load scheduler may well
         reduce that to 1.  */
-      if (tune_flags & FL_LDSCHED)
+      if (arm_ld_sched)
         arm_constant_limit = 1;
 
       /* On XScale the longer latency of a load makes it more difficult
@@ -7258,43 +7258,52 @@ push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx *loc,
   minipool_fix_tail = fix;
 }
 
-/* Determine if a CONST_DOUBLE should be pushed to the minipool */
-static bool
-const_double_needs_minipool (rtx val)
+/* Return the cost of synthesising the const_double VAL inline.
+   Returns the number of insns needed, or 99 if we don't know how to
+   do it.  */
+int
+arm_const_double_inline_cost (rtx val)
 {
   long parts[2];
-
-  /* thumb only knows to load a CONST_DOUBLE from memory at the moment */
-  if (TARGET_THUMB)
-    return true;
-
+  
   if (GET_MODE (val) == DFmode)
     {
       REAL_VALUE_TYPE r;
       if (!TARGET_SOFT_FLOAT)
-       return true;
+       return 99;
       REAL_VALUE_FROM_CONST_DOUBLE (r, val);
       REAL_VALUE_TO_TARGET_DOUBLE (r, parts);
     }
   else if (GET_MODE (val) != VOIDmode)
-    return true;
+    return 99;
   else
     {
       parts[0] = CONST_DOUBLE_LOW (val);
       parts[1] = CONST_DOUBLE_HIGH (val);
     }
 
+  return (arm_gen_constant (SET, SImode, NULL_RTX, parts[0],
+                           NULL_RTX, NULL_RTX, 0, 0)
+         + arm_gen_constant (SET, SImode, NULL_RTX, parts[1],
+                             NULL_RTX, NULL_RTX, 0, 0));
+}
+
+/* Determine if a CONST_DOUBLE should be pushed to the minipool */
+static bool
+const_double_needs_minipool (rtx val)
+{
+  /* thumb only knows to load a CONST_DOUBLE from memory at the moment */
+  if (TARGET_THUMB)
+    return true;
+
   /* Don't push anything to the minipool if a CONST_DOUBLE can be built with
      a few ALU insns directly. On balance, the optimum is likely to be around
      3 insns, except when there are no load delay slots where it should be 4.
      When optimizing for size, a limit of 3 allows saving at least one word
      except for cases where a single minipool entry could be shared more than
      2 times which is rather unlikely to outweight the overall savings. */
-  return (  arm_gen_constant (SET, SImode, NULL_RTX, parts[0],
-                             NULL_RTX, NULL_RTX, 0, 0)
-         + arm_gen_constant (SET, SImode, NULL_RTX, parts[1],
-                             NULL_RTX, NULL_RTX, 0, 0)
-         > ((optimize_size || (tune_flags & FL_LDSCHED)) ? 3 : 4));
+  return (arm_const_double_inline_cost (val)
+         > ((optimize_size || arm_ld_sched) ? 3 : 4));
 }
 
 /* Scan INSN and note any of its operands that need fixing.
index f8a0002..b09905a 100644 (file)
@@ -1309,27 +1309,39 @@ enum reg_class
    `S' means any symbol that has the SYMBOL_REF_FLAG set or a CONSTANT_POOL
    address.  This means that the symbol is in the text segment and can be
    accessed without using a load.
+   'D' Prefixes a number of const_double operands where:
+   'Da' is a constant that takes two ARM insns to load.
+   'Db' takes three ARM insns.
+   'Dc' takes four ARM insns, if we allow that in this compilation.
    'U' Prefixes an extended memory constraint where:
    'Uv' is an address valid for VFP load/store insns.
    'Uy' is an address valid for iwmmxt load/store insns.
    'Uq' is an address valid for ldrsb.  */
 
-#define EXTRA_CONSTRAINT_STR_ARM(OP, C, STR)                   \
-  (((C) == 'Q') ? (GET_CODE (OP) == MEM                                \
-                && GET_CODE (XEXP (OP, 0)) == REG) :           \
-   ((C) == 'R') ? (GET_CODE (OP) == MEM                                \
-                  && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF     \
-                  && CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) : \
-   ((C) == 'S') ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) :  \
-   ((C) == 'T') ? cirrus_memory_offset (OP) :                  \
+#define EXTRA_CONSTRAINT_STR_ARM(OP, C, STR)                           \
+  (((C) == 'D') ? (GET_CODE (OP) == CONST_DOUBLE                       \
+                  && (((STR)[1] == 'a'                                 \
+                       && arm_const_double_inline_cost (OP) == 2)      \
+                      || ((STR)[1] == 'b'                              \
+                          && arm_const_double_inline_cost (OP) == 3)   \
+                      || ((STR)[1] == 'c'                              \
+                          && arm_const_double_inline_cost (OP) == 4    \
+                          && !(optimize_size || arm_ld_sched)))) :     \
+   ((C) == 'Q') ? (GET_CODE (OP) == MEM                                        \
+                && GET_CODE (XEXP (OP, 0)) == REG) :                   \
+   ((C) == 'R') ? (GET_CODE (OP) == MEM                                        \
+                  && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF             \
+                  && CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) :         \
+   ((C) == 'S') ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) :          \
+   ((C) == 'T') ? cirrus_memory_offset (OP) :                          \
    ((C) == 'U' && (STR)[1] == 'v') ? arm_coproc_mem_operand (OP, FALSE) : \
    ((C) == 'U' && (STR)[1] == 'y') ? arm_coproc_mem_operand (OP, TRUE) : \
-   ((C) == 'U' && (STR)[1] == 'q')                             \
-    ? arm_extendqisi_mem_op (OP, GET_MODE (OP))                        \
-      : 0)
+   ((C) == 'U' && (STR)[1] == 'q')                                     \
+    ? arm_extendqisi_mem_op (OP, GET_MODE (OP))                                \
+   : 0)
 
 #define CONSTRAINT_LEN(C,STR)                          \
-  ((C) == 'U' ? 2 : DEFAULT_CONSTRAINT_LEN (C, STR))
+  (((C) == 'U' || (C) == 'D') ? 2 : DEFAULT_CONSTRAINT_LEN (C, STR))
 
 #define EXTRA_CONSTRAINT_THUMB(X, C)                                   \
   ((C) == 'Q' ? (GET_CODE (X) == MEM                                   \
index 7f28141..f464aa4 100644 (file)
 )
 
 (define_insn "*arm_movdi"
-  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
-       (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
+  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,   r, r, r, m")
+       (match_operand:DI 1 "di_operand"              "rIKDa,Db,Dc,mi,r"))]
   "TARGET_ARM
   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
   && !TARGET_IWMMXT"
   "*
   return (output_move_double (operands));
   "
-  [(set_attr "length" "8")
-   (set_attr "type" "*,load2,store2")
-   (set_attr "pool_range" "*,1020,*")
-   (set_attr "neg_pool_range" "*,1008,*")]
+  [(set_attr "length" "8,12,16,8,8")
+   (set_attr "type" "*,*,*,load2,store2")
+   (set_attr "pool_range" "*,*,*,1020,*")
+   (set_attr "neg_pool_range" "*,*,*,1008,*")]
 )
 
 ;; We can't actually do base+index doubleword loads if the index and
 )
 
 (define_insn "*movdf_soft_insn"
-  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
-       (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
+  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
+       (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
   "TARGET_ARM && TARGET_SOFT_FLOAT
   "
   "* return output_move_double (operands);"
-  [(set_attr "length" "8,8,8")
-   (set_attr "type" "*,load2,store2")
+  [(set_attr "length" "8,12,16,8,8")
+   (set_attr "type" "*,*,*,load2,store2")
    (set_attr "pool_range" "1020")
    (set_attr "neg_pool_range" "1008")]
 )