2012-04-24 Ian Bolton <ian.bolton at arm.com> Sameera Deshpande...
authorIan Bolton <ian.bolton@arm.com>
Mon, 30 Apr 2012 13:41:49 +0000 (13:41 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Mon, 30 Apr 2012 13:41:49 +0000 (13:41 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/predicates.md

index 0ee7588955af6b01ea921fe7baae37534dcbc4d6..7da2ecf5e0851b347f94b8fd6152325915a9cca7 100644 (file)
@@ -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
index 753e109273cd637740d2ac3b2ae1e0697cd84704..efb5b9fe553942e399d313805f6b501d28d900ed 100644 (file)
@@ -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);
index c856af8e09fe819e37cc74de631380fc15037525..54b07c5aafaf99fe8fe687445b7d276bde837c6f 100644 (file)
@@ -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))
index 20a64ec37010aa4c879a536cd486f95f72d5e9cd..428f9e053beb86ec65b277dd2eccdcb917cdf32b 100644 (file)
 (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"