+2016-12-07 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * config/aarch64/aarch64.md (movti_aarch64): Change Ump to m.
+ (movtf_aarch64): Likewise.
+ * config/aarch64/aarch64.c (aarch64_classify_address):
+ Use correct intersection of offsets.
+ (aarch64_legitimize_address_displacement): Use 9-bit signed offsets.
+ (aarch64_legitimize_address): Use 9-bit signed offsets for TI/TF mode.
+ Use 7-bit signed scaled mode for modes > 16 bytes.
+
2016-12-07 James Greenhalgh <james.greenhalgh@arm.com>
PR rtl-optimization/78561
instruction memory accesses. */
if (mode == TImode || mode == TFmode)
return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
- && offset_9bit_signed_unscaled_p (mode, offset));
+ && (offset_9bit_signed_unscaled_p (mode, offset)
+ || offset_12bit_unsigned_scaled_p (mode, offset)));
/* A 7bit offset check because OImode will emit a ldp/stp
instruction (only big endian will get here).
/* Split an out-of-range address displacement into a base and offset.
Use 4KB range for 1- and 2-byte accesses and a 16KB range otherwise
to increase opportunities for sharing the base address of different sizes.
- For TI/TFmode and unaligned accesses use a 256-byte range. */
+ For unaligned accesses and TI/TF mode use the signed 9-bit range. */
static bool
aarch64_legitimize_address_displacement (rtx *disp, rtx *off, machine_mode mode)
{
- HOST_WIDE_INT mask = GET_MODE_SIZE (mode) < 4 ? 0xfff : 0x3fff;
+ HOST_WIDE_INT offset = INTVAL (*disp);
+ HOST_WIDE_INT base = offset & ~(GET_MODE_SIZE (mode) < 4 ? 0xfff : 0x3ffc);
- if (mode == TImode || mode == TFmode ||
- (INTVAL (*disp) & (GET_MODE_SIZE (mode) - 1)) != 0)
- mask = 0xff;
+ if (mode == TImode || mode == TFmode
+ || (offset & (GET_MODE_SIZE (mode) - 1)) != 0)
+ base = (offset + 0x100) & ~0x1ff;
- *off = GEN_INT (INTVAL (*disp) & ~mask);
- *disp = GEN_INT (INTVAL (*disp) & mask);
+ *off = GEN_INT (base);
+ *disp = GEN_INT (offset - base);
return true;
}
x = gen_rtx_PLUS (Pmode, base, offset_rtx);
}
- /* Does it look like we'll need a load/store-pair operation? */
+ /* Does it look like we'll need a 16-byte load/store-pair operation? */
HOST_WIDE_INT base_offset;
- if (GET_MODE_SIZE (mode) > 16
- || mode == TImode)
- base_offset = ((offset + 64 * GET_MODE_SIZE (mode))
- & ~((128 * GET_MODE_SIZE (mode)) - 1));
+ if (GET_MODE_SIZE (mode) > 16)
+ base_offset = (offset + 0x400) & ~0x7f0;
/* For offsets aren't a multiple of the access size, the limit is
-256...255. */
else if (offset & (GET_MODE_SIZE (mode) - 1))
/* Small negative offsets are supported. */
else if (IN_RANGE (offset, -256, 0))
base_offset = 0;
+ else if (mode == TImode || mode == TFmode)
+ base_offset = (offset + 0x100) & ~0x1ff;
/* Use 12-bit offset by access size. */
else
base_offset = offset & (~0xfff * GET_MODE_SIZE (mode));
(define_insn "*movti_aarch64"
[(set (match_operand:TI 0
- "nonimmediate_operand" "=r, *w,r ,*w,r ,Ump,Ump,*w,m")
+ "nonimmediate_operand" "=r, *w,r ,*w,r,m,m,*w,m")
(match_operand:TI 1
- "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r ,Z , m,*w"))]
+ "aarch64_movti_operand" " rn,r ,*w,*w,m,r,Z, m,*w"))]
"(register_operand (operands[0], TImode)
|| aarch64_reg_or_zero (operands[1], TImode))"
"@
(define_insn "*movtf_aarch64"
[(set (match_operand:TF 0
- "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump,Ump")
+ "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
(match_operand:TF 1
- "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,Ump,?r ,Y"))]
+ "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
"TARGET_FLOAT && (register_operand (operands[0], TFmode)
|| aarch64_reg_or_fp_zero (operands[1], TFmode))"
"@