diff options
author | Wei Guozhi <carrot@google.com> | 2011-04-08 09:17:42 +0000 |
---|---|---|
committer | Wei Guozhi <carrot@gcc.gnu.org> | 2011-04-08 09:17:42 +0000 |
commit | 0c27e2d89b13856a0d04a4405f78d5850c4f7eab (patch) | |
tree | be5240f3b06afa52622ec493f89a65af400cff15 /gcc | |
parent | 07c5f94e8209f6c52ac32a94cc234182dd6f10d2 (diff) | |
download | gcc-0c27e2d89b13856a0d04a4405f78d5850c4f7eab.zip gcc-0c27e2d89b13856a0d04a4405f78d5850c4f7eab.tar.gz gcc-0c27e2d89b13856a0d04a4405f78d5850c4f7eab.tar.bz2 |
arm-protos.h (arm_attr_length_push_multi): New prototype.
* 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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 26 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 24 |
4 files changed, 38 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 62df916..3162967 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index f037a45..c8cadf3 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -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); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 533ad91..44c8e2f 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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" diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 3a5bc42..e54acc7 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -10249,6 +10249,8 @@ ;; 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") @@ -10290,27 +10292,7 @@ }" [(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" |