diff mbox

[ARM,2/2] generalize ldm_stm_operation_p

Message ID 000501cd2237$c0df7cb0$429e7610$@Yorsh@arm.com
State New
Headers show

Commit Message

Greta Yorsh April 24, 2012, 4:31 p.m. UTC
Generalize ldm_stm_operation_p with additional parameters that will be used
by epilogue patterns:
  * machine mode to support both SImode and DFmode registers
  * flag to request consecutive registers in the register list
  * flag to indicate whether PC in the register list

gcc/ChangeLog

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.

Comments

Richard Earnshaw April 30, 2012, 1:44 p.m. UTC | #1
On 24/04/12 17:31, Greta Yorsh wrote:
> Generalize ldm_stm_operation_p with additional parameters that will be used
> by epilogue patterns:
>   * machine mode to support both SImode and DFmode registers
>   * flag to request consecutive registers in the register list
>   * flag to indicate whether PC in the register list
> 
> gcc/ChangeLog
> 
> 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.
> 

Thanks, committed.

R.
diff mbox

Patch

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 4216d05..5477de2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -10139,7 +10139,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>))))
@@ -10154,20 +10156,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
@@ -10195,9 +10208,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)
@@ -10218,6 +10233,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)
     {
@@ -10249,10 +10265,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"