Commit 38e60111 by Peter Bergner Committed by Peter Bergner

re PR rtl-optimization/87507 (IRA unnecessarily uses non-volatile registers…

re PR rtl-optimization/87507 (IRA unnecessarily uses non-volatile registers during register assignment)

gcc/
	PR rtl-optimization/87507
	* lower-subreg.c (operand_for_swap_move_operator): New function.
	(simple_move): Strip simple operators.
	(find_pseudo_copy): Likewise.
	(resolve_operand_for_swap_move_operator): New function.
	(resolve_simple_move): Strip simple operators and swap operands.

gcc/testsuite/
	PR rtl-optimization/87507
	* gcc.target/powerpc/pr87507.c: New test.
	* gcc.target/powerpc/pr68805.c: Update expected results.

From-SVN: r266097
parent 72931dea
2018-11-13 Peter Bergner <bergner@linux.ibm.com>
PR rtl-optimization/87507
* lower-subreg.c (operand_for_swap_move_operator): New function.
(simple_move): Strip simple operators.
(find_pseudo_copy): Likewise.
(resolve_operand_for_swap_move_operator): New function.
(resolve_simple_move): Strip simple operators and swap operands.
2018-11-13 Jakub Jelinek <jakub@redhat.com> 2018-11-13 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/87898 PR tree-optimization/87898
...@@ -320,6 +320,24 @@ simple_move_operand (rtx x) ...@@ -320,6 +320,24 @@ simple_move_operand (rtx x)
return true; return true;
} }
/* If X is an operator that can be treated as a simple move that we
can split, then return the operand that is operated on. */
static rtx
operand_for_swap_move_operator (rtx x)
{
/* A word sized rotate of a register pair is equivalent to swapping
the registers in the register pair. */
if (GET_CODE (x) == ROTATE
&& GET_MODE (x) == twice_word_mode
&& simple_move_operand (XEXP (x, 0))
&& CONST_INT_P (XEXP (x, 1))
&& INTVAL (XEXP (x, 1)) == BITS_PER_WORD)
return XEXP (x, 0);
return NULL_RTX;
}
/* If INSN is a single set between two objects that we want to split, /* If INSN is a single set between two objects that we want to split,
return the single set. SPEED_P says whether we are optimizing return the single set. SPEED_P says whether we are optimizing
INSN for speed or size. INSN for speed or size.
...@@ -330,7 +348,7 @@ simple_move_operand (rtx x) ...@@ -330,7 +348,7 @@ simple_move_operand (rtx x)
static rtx static rtx
simple_move (rtx_insn *insn, bool speed_p) simple_move (rtx_insn *insn, bool speed_p)
{ {
rtx x; rtx x, op;
rtx set; rtx set;
machine_mode mode; machine_mode mode;
...@@ -348,6 +366,9 @@ simple_move (rtx_insn *insn, bool speed_p) ...@@ -348,6 +366,9 @@ simple_move (rtx_insn *insn, bool speed_p)
return NULL_RTX; return NULL_RTX;
x = SET_SRC (set); x = SET_SRC (set);
if ((op = operand_for_swap_move_operator (x)) != NULL_RTX)
x = op;
if (x != recog_data.operand[0] && x != recog_data.operand[1]) if (x != recog_data.operand[0] && x != recog_data.operand[1])
return NULL_RTX; return NULL_RTX;
/* For the src we can handle ASM_OPERANDS, and it is beneficial for /* For the src we can handle ASM_OPERANDS, and it is beneficial for
...@@ -386,9 +407,13 @@ find_pseudo_copy (rtx set) ...@@ -386,9 +407,13 @@ find_pseudo_copy (rtx set)
{ {
rtx dest = SET_DEST (set); rtx dest = SET_DEST (set);
rtx src = SET_SRC (set); rtx src = SET_SRC (set);
rtx op;
unsigned int rd, rs; unsigned int rd, rs;
bitmap b; bitmap b;
if ((op = operand_for_swap_move_operator (src)) != NULL_RTX)
src = op;
if (!REG_P (dest) || !REG_P (src)) if (!REG_P (dest) || !REG_P (src))
return false; return false;
...@@ -846,6 +871,21 @@ can_decompose_p (rtx x) ...@@ -846,6 +871,21 @@ can_decompose_p (rtx x)
return true; return true;
} }
/* OPND is a concatn operand this is used with a simple move operator.
Return a new rtx with the concatn's operands swapped. */
static rtx
resolve_operand_for_swap_move_operator (rtx opnd)
{
gcc_assert (GET_CODE (opnd) == CONCATN);
rtx concatn = copy_rtx (opnd);
rtx op0 = XVECEXP (concatn, 0, 0);
rtx op1 = XVECEXP (concatn, 0, 1);
XVECEXP (concatn, 0, 0) = op1;
XVECEXP (concatn, 0, 1) = op0;
return concatn;
}
/* Decompose the registers used in a simple move SET within INSN. If /* Decompose the registers used in a simple move SET within INSN. If
we don't change anything, return INSN, otherwise return the start we don't change anything, return INSN, otherwise return the start
of the sequence of moves. */ of the sequence of moves. */
...@@ -853,7 +893,7 @@ can_decompose_p (rtx x) ...@@ -853,7 +893,7 @@ can_decompose_p (rtx x)
static rtx_insn * static rtx_insn *
resolve_simple_move (rtx set, rtx_insn *insn) resolve_simple_move (rtx set, rtx_insn *insn)
{ {
rtx src, dest, real_dest; rtx src, dest, real_dest, src_op;
rtx_insn *insns; rtx_insn *insns;
machine_mode orig_mode, dest_mode; machine_mode orig_mode, dest_mode;
unsigned int orig_size, words; unsigned int orig_size, words;
...@@ -876,6 +916,23 @@ resolve_simple_move (rtx set, rtx_insn *insn) ...@@ -876,6 +916,23 @@ resolve_simple_move (rtx set, rtx_insn *insn)
real_dest = NULL_RTX; real_dest = NULL_RTX;
if ((src_op = operand_for_swap_move_operator (src)) != NULL_RTX)
{
if (resolve_reg_p (dest))
{
/* DEST is a CONCATN, so swap its operands and strip
SRC's operator. */
dest = resolve_operand_for_swap_move_operator (dest);
src = src_op;
}
else if (resolve_reg_p (src_op))
{
/* SRC is an operation on a CONCATN, so strip the operator and
swap the CONCATN's operands. */
src = resolve_operand_for_swap_move_operator (src_op);
}
}
if (GET_CODE (src) == SUBREG if (GET_CODE (src) == SUBREG
&& resolve_reg_p (SUBREG_REG (src)) && resolve_reg_p (SUBREG_REG (src))
&& (maybe_ne (SUBREG_BYTE (src), 0) && (maybe_ne (SUBREG_BYTE (src), 0)
......
2018-11-13 Peter Bergner <bergner@linux.ibm.com>
PR rtl-optimization/87507
* gcc.target/powerpc/pr87507.c: New test.
* gcc.target/powerpc/pr68805.c: Update expected results.
2018-11-13 Jakub Jelinek <jakub@redhat.com> 2018-11-13 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/87898 PR tree-optimization/87898
......
...@@ -9,7 +9,7 @@ typedef struct bar { ...@@ -9,7 +9,7 @@ typedef struct bar {
void foo (TYPE *p, TYPE *q) { *p = *q; } void foo (TYPE *p, TYPE *q) { *p = *q; }
/* { dg-final { scan-assembler "lxvd2x" } } */ /* { dg-final { scan-assembler-times {\mld\M} 2 } } */
/* { dg-final { scan-assembler "stxvd2x" } } */ /* { dg-final { scan-assembler-times {\mstd\M} 2 } } */
/* { dg-final { scan-assembler-not "xxpermdi" } } */ /* { dg-final { scan-assembler-not "xxpermdi" } } */
/* { dg-do compile { target powerpc64le-*-* } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
/* { dg-options "-O2 -mcpu=power8" } */
typedef struct
{
__int128_t x;
__int128_t y;
} foo_t;
void
foo (long cond, foo_t *dst, __int128_t src)
{
if (cond)
{
dst->x = src;
dst->y = src;
}
}
/* { dg-final { scan-assembler-times {\mstd\M} 4 } } */
/* { dg-final { scan-assembler-not {\mld\M} } } */
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