Commit 2075b05d by Richard Earnshaw Committed by Richard Earnshaw

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
parent 9eaf7da0
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.
......
......@@ -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 *);
......
......@@ -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.
......
......@@ -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 \
......
......@@ -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")]
)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment