Commit 9b56ec11 by Jackson Woodruff Committed by Kyrylo Tkachov

[AArch64, patch] Refactor of aarch64-ldpstp

This patch removes a lot of duplicated code in aarch64-ldpstp.md.

The patterns that did not previously generate a base register now
do not check for aarch64_mem_pair_operand in the pattern. This has
been extracted to a check in aarch64_operands_ok_for_ldpstp.

All patterns in the file used to have explicit switching code to
swap loads and stores that were in the wrong order.

This has been extracted into aarch64_operands_ok_for_ldpstp
as a final operation after all the checks have been performed. 

2018-05-22  Jackson Woodruff  <jackson.woodruff@arm.com>
            Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

	* config/aarch64/aarch64-ldpstp.md: Replace uses of
	aarch64_mem_pair_operand with memory_operand and delete operand swapping
	code.
	* config/aarch64/aarch64.c (aarch64_operands_ok_for_ldpstp):
	Add check for legitimate_address.
	(aarch64_gen_adjusted_ldpstp): Swap operands where appropriate.
	(aarch64_swap_ldrstr_operands): New.
	* config/aarch64/aarch64-protos.h (aarch64_swap_ldrstr_operands):
	Define prototype.

Co-Authored-By: Kyrylo Tkachov <kyrylo.tkachov@arm.com>

