arm.c (arm_override_options): Use arm_ld_sched rather than testing a bit in tune_flags.

* 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.

From-SVN: r90962
This commit is contained in:
Richard Earnshaw 2004-11-20 11:21:55 +00:00 committed by Richard Earnshaw
parent 9eaf7da094
commit 2075b05db6
5 changed files with 74 additions and 38 deletions

View 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.

View 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 *);

View 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.

View 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 \

View File

@ -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")]
)