From 359a6e9ffd0f4e9685d2299fbfdda572d375b171 Mon Sep 17 00:00:00 2001 From: rearnsha Date: Sat, 20 Nov 2004 11:21:55 +0000 Subject: [PATCH] * 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 --- gcc/ChangeLog | 14 ++++++++++++++ gcc/config/arm/arm-protos.h | 1 + gcc/config/arm/arm.c | 41 +++++++++++++++++++++++++---------------- gcc/config/arm/arm.h | 36 ++++++++++++++++++++++++------------ gcc/config/arm/arm.md | 20 ++++++++++---------- 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 + + * 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 * 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")] ) -- 2.11.0