diff options
author | Ian Bolton <ian.bolton@arm.com> | 2012-04-30 13:41:49 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2012-04-30 13:41:49 +0000 |
commit | fb40241da4b1bf3a0abde0a30803ac3483636a96 (patch) | |
tree | a5b10dd89be2705840d4e03f2c40fac4cf9b1991 | |
parent | 5991e1568cd0d505ae3646c3178b1676cc70bc13 (diff) | |
download | gcc-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/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 37 | ||||
-rw-r--r-- | gcc/config/arm/predicates.md | 8 |
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" |