diff options
author | Paul Brook <paul@codesourcery.com> | 2007-03-01 22:58:40 +0000 |
---|---|---|
committer | Paul Brook <pbrook@gcc.gnu.org> | 2007-03-01 22:58:40 +0000 |
commit | fe2d934b4b7bdb0e3f72b575f90041e4e9b7e140 (patch) | |
tree | ea80e92e5fd211797f4d35d15f47aa342c1aa013 | |
parent | 2711355fbc306e7e0f59b3247943614eba4a382b (diff) | |
download | gcc-fe2d934b4b7bdb0e3f72b575f90041e4e9b7e140.zip gcc-fe2d934b4b7bdb0e3f72b575f90041e4e9b7e140.tar.gz gcc-fe2d934b4b7bdb0e3f72b575f90041e4e9b7e140.tar.bz2 |
arm.c (arm_legitimate_index_p): Limit iWMMXt addressing modes to LDRD for DImode.
2007-03-01 Paul Brook <paul@codesourcery.com>
* 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.
From-SVN: r122437
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 74 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 12 |
4 files changed, 85 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9c75bc2..c3d0a7e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2007-03-01 Paul Brook <paul@codesourcery.com> + + * 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 <dvorakz@suse.cz> * 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 6a9a549..9d24cd2 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 6998332..74a9e00 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 318d4f4..d09bb73 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 \ |