This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, ARM] Fix generation of LDRD/STRD on Thumb-2
- From: Richard Earnshaw <rearnsha at arm dot com>
- To: gcc patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 13 Jan 2009 14:34:44 +0000
- Subject: [PATCH, ARM] Fix generation of LDRD/STRD on Thumb-2
This patch fixes a bug in the Thumb-2 code generation where we would
incorrectly generate two 32-bit load instructions. Because of the
different offset ranges, in addition to being less efficient, this
generated code that would not always assemble.
2009-01-13 Richard Earnshaw <rearnsha@arm.com>
* arm.c (output_move_double): Don't synthesize thumb-2 ldrd/strd with
two 32-bit instructions.
*** arm.c (revision 143352)
--- arm.c (local)
*************** neon_valid_immediate (rtx op, enum machi
*** 6377,6383 ****
break; \
}
! unsigned int i, elsize, idx = 0, n_elts = CONST_VECTOR_NUNITS (op);
unsigned int innersize = GET_MODE_SIZE (GET_MODE_INNER (mode));
unsigned char bytes[16];
int immtype = -1, matches;
--- 6377,6383 ----
break; \
}
! unsigned int i, elsize = 0, idx = 0, n_elts = CONST_VECTOR_NUNITS (op);
unsigned int innersize = GET_MODE_SIZE (GET_MODE_INNER (mode));
unsigned char bytes[16];
int immtype = -1, matches;
*************** output_move_double (rtx *operands)
*** 10391,10426 ****
}
else
{
! /* 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
{
! /* 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;
--- 10391,10426 ----
}
else
{
! /* Use a single insn if we can.
! FIXME: IWMMXT allows offsets larger than ldrd can
! handle, fix these up with a pair of ldr. */
! if (TARGET_THUMB2
! || GET_CODE (otherops[2]) != CONST_INT
! || (INTVAL (otherops[2]) > -256
! && INTVAL (otherops[2]) < 256))
! output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
! else
{
output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
! output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
}
}
}
else
{
! /* Use a single insn if we can.
! FIXME: IWMMXT allows offsets larger than ldrd can handle,
fix these up with a pair of ldr. */
! if (TARGET_THUMB2
! || GET_CODE (otherops[2]) != CONST_INT
! || (INTVAL (otherops[2]) > -256
! && INTVAL (otherops[2]) < 256))
! output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
! else
{
! output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
}
}
break;
*************** output_move_double (rtx *operands)
*** 10474,10479 ****
--- 10474,10480 ----
operands[1] = otherops[0];
if (TARGET_LDRD
&& (GET_CODE (otherops[2]) == REG
+ || TARGET_THUMB2
|| (GET_CODE (otherops[2]) == CONST_INT
&& INTVAL (otherops[2]) > -256
&& INTVAL (otherops[2]) < 256)))
*************** output_move_double (rtx *operands)
*** 10586,10608 ****
/* 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);
}
}
--- 10587,10605 ----
/* IWMMXT allows offsets larger than ldrd can handle,
fix these up with a pair of ldr. */
! if (!TARGET_THUMB2
! && GET_CODE (otherops[2]) == CONST_INT
&& (INTVAL(otherops[2]) <= -256
|| INTVAL(otherops[2]) >= 256))
{
if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
{
output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
! output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
}
else
{
! output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
}
}
*************** output_move_double (rtx *operands)
*** 10637,10642 ****
--- 10634,10640 ----
}
if (TARGET_LDRD
&& (GET_CODE (otherops[2]) == REG
+ || TARGET_THUMB2
|| (GET_CODE (otherops[2]) == CONST_INT
&& INTVAL (otherops[2]) > -256
&& INTVAL (otherops[2]) < 256)))
*************** output_move_double (rtx *operands)
*** 10650,10658 ****
default:
otherops[0] = adjust_address (operands[0], SImode, 4);
! otherops[1] = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
output_asm_insn ("str%?\t%1, %0", operands);
! output_asm_insn ("str%?\t%1, %0", otherops);
}
}
--- 10648,10656 ----
default:
otherops[0] = adjust_address (operands[0], SImode, 4);
! otherops[1] = operands[1];
output_asm_insn ("str%?\t%1, %0", operands);
! output_asm_insn ("str%?\t%H1, %0", otherops);
}
}