re PR rtl-optimization/87507 (IRA unnecessarily uses non-volatile registers during...
authorPeter Bergner <bergner@linux.ibm.com>
Wed, 14 Nov 2018 02:17:35 +0000 (02:17 +0000)
committerPeter Bergner <bergner@gcc.gnu.org>
Wed, 14 Nov 2018 02:17:35 +0000 (20:17 -0600)
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

gcc/ChangeLog
gcc/lower-subreg.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/pr68805.c
gcc/testsuite/gcc.target/powerpc/pr87507.c [new file with mode: 0644]

index fa13fdd0a718781f33864b9b37c584d1a144d91a..62f6383195a4b8e75aac682c0a7c89d5ea056a75 100644 (file)
@@ -1,3 +1,12 @@
+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>
 
        PR tree-optimization/87898
index 72818b8255851921a6300db960fb42a7b29b5e6b..25cb155e384ca25c96548a88a8029ba188cf020a 100644 (file)
@@ -320,6 +320,24 @@ simple_move_operand (rtx x)
   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,
    return the single set.  SPEED_P says whether we are optimizing
    INSN for speed or size.
@@ -330,7 +348,7 @@ simple_move_operand (rtx x)
 static rtx
 simple_move (rtx_insn *insn, bool speed_p)
 {
-  rtx x;
+  rtx x, op;
   rtx set;
   machine_mode mode;
 
@@ -348,6 +366,9 @@ simple_move (rtx_insn *insn, bool speed_p)
     return NULL_RTX;
 
   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])
     return NULL_RTX;
   /* For the src we can handle ASM_OPERANDS, and it is beneficial for
@@ -386,9 +407,13 @@ find_pseudo_copy (rtx set)
 {
   rtx dest = SET_DEST (set);
   rtx src = SET_SRC (set);
+  rtx op;
   unsigned int rd, rs;
   bitmap b;
 
+  if ((op = operand_for_swap_move_operator (src)) != NULL_RTX)
+    src = op;
+
   if (!REG_P (dest) || !REG_P (src))
     return false;
 
@@ -846,6 +871,21 @@ can_decompose_p (rtx x)
   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
    we don't change anything, return INSN, otherwise return the start
    of the sequence of moves.  */
@@ -853,7 +893,7 @@ can_decompose_p (rtx x)
 static rtx_insn *
 resolve_simple_move (rtx set, rtx_insn *insn)
 {
-  rtx src, dest, real_dest;
+  rtx src, dest, real_dest, src_op;
   rtx_insn *insns;
   machine_mode orig_mode, dest_mode;
   unsigned int orig_size, words;
@@ -876,6 +916,23 @@ resolve_simple_move (rtx set, rtx_insn *insn)
 
   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
       && resolve_reg_p (SUBREG_REG (src))
       && (maybe_ne (SUBREG_BYTE (src), 0)
index be7cf2880caa22539e5f2349a2b613b358aebf5e..c1c92b1cbc8fa0695d82737e86f6b66f28093e62 100644 (file)
@@ -1,3 +1,9 @@
+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>
 
        PR tree-optimization/87898
index 626e2271829482003c9b323ff0c1b6728667eeb1..9f76e2bf89ab254e227d2fa8edd1283d50d3f3f7 100644 (file)
@@ -9,7 +9,7 @@ typedef struct bar {
 
 void foo (TYPE *p, TYPE *q) { *p = *q; }
 
-/* { dg-final { scan-assembler     "lxvd2x"   } } */
-/* { dg-final { scan-assembler     "stxvd2x"  } } */
+/* { dg-final { scan-assembler-times {\mld\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mstd\M} 2 } } */
 /* { dg-final { scan-assembler-not "xxpermdi" } } */
 
diff --git a/gcc/testsuite/gcc.target/powerpc/pr87507.c b/gcc/testsuite/gcc.target/powerpc/pr87507.c
new file mode 100644 (file)
index 0000000..d30a744
--- /dev/null
@@ -0,0 +1,22 @@
+/* { 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} } } */