[RFC ivopts] ARM - Make ivopts take into account whether pre and post increments are actually supported on targets.
Ramana Radhakrishnan
ramana.radhakrishnan@linaro.org
Tue Apr 10 12:51:00 GMT 2012
On 28 March 2012 11:13, Richard Guenther <richard.guenther@gmail.com> wrote:
> On Wed, Mar 28, 2012 at 11:57 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Tue, Mar 27, 2012 at 3:17 PM, Ramana Radhakrishnan
>> <ramana.radhakrishnan@linaro.org> wrote:
>>> And the patch is now attached ....
>>
>> This does not look like it would compile on any other target.
>
> Looks like the macros are pre-existing in rtl.h. With that the ivopts change
> is ok. I'll let arm folks decide over the arm specific bits.
Thanks for the approval on the ivopts stuff -which I haven't changed .
I have revised the ARM backend specific changes to tweak costs to
prevent auto-inc-dec from gratuitously adding more moves for the
pre/post_modify_disp variety of instructions and to disable these for
versions of the architecture which don't have support for LDRD.
I would like another set of eyes on the backend specific changes - I
am currently regression testing this final version on FSF trunk.
2012-04-10 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
* tree-ssa-loop-ivopts.c (add_autoinc_candidates, get_address_cost):
Replace use of HAVE_{POST/PRE}_{INCREMENT/DECREMENT} with
USE_{LOAD/STORE}_{PRE/POST}_{INCREMENT/DECREMENT} appropriately.
* config/arm/arm.h (ARM_AUTOINC_VALID_FOR_MODE_P): New.
(USE_LOAD_POST_INCREMENT): Define.
(USE_LOAD_PRE_INCREMENT): Define.
(USE_LOAD_POST_DECREMENT): Define.
(USE_LOAD_PRE_DECREMENT): Define.
(USE_STORE_PRE_DECREMENT): Define.
(USE_STORE_PRE_INCREMENT): Define.
(USE_STORE_POST_DECREMENT): Define.
(USE_STORE_POST_INCREMENT): Define.
(arm_auto_incmodes): Add enumeration.
* config/arm/arm-protos.h (arm_autoinc_modes_ok_p): Declare.
* config/arm/arm.c (arm_autoinc_modes_ok_p): Define.
(arm_rtx_costs_1): Adjust costs for
auto-inc modes and pre / post modify in floating point mode.
(arm_size_rtx_costs): Likewise.
regards,
Ramana
> Richard.
>
>> Richard.
>>
>>> Ramana
-------------- next part --------------
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 900d09a..f9cb75a 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -248,4 +248,6 @@ extern int vfp3_const_double_for_fract_bits (rtx);
extern void arm_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel);
extern bool arm_expand_vec_perm_const (rtx target, rtx op0, rtx op1, rtx sel);
+extern bool arm_autoinc_modes_ok_p (enum machine_mode, enum arm_auto_incmodes);
+
#endif /* ! GCC_ARM_PROTOS_H */
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 5522fc1..6bc5aa9 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -7121,6 +7121,19 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
/* Memory costs quite a lot for the first word, but subsequent words
load at the equivalent of a single insn each. */
*total = COSTS_N_INSNS (2 + ARM_NUM_REGS (mode));
+
+ /* If we have hard float or there is no support for ldrd
+ and strd there is no point in allowing post_dec,
+ pre_inc and pre/post_modify_disp to have the same cost
+ for memory accesses in floating point modes. */
+ if ((TARGET_HARD_FLOAT
+ || !TARGET_LDRD)
+ && (FLOAT_MODE_P (mode) &&
+ (GET_CODE (XEXP (x, 0)) == POST_DEC
+ || GET_CODE (XEXP (x, 0)) == PRE_INC
+ || GET_CODE (XEXP (x, 0)) == PRE_MODIFY
+ || GET_CODE (XEXP (x, 0)) == POST_MODIFY)))
+ *total += COSTS_N_INSNS (2);
return true;
case DIV:
@@ -7831,6 +7844,20 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
*total = COSTS_N_INSNS (2);
else
*total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+
+ /* If we have hard float or there is no support for ldrd
+ and strd there is no point in allowing post_dec,
+ pre_inc and pre/post_modify_disp to have the same cost
+ for memory accesses in floating point modes. */
+ if ((TARGET_HARD_FLOAT
+ || !TARGET_LDRD)
+ && (FLOAT_MODE_P (mode) &&
+ (GET_CODE (XEXP (x, 0)) == POST_DEC
+ || GET_CODE (XEXP (x, 0)) == PRE_INC
+ || GET_CODE (XEXP (x, 0)) == PRE_MODIFY
+ || GET_CODE (XEXP (x, 0)) == POST_MODIFY)))
+ *total = COSTS_N_INSNS (2);
+
return true;
case DIV:
@@ -25680,5 +25707,51 @@ arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
return ret;
}
-
+bool
+arm_autoinc_modes_ok_p (enum machine_mode mode, enum arm_auto_incmodes code)
+{
+ /* If we are soft float and we do not have ldrd
+ then all auto increment forms are ok. */
+ if (TARGET_SOFT_FLOAT && (TARGET_LDRD || GET_MODE_SIZE (mode) <= 4))
+ return true;
+
+ switch (code)
+ {
+ /* Post increment and Pre Decrement are supported for all
+ instruction forms except for vector forms. */
+ case ARM_POST_INC:
+ case ARM_PRE_DEC:
+ if (VECTOR_MODE_P (mode))
+ {
+ if (code != ARM_PRE_DEC)
+ return true;
+ else
+ return false;
+ }
+
+ return true;
+
+ case ARM_POST_DEC:
+ case ARM_PRE_INC:
+ /* Without LDRD and mode size greater than
+ word size, there is no point in auto-incrementing
+ because ldm and stm will not have these forms. */
+ if (!TARGET_LDRD && GET_MODE_SIZE (mode) > 4)
+ return false;
+
+ /* Vector and floating point modes do not support
+ these auto increment forms. */
+ if (FLOAT_MODE_P (mode) || VECTOR_MODE_P (mode))
+ return false;
+
+ return true;
+
+ default:
+ return false;
+
+ }
+
+ return false;
+}
+
#include "gt-arm.h"
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index c6b4cc0..f4204e4 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1613,6 +1613,30 @@ typedef struct
#define HAVE_PRE_MODIFY_REG TARGET_32BIT
#define HAVE_POST_MODIFY_REG TARGET_32BIT
+enum arm_auto_incmodes
+ {
+ ARM_POST_INC,
+ ARM_PRE_INC,
+ ARM_POST_DEC,
+ ARM_PRE_DEC
+ };
+
+#define ARM_AUTOINC_VALID_FOR_MODE_P(mode, code) \
+ (TARGET_32BIT && arm_autoinc_modes_ok_p (mode, code))
+#define USE_LOAD_POST_INCREMENT(mode) \
+ ARM_AUTOINC_VALID_FOR_MODE_P(mode, ARM_POST_INC)
+#define USE_LOAD_PRE_INCREMENT(mode) \
+ ARM_AUTOINC_VALID_FOR_MODE_P(mode, ARM_PRE_INC)
+#define USE_LOAD_POST_DECREMENT(mode) \
+ ARM_AUTOINC_VALID_FOR_MODE_P(mode, ARM_POST_DEC)
+#define USE_LOAD_PRE_DECREMENT(mode) \
+ ARM_AUTOINC_VALID_FOR_MODE_P(mode, ARM_PRE_DEC)
+
+#define USE_STORE_PRE_DECREMENT(mode) USE_LOAD_PRE_DECREMENT(mode)
+#define USE_STORE_PRE_INCREMENT(mode) USE_LOAD_PRE_INCREMENT(mode)
+#define USE_STORE_POST_DECREMENT(mode) USE_LOAD_POST_DECREMENT(mode)
+#define USE_STORE_POST_INCREMENT(mode) USE_LOAD_POST_INCREMENT(mode)
+
/* Macros to check register numbers against specific register classes. */
/* These assume that REGNO is a hard or pseudo reg number.
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 527c911..ac37608 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -2361,8 +2361,12 @@ add_autoinc_candidates (struct ivopts_data *data, tree base, tree step,
cstepi = int_cst_value (step);
mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p));
- if ((HAVE_PRE_INCREMENT && GET_MODE_SIZE (mem_mode) == cstepi)
- || (HAVE_PRE_DECREMENT && GET_MODE_SIZE (mem_mode) == -cstepi))
+ if (((USE_LOAD_PRE_INCREMENT (mem_mode)
+ || USE_STORE_PRE_INCREMENT (mem_mode))
+ && GET_MODE_SIZE (mem_mode) == cstepi)
+ || ((USE_LOAD_PRE_DECREMENT (mem_mode)
+ || USE_STORE_PRE_DECREMENT (mem_mode))
+ && GET_MODE_SIZE (mem_mode) == -cstepi))
{
enum tree_code code = MINUS_EXPR;
tree new_base;
@@ -2379,8 +2383,12 @@ add_autoinc_candidates (struct ivopts_data *data, tree base, tree step,
add_candidate_1 (data, new_base, step, important, IP_BEFORE_USE, use,
use->stmt);
}
- if ((HAVE_POST_INCREMENT && GET_MODE_SIZE (mem_mode) == cstepi)
- || (HAVE_POST_DECREMENT && GET_MODE_SIZE (mem_mode) == -cstepi))
+ if (((USE_LOAD_POST_INCREMENT (mem_mode)
+ || USE_STORE_POST_INCREMENT (mem_mode))
+ && GET_MODE_SIZE (mem_mode) == cstepi)
+ || ((USE_LOAD_POST_DECREMENT (mem_mode)
+ || USE_STORE_POST_DECREMENT (mem_mode))
+ && GET_MODE_SIZE (mem_mode) == -cstepi))
{
add_candidate_1 (data, base, step, important, IP_AFTER_USE, use,
use->stmt);
@@ -3314,25 +3322,29 @@ get_address_cost (bool symbol_present, bool var_present,
reg0 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2);
- if (HAVE_PRE_DECREMENT)
+ if (USE_LOAD_PRE_DECREMENT (mem_mode)
+ || USE_STORE_PRE_DECREMENT (mem_mode))
{
addr = gen_rtx_PRE_DEC (address_mode, reg0);
has_predec[mem_mode]
= memory_address_addr_space_p (mem_mode, addr, as);
}
- if (HAVE_POST_DECREMENT)
+ if (USE_LOAD_POST_DECREMENT (mem_mode)
+ || USE_STORE_POST_DECREMENT (mem_mode))
{
addr = gen_rtx_POST_DEC (address_mode, reg0);
has_postdec[mem_mode]
= memory_address_addr_space_p (mem_mode, addr, as);
}
- if (HAVE_PRE_INCREMENT)
+ if (USE_LOAD_PRE_INCREMENT (mem_mode)
+ || USE_STORE_PRE_DECREMENT (mem_mode))
{
addr = gen_rtx_PRE_INC (address_mode, reg0);
has_preinc[mem_mode]
= memory_address_addr_space_p (mem_mode, addr, as);
}
- if (HAVE_POST_INCREMENT)
+ if (USE_LOAD_POST_INCREMENT (mem_mode)
+ || USE_STORE_POST_INCREMENT (mem_mode))
{
addr = gen_rtx_POST_INC (address_mode, reg0);
has_postinc[mem_mode]
More information about the Gcc-patches
mailing list