From b4a58f80ff157c8dd62151294fa935820540fc05 Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Fri, 8 Apr 2005 13:34:27 +0000 Subject: [PATCH] arm.c (arm_const_double_by_parts): New function. * arm.c (arm_const_double_by_parts): New function. * arm-protos.h (arm_const_double_by_parts): Add prototype. * arm.md (define_split for 64-bit constants): Add another one. From-SVN: r97828 --- gcc/ChangeLog | 6 ++++++ gcc/config/arm/arm-protos.h | 1 + gcc/config/arm/arm.c | 35 +++++++++++++++++++++++++++++++++++ gcc/config/arm/arm.md | 24 ++++++++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 33d84cf10fd5..ed81d90df681 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2005-04-08 Richard Earnshaw + + * arm.c (arm_const_double_by_parts): New function. + * arm-protos.h (arm_const_double_by_parts): Add prototype. + * arm.md (define_split for 64-bit constants): Add another one. + 2005-04-08 Andrew MacLeod * tree-ssa-operands.c (correct_use_link): Remove linear scan. diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 0baca5783ff9..087b475a96b8 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -91,6 +91,7 @@ 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 bool arm_const_double_by_parts (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 27c6f75a5e56..a1abe96a6e5a 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -7418,6 +7418,41 @@ arm_const_double_inline_cost (rtx val) NULL_RTX, NULL_RTX, 0, 0)); } +/* Return true if it is worthwile to split a 64-bit constant into two + 32-bit operations. This is the case if optimizing for size, or + if we have load delay slots, or if one 32-bit part can be done with + a single data operation. */ +bool +arm_const_double_by_parts (rtx val) +{ + enum machine_mode mode = GET_MODE (val); + rtx part; + + if (optimize_size || arm_ld_sched) + return true; + + if (mode == VOIDmode) + mode = DImode; + + part = gen_highpart_mode (SImode, mode, val); + + gcc_assert (GET_CODE (part) == CONST_INT); + + if (const_ok_for_arm (INTVAL (part)) + || const_ok_for_arm (~INTVAL (part))) + return true; + + part = gen_lowpart (SImode, val); + + gcc_assert (GET_CODE (part) == CONST_INT); + + if (const_ok_for_arm (INTVAL (part)) + || const_ok_for_arm (~INTVAL (part))) + return true; + + return false; +} + /* Scan INSN and note any of its operands that need fixing. If DO_PUSHES is false we do not actually push any of the fixups needed. The function returns TRUE if any fixups were needed/pushed. diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 9474c0db55a4..e94ceb81461c 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -4192,6 +4192,30 @@ " ) +; If optimizing for size, or if we have load delay slots, then +; we want to split the constant into two separate operations. +; In both cases this may split a trivial part into a single data op +; leaving a single complex constant to load. We can also get longer +; offsets in a LDR which means we get better chances of sharing the pool +; entries. Finally, we can normally do a better job of scheduling +; LDR instructions than we can with LDM. +; This pattern will only match if the one above did not. +(define_split + [(set (match_operand:ANY64 0 "arm_general_register_operand" "") + (match_operand:ANY64 1 "const_double_operand" ""))] + "TARGET_ARM && reload_completed + && arm_const_double_by_parts (operands[1])" + [(set (match_dup 0) (match_dup 1)) + (set (match_dup 2) (match_dup 3))] + " + operands[2] = gen_highpart (SImode, operands[0]); + operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]), + operands[1]); + operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_lowpart (SImode, operands[1]); + " +) + (define_split [(set (match_operand:ANY64 0 "arm_general_register_operand" "") (match_operand:ANY64 1 "arm_general_register_operand" ""))] -- 2.43.5