aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Bolton <ian.bolton@arm.com>2012-04-30 13:41:49 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2012-04-30 13:41:49 +0000
commitfb40241da4b1bf3a0abde0a30803ac3483636a96 (patch)
treea5b10dd89be2705840d4e03f2c40fac4cf9b1991
parent5991e1568cd0d505ae3646c3178b1676cc70bc13 (diff)
downloadgcc-fb40241da4b1bf3a0abde0a30803ac3483636a96.zip
gcc-fb40241da4b1bf3a0abde0a30803ac3483636a96.tar.gz
gcc-fb40241da4b1bf3a0abde0a30803ac3483636a96.tar.bz2
2012-04-24 Ian Bolton <ian.bolton at arm.com> Sameera Deshpande...
2012-04-24 Ian Bolton <ian.bolton at arm.com> Sameera Deshpande <sameera.deshpande at arm.com> Greta Yorsh <greta.yorsh at arm.com> * config/arm/arm-protos.h (ldm_stm_operation_p): New parameters. * config/arm/arm.c (ldm_stm_operation_p): New parameters. * config/arm/predicates.md (load_multiple_operation): Add arguments. (store_multiple_operation): Likewise. Co-Authored-By: Greta Yorsh <greta.yorsh@arm.com> Co-Authored-By: Sameera Deshpande <sameera.deshpande@arm.com> From-SVN: r186981
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/arm/arm-protos.h3
-rw-r--r--gcc/config/arm/arm.c37
-rw-r--r--gcc/config/arm/predicates.md8
4 files changed, 41 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0ee7588..7da2ecf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -7,6 +7,11 @@
* config/arm/predicates.md (load_multiple_operation): Update predicate.
(store_multiple_operation): Likewise.
+ * config/arm/arm-protos.h (ldm_stm_operation_p): New parameters.
+ * config/arm/arm.c (ldm_stm_operation_p): New parameters.
+ * config/arm/predicates.md (load_multiple_operation): Add arguments.
+ (store_multiple_operation): Likewise.
+
2012-04-30 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (and<mode>3): Expand masking operations with
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 753e109..efb5b9f 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -62,7 +62,8 @@ extern bool arm_legitimize_reload_address (rtx *, enum machine_mode, int, int,
extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
int);
extern int thumb1_legitimate_address_p (enum machine_mode, rtx, int);
-extern bool ldm_stm_operation_p (rtx, bool);
+extern bool ldm_stm_operation_p (rtx, bool, enum machine_mode mode,
+ bool, bool);
extern int arm_const_double_rtx (rtx);
extern int neg_const_double_rtx_ok_for_fpa (rtx);
extern int vfp3_const_double_rtx (rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c856af8..54b07c5 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -10167,7 +10167,9 @@ adjacent_mem_locations (rtx a, rtx b)
}
/* Return true if OP is a valid load or store multiple operation. LOAD is true
- for load operations, false for store operations.
+ for load operations, false for store operations. CONSECUTIVE is true
+ if the register numbers in the operation must be consecutive in the register
+ bank. RETURN_PC is true if value is to be loaded in PC.
The pattern we are trying to match for load is:
[(SET (R_d0) (MEM (PLUS (addr) (offset))))
(SET (R_d1) (MEM (PLUS (addr) (offset + <reg_increment>))))
@@ -10182,20 +10184,31 @@ adjacent_mem_locations (rtx a, rtx b)
REGNO (R_dk) = REGNO (R_d0) + k.
The pattern for store is similar. */
bool
-ldm_stm_operation_p (rtx op, bool load)
+ldm_stm_operation_p (rtx op, bool load, enum machine_mode mode,
+ bool consecutive, bool return_pc)
{
HOST_WIDE_INT count = XVECLEN (op, 0);
rtx reg, mem, addr;
unsigned regno;
+ unsigned first_regno;
HOST_WIDE_INT i = 1, base = 0, offset = 0;
rtx elt;
bool addr_reg_in_reglist = false;
bool update = false;
int reg_increment;
int offset_adj;
+ int regs_per_val;
- reg_increment = 4;
- offset_adj = 0;
+ /* If not in SImode, then registers must be consecutive
+ (e.g., VLDM instructions for DFmode). */
+ gcc_assert ((mode == SImode) || consecutive);
+ /* Setting return_pc for stores is illegal. */
+ gcc_assert (!return_pc || load);
+
+ /* Set up the increments and the regs per val based on the mode. */
+ reg_increment = GET_MODE_SIZE (mode);
+ regs_per_val = reg_increment / 4;
+ offset_adj = return_pc ? 1 : 0;
if (count <= 1
|| GET_CODE (XVECEXP (op, 0, offset_adj)) != SET
@@ -10223,9 +10236,11 @@ ldm_stm_operation_p (rtx op, bool load)
i = i + offset_adj;
base = base + offset_adj;
- /* Perform a quick check so we don't blow up below. */
- if (count <= i)
- return false;
+ /* Perform a quick check so we don't blow up below. If only one reg is loaded,
+ success depends on the type: VLDM can do just one reg,
+ LDM must do at least two. */
+ if ((count <= i) && (mode == SImode))
+ return false;
elt = XVECEXP (op, 0, i - 1);
if (GET_CODE (elt) != SET)
@@ -10246,6 +10261,7 @@ ldm_stm_operation_p (rtx op, bool load)
return false;
regno = REGNO (reg);
+ first_regno = regno;
addr = XEXP (mem, 0);
if (GET_CODE (addr) == PLUS)
{
@@ -10277,10 +10293,13 @@ ldm_stm_operation_p (rtx op, bool load)
}
if (!REG_P (reg)
- || GET_MODE (reg) != SImode
+ || GET_MODE (reg) != mode
|| REGNO (reg) <= regno
+ || (consecutive
+ && (REGNO (reg) !=
+ (unsigned int) (first_regno + regs_per_val * (i - base))))
|| !MEM_P (mem)
- || GET_MODE (mem) != SImode
+ || GET_MODE (mem) != mode
|| ((GET_CODE (XEXP (mem, 0)) != PLUS
|| !rtx_equal_p (XEXP (XEXP (mem, 0), 0), addr)
|| !CONST_INT_P (XEXP (XEXP (mem, 0), 1))
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 20a64ec..428f9e0 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -380,13 +380,17 @@
(define_special_predicate "load_multiple_operation"
(match_code "parallel")
{
- return ldm_stm_operation_p (op, /*load=*/true);
+ return ldm_stm_operation_p (op, /*load=*/true, SImode,
+ /*consecutive=*/false,
+ /*return_pc=*/false);
})
(define_special_predicate "store_multiple_operation"
(match_code "parallel")
{
- return ldm_stm_operation_p (op, /*load=*/false);
+ return ldm_stm_operation_p (op, /*load=*/false, SImode,
+ /*consecutive=*/false,
+ /*return_pc=*/false);
})
(define_special_predicate "multi_register_push"