arm-protos.h (arm_attr_length_push_multi): New prototype.
authorWei Guozhi <carrot@google.com>
Fri, 8 Apr 2011 09:17:42 +0000 (09:17 +0000)
committerWei Guozhi <carrot@gcc.gnu.org>
Fri, 8 Apr 2011 09:17:42 +0000 (09:17 +0000)
* config/arm/arm-protos.h (arm_attr_length_push_multi): New prototype.
* config/arm/arm.c (arm_attr_length_push_multi): New function.
* config/arm/arm.md (*push_multi): Change the length computation to
call a C function.

From-SVN: r172169

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

index 62df9162caac15bc0ba27d93b76654932aeb9ac9..3162967c67b9030ce4e2b8eb0baf4d6533d7a5fb 100644 (file)
@@ -1,3 +1,11 @@
+2011-04-08  Wei Guozhi  <carrot@google.com>
+
+       PR target/47855
+       * config/arm/arm-protos.h (arm_attr_length_push_multi): New prototype.
+       * config/arm/arm.c (arm_attr_length_push_multi): New function.
+       * config/arm/arm.md (*push_multi): Change the length computation to
+       call a C function.
+
 2011-04-08  Anatoly Sokolov  <aesok@post.ru>
 
        * doc/tm.texi.in (ASM_OUTPUT_BSS): Remove documentation.
index f037a456a0602c2cb6bbfe21db01889a97435ff9..c8cadf34d990b365e1e13b148494279d7b3c5bc8 100644 (file)
@@ -152,6 +152,7 @@ extern void arm_expand_sync (enum machine_mode, struct arm_sync_generator *,
 extern const char *arm_output_memory_barrier (rtx *);
 extern const char *arm_output_sync_insn (rtx, rtx *);
 extern unsigned int arm_sync_loop_insns (rtx , rtx *);
+extern int arm_attr_length_push_multi(rtx, rtx);
 
 #if defined TREE_CODE
 extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
index 533ad910c8f29b7b336db6b6d86aec4e16892c78..44c8e2fd9a272f97ac48be9911e0e77a91e0bee4 100644 (file)
@@ -23696,4 +23696,30 @@ arm_preferred_rename_class (reg_class_t rclass)
     return NO_REGS;
 }
 
+/* Compute the atrribute "length" of insn "*push_multi".
+   So this function MUST be kept in sync with that insn pattern.  */
+int
+arm_attr_length_push_multi(rtx parallel_op, rtx first_op)
+{
+  int i, regno, hi_reg;
+  int num_saves = XVECLEN (parallel_op, 0);
+
+  /* ARM mode.  */
+  if (TARGET_ARM)
+    return 4;
+
+  /* Thumb2 mode.  */
+  regno = REGNO (first_op);
+  hi_reg = (REGNO_REG_CLASS (regno) == HI_REGS) && (regno != LR_REGNUM);
+  for (i = 1; i < num_saves && !hi_reg; i++)
+    {
+      regno = REGNO (XEXP (XVECEXP (parallel_op, 0, i), 0));
+      hi_reg |= (REGNO_REG_CLASS (regno) == HI_REGS) && (regno != LR_REGNUM);
+    }
+
+  if (!hi_reg)
+    return 2;
+  return 4;
+}
+
 #include "gt-arm.h"
index 3a5bc42a2a8fc769ba96a5f222c6b774637beb99..e54acc72ea69c300b01d84dc56a29c9797043fca 100644 (file)
 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
 ;; expressions.  For simplicity, the first register is also in the unspec
 ;; part.
+;; To avoid the usage of GNU extension, the length attribute is computed
+;; in a C function arm_attr_length_push_multi.
 (define_insn "*push_multi"
   [(match_parallel 2 "multi_register_push"
     [(set (match_operand:BLK 0 "memory_operand" "=m")
   }"
   [(set_attr "type" "store4")
    (set (attr "length")
-       (if_then_else
-          (and (ne (symbol_ref "TARGET_THUMB2") (const_int 0))
-               (ne (symbol_ref "{
-                   /* Check if there are any high register (except lr)
-                      references in the list. KEEP the following iteration
-                      in sync with the template above.  */
-                   int i, regno, hi_reg;
-                   int num_saves = XVECLEN (operands[2], 0);
-                   regno = REGNO (operands[1]);
-                   hi_reg = (REGNO_REG_CLASS (regno) == HI_REGS)
-                            && (regno != LR_REGNUM);
-                   for (i = 1; i < num_saves && !hi_reg; i++)
-                     {
-                       regno = REGNO (XEXP (XVECEXP (operands[2], 0, i), 0));
-                       hi_reg |= (REGNO_REG_CLASS (regno) == HI_REGS)
-                                 && (regno != LR_REGNUM);
-                     }
-                   !hi_reg;    }")
-                 (const_int 0)))
-          (const_int 2)
-          (const_int 4)))]
+       (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
 )
 
 (define_insn "stack_tie"