summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2004-11-20 11:21:55 +0000
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>2004-11-20 11:21:55 +0000
commit359a6e9ffd0f4e9685d2299fbfdda572d375b171 (patch)
treed507dbbe8977ece1767492a24c84daef2fcbcf24 /gcc
parentb33f46b59edc88be98c54e07e62ea4be08c4406d (diff)
downloadgcc-359a6e9ffd0f4e9685d2299fbfdda572d375b171.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@90962 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/arm/arm-protos.h1
-rw-r--r--gcc/config/arm/arm.c41
-rw-r--r--gcc/config/arm/arm.h36
-rw-r--r--gcc/config/arm/arm.md20
5 files changed, 74 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4ad29a70ee4..361a03111c8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 44a259fd12a..c46ce8273db 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -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 *);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 192fdb4f17b..066761362d9 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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.
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index f8a000255bd..b09905aed87 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -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 \
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 7f28141dce1..f464aa44d07 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4156,18 +4156,18 @@
)
(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
@@ -5165,13 +5165,13 @@
)
(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")]
)