From-SVN: r260539
parent dfe1da23
2018-05-22 Jackson Woodruff <jackson.woodruff@arm.com> 2018-05-22 Jackson Woodruff <jackson.woodruff@arm.com>
Kyrylo Tkachov <kyrylo.tkachov@arm.com> Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/aarch64/aarch64-ldpstp.md: Replace uses of
aarch64_mem_pair_operand with memory_operand and delete operand swapping
code.
* config/aarch64/aarch64.c (aarch64_operands_ok_for_ldpstp):
Add check for legitimate_address.
(aarch64_gen_adjusted_ldpstp): Swap operands where appropriate.
(aarch64_swap_ldrstr_operands): New.
* config/aarch64/aarch64-protos.h (aarch64_swap_ldrstr_operands):
Define prototype.
2018-05-22 Jackson Woodruff <jackson.woodruff@arm.com>
Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/aarch64/aarch64.md: New patterns to generate stp * config/aarch64/aarch64.md: New patterns to generate stp
and ldp. and ldp.
(store_pair_sw, store_pair_dw): New patterns to generate stp for (store_pair_sw, store_pair_dw): New patterns to generate stp for
......
...@@ -534,6 +534,7 @@ int aarch64_ccmp_mode_to_code (machine_mode mode); ...@@ -534,6 +534,7 @@ int aarch64_ccmp_mode_to_code (machine_mode mode);
bool extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset); bool extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset);
bool aarch64_operands_ok_for_ldpstp (rtx *, bool, machine_mode); bool aarch64_operands_ok_for_ldpstp (rtx *, bool, machine_mode);
bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, scalar_mode); bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, scalar_mode);
void aarch64_swap_ldrstr_operands (rtx *, bool);
extern void aarch64_asm_output_pool_epilogue (FILE *, const char *, extern void aarch64_asm_output_pool_epilogue (FILE *, const char *,
tree, HOST_WIDE_INT); tree, HOST_WIDE_INT);
......
...@@ -16874,9 +16874,16 @@ aarch64_operands_ok_for_ldpstp (rtx *operands, bool load, ...@@ -16874,9 +16874,16 @@ aarch64_operands_ok_for_ldpstp (rtx *operands, bool load,
/* In increasing order, the last load can clobber the address. */ /* In increasing order, the last load can clobber the address. */
if (offval_1 > offval_2 && reg_mentioned_p (reg_2, mem_2)) if (offval_1 > offval_2 && reg_mentioned_p (reg_2, mem_2))
return false; return false;
} }
/* One of the memory accesses must be a mempair operand.
If it is not the first one, they need to be swapped by the
peephole. */
if (!aarch64_mem_pair_operand (mem_1, GET_MODE (mem_1))
&& !aarch64_mem_pair_operand (mem_2, GET_MODE (mem_2)))
return false;
if (REG_P (reg_1) && FP_REGNUM_P (REGNO (reg_1))) if (REG_P (reg_1) && FP_REGNUM_P (REGNO (reg_1)))
rclass_1 = FP_REGS; rclass_1 = FP_REGS;
else else
...@@ -16894,6 +16901,40 @@ aarch64_operands_ok_for_ldpstp (rtx *operands, bool load, ...@@ -16894,6 +16901,40 @@ aarch64_operands_ok_for_ldpstp (rtx *operands, bool load,
return true; return true;
} }
/* Given OPERANDS of consecutive load/store that can be merged,
swap them if they are not in ascending order. */
void
aarch64_swap_ldrstr_operands (rtx* operands, bool load)
{
rtx mem_1, mem_2, base_1, base_2, offset_1, offset_2;
HOST_WIDE_INT offval_1, offval_2;
if (load)
{
mem_1 = operands[1];
mem_2 = operands[3];
}
else
{
mem_1 = operands[0];
mem_2 = operands[2];
}
extract_base_offset_in_addr (mem_1, &base_1, &offset_1);
extract_base_offset_in_addr (mem_2, &base_2, &offset_2);
offval_1 = INTVAL (offset_1);
offval_2 = INTVAL (offset_2);
if (offval_1 > offval_2)
{
/* Irrespective of whether this is a load or a store,
we do the same swap. */
std::swap (operands[0], operands[2]);
std::swap (operands[1], operands[3]);
}
}
/* Given OPERANDS of consecutive load/store, check if we can merge /* Given OPERANDS of consecutive load/store, check if we can merge
them into ldp/stp by adjusting the offset. LOAD is true if they them into ldp/stp by adjusting the offset. LOAD is true if they
are load instructions. MODE is the mode of memory operands. are load instructions. MODE is the mode of memory operands.
...@@ -17053,7 +17094,7 @@ bool ...@@ -17053,7 +17094,7 @@ bool
aarch64_gen_adjusted_ldpstp (rtx *operands, bool load, aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
scalar_mode mode, RTX_CODE code) scalar_mode mode, RTX_CODE code)
{ {
rtx base, offset, t1, t2; rtx base, offset_1, offset_2, t1, t2;
rtx mem_1, mem_2, mem_3, mem_4; rtx mem_1, mem_2, mem_3, mem_4;
HOST_WIDE_INT off_val, abs_off, adj_off, new_off, stp_off_limit, msize; HOST_WIDE_INT off_val, abs_off, adj_off, new_off, stp_off_limit, msize;
...@@ -17061,6 +17102,30 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load, ...@@ -17061,6 +17102,30 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
{ {
mem_1 = operands[1]; mem_1 = operands[1];
mem_2 = operands[3]; mem_2 = operands[3];
}
else
{
mem_1 = operands[0];
mem_2 = operands[2];
}
extract_base_offset_in_addr (mem_1, &base, &offset_1);
extract_base_offset_in_addr (mem_2, &base, &offset_2);
gcc_assert (base != NULL_RTX && offset_1 != NULL_RTX
&& offset_2 != NULL_RTX);
if (INTVAL (offset_1) > INTVAL (offset_2))
{
std::swap (operands[0], operands[6]);
std::swap (operands[1], operands[7]);
std::swap (operands[2], operands[4]);
std::swap (operands[3], operands[5]);
}
if (load)
{
mem_1 = operands[1];
mem_2 = operands[3];
mem_3 = operands[5]; mem_3 = operands[5];
mem_4 = operands[7]; mem_4 = operands[7];
} }
...@@ -17073,13 +17138,14 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load, ...@@ -17073,13 +17138,14 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
gcc_assert (code == UNKNOWN); gcc_assert (code == UNKNOWN);
} }
extract_base_offset_in_addr (mem_1, &base, &offset); /* Extract the offset of the new first address. */
gcc_assert (base != NULL_RTX && offset != NULL_RTX); extract_base_offset_in_addr (mem_1, &base, &offset_1);
extract_base_offset_in_addr (mem_2, &base, &offset_2);
/* Adjust offset thus it can fit in ldp/stp instruction. */ /* Adjust offset thus it can fit in ldp/stp instruction. */
msize = GET_MODE_SIZE (mode); msize = GET_MODE_SIZE (mode);
stp_off_limit = msize * 0x40; stp_off_limit = msize * 0x40;
off_val = INTVAL (offset); off_val = INTVAL (offset_1);
abs_off = (off_val < 0) ? -off_val : off_val; abs_off = (off_val < 0) ? -off_val : off_val;
new_off = abs_off % stp_off_limit; new_off = abs_off % stp_off_limit;
adj_off = abs_off - new_off; adj_off = abs_off - new_off;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment