From f1225f6f0f9b7acb3a64314f2113807ebeea5abf Mon Sep 17 00:00:00 2001 From: pbrook Date: Thu, 1 Mar 2007 22:58:40 +0000 Subject: [PATCH] 2007-03-01 Paul Brook * config/arm/arm.c (arm_legitimate_index_p): Limit iWMMXt addressing modes to LDRD for DImode. (output_move_double): Fixup out of range ldrd/strd. (vfp_secondary_reload_class): Rename... (coproc_secondary_reload_class): ... to this. Add wb argument. * config/arm/arm.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use coproc_secondary_reload_class for CLASS_IWMMXT. (SECONDARY_INPUT_RELOAD_CLASS): Ditto. * arm-protos.h (coproc_secondary_reload_class): Update prototype. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122437 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 12 ++++++++ gcc/config/arm/arm-protos.h | 3 +- gcc/config/arm/arm.c | 74 ++++++++++++++++++++++++++++++++++++++------- gcc/config/arm/arm.h | 12 +++++--- 4 files changed, 85 insertions(+), 16 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9c75bc251ed..c3d0a7e3fb9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2007-03-01 Paul Brook + + * config/arm/arm.c (arm_legitimate_index_p): Limit iWMMXt addressing + modes to LDRD for DImode. + (output_move_double): Fixup out of range ldrd/strd. + (vfp_secondary_reload_class): Rename... + (coproc_secondary_reload_class): ... to this. Add wb argument. + * config/arm/arm.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use + coproc_secondary_reload_class for CLASS_IWMMXT. + (SECONDARY_INPUT_RELOAD_CLASS): Ditto. + * arm-protos.h (coproc_secondary_reload_class): Update prototype. + 2007-03-01 Zdenek Dvorak * tree-ssa-loop-prefetch.c (determine_unroll_factor): Bound the unroll diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 6a9a5492c1c..9d24cd2b877 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -68,7 +68,8 @@ extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int, int); extern int arm_const_double_rtx (rtx); extern int neg_const_double_rtx_ok_for_fpa (rtx); -extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx); +extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx, + bool); extern bool arm_tls_referenced_p (rtx); extern int cirrus_memory_offset (rtx); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 6998332a79d..74a9e008ca5 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -3922,10 +3922,15 @@ thumb2_legitimate_index_p (enum machine_mode mode, rtx index, int strict_p) && (INTVAL (index) & 3) == 0); if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode)) - return (code == CONST_INT - && INTVAL (index) < 1024 - && INTVAL (index) > -1024 - && (INTVAL (index) & 3) == 0); + { + /* For DImode assume values will usually live in core regs + and only allow LDRD addressing modes. */ + if (!TARGET_LDRD || mode != DImode) + return (code == CONST_INT + && INTVAL (index) < 1024 + && INTVAL (index) > -1024 + && (INTVAL (index) & 3) == 0); + } if (arm_address_register_rtx_p (index, strict_p) && (GET_MODE_SIZE (mode) <= 4)) @@ -5764,12 +5769,12 @@ arm_eliminable_register (rtx x) } /* Return GENERAL_REGS if a scratch register required to reload x to/from - VFP registers. Otherwise return NO_REGS. */ + coprocessor registers. Otherwise return NO_REGS. */ enum reg_class -vfp_secondary_reload_class (enum machine_mode mode, rtx x) +coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb) { - if (arm_coproc_mem_operand (x, FALSE) || s_register_operand (x, mode)) + if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode)) return NO_REGS; return GENERAL_REGS; @@ -9146,12 +9151,37 @@ output_move_double (rtx *operands) output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops); } else - output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops); + { + /* IWMMXT allows offsets larger than ldrd can handle, + fix these up with a pair of ldr. */ + if (GET_CODE (otherops[2]) == CONST_INT + && (INTVAL(otherops[2]) <= -256 + || INTVAL(otherops[2]) >= 256)) + { + output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops); + otherops[0] = gen_rtx_REG (SImode, 1 + reg0); + output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops); + } + else + output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops); + } } else { - /* We only allow constant increments, so this is safe. */ - output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops); + /* IWMMXT allows offsets larger than ldrd can handle, + fix these up with a pair of ldr. */ + if (GET_CODE (otherops[2]) == CONST_INT + && (INTVAL(otherops[2]) <= -256 + || INTVAL(otherops[2]) >= 256)) + { + otherops[0] = gen_rtx_REG (SImode, 1 + reg0); + output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops); + otherops[0] = operands[0]; + output_asm_insn ("ldr%?\t%0, [%1], %2", otherops); + } + else + /* We only allow constant increments, so this is safe. */ + output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops); } break; @@ -9289,7 +9319,29 @@ output_move_double (rtx *operands) otherops[1] = XEXP (XEXP (XEXP (operands[0], 0), 1), 0); otherops[2] = XEXP (XEXP (XEXP (operands[0], 0), 1), 1); - if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY) + /* IWMMXT allows offsets larger than ldrd can handle, + fix these up with a pair of ldr. */ + if (GET_CODE (otherops[2]) == CONST_INT + && (INTVAL(otherops[2]) <= -256 + || INTVAL(otherops[2]) >= 256)) + { + rtx reg1; + reg1 = gen_rtx_REG (SImode, 1 + REGNO (operands[1])); + if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY) + { + output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops); + otherops[0] = reg1; + output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops); + } + else + { + otherops[0] = reg1; + output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops); + otherops[0] = operands[1]; + output_asm_insn ("ldr%?\t%0, [%1], %2", otherops); + } + } + else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY) output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops); else output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops); diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 318d4f44624..d09bb734e2d 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1121,10 +1121,12 @@ enum reg_class or out of a register in CLASS in MODE. If it can be done directly, NO_REGS is returned. */ #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ - /* Restrict which direct reloads are allowed for VFP regs. */ \ + /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \ ((TARGET_VFP && TARGET_HARD_FLOAT \ && (CLASS) == VFP_REGS) \ - ? vfp_secondary_reload_class (MODE, X) \ + ? coproc_secondary_reload_class (MODE, X, FALSE) \ + : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) \ + ? coproc_secondary_reload_class (MODE, X, TRUE) \ : TARGET_32BIT \ ? (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \ ? GENERAL_REGS : NO_REGS) \ @@ -1132,10 +1134,12 @@ enum reg_class /* If we need to load shorts byte-at-a-time, then we need a scratch. */ #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ - /* Restrict which direct reloads are allowed for VFP regs. */ \ + /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \ ((TARGET_VFP && TARGET_HARD_FLOAT \ && (CLASS) == VFP_REGS) \ - ? vfp_secondary_reload_class (MODE, X) : \ + ? coproc_secondary_reload_class (MODE, X, FALSE) : \ + (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ? \ + coproc_secondary_reload_class (MODE, X, TRUE) : \ /* Cannot load constants into Cirrus registers. */ \ (TARGET_MAVERICK && TARGET_HARD_FLOAT \ && (CLASS) == CIRRUS_REGS \ -- 2.11.4.GIT