]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rs6000: Add two peephole patterns for "mr." insn
authorHaochen Gui <guihaoc@gcc.gnu.org>
Wed, 28 Jun 2023 08:45:50 +0000 (16:45 +0800)
committerHaochen Gui <guihaoc@gcc.gnu.org>
Wed, 28 Jun 2023 08:49:32 +0000 (16:49 +0800)
When investigating the issue mentioned in PR87871#c30 - if compare
and move pattern benefits before RA, I checked the assembly generated
for SPEC2017 and found that certain insn sequences aren't converted to
"mr." instructions.
Following two sequence are never to be combined to "mr." pattern as
there is no register link between them. This patch adds two peephole2
patterns to convert them to "mr." instructions.

cmp 0,3,0
mr 4,3

mr 4,3
cmp 0,3,0

The patch also creates a new mode iterator which decided by
TARGET_POWERPC64.  This mode iterator is used in "mr." and its split
pattern.  The original P iterator is improper when -m32/-mpowerpc64 is
set.  In this situation, the "mr." should compares the whole 64-bit
register with 0 other than the low 32-bit one.

gcc/
* config/rs6000/rs6000.md (peephole2 for compare_and_move): New.
(peephole2 for move_and_compare): New.
(mode_iterator WORD): New.  Set the mode to SI/DImode by
TARGET_POWERPC64.
(*mov<mode>_internal2): Change the mode iterator from P to WORD.
(split pattern for compare_and_move): Likewise.

gcc/testsuite/
* gcc.dg/rtl/powerpc/move_compare_peephole_32.c: New.
* gcc.dg/rtl/powerpc/move_compare_peephole_64.c: New.

gcc/config/rs6000/rs6000.md
gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_32.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_64.c [new file with mode: 0644]

index 75c5e5fc93dd992ce64abb15e3bcf8c07fcaea49..cdab49fbb915b302314b5844722ecdee61b29359 100644 (file)
 ; The size of a pointer.  Also, the size of the value that a record-condition
 ; (one with a '.') will compare; and the size used for arithmetic carries.
 (define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
+(define_mode_iterator WORD [(SI "!TARGET_POWERPC64") (DI "TARGET_POWERPC64")])
 
 ; Iterator to add PTImode along with TImode (TImode can go in VSX registers,
 ; PTImode is GPR only)
 
 (define_insn "*mov<mode>_internal2"
   [(set (match_operand:CC 2 "cc_reg_operand" "=y,x,?y")
-       (compare:CC (match_operand:P 1 "gpc_reg_operand" "0,r,r")
+       (compare:CC (match_operand:WORD 1 "gpc_reg_operand" "0,r,r")
                    (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
+   (set (match_operand:WORD 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
   ""
   "@
    cmp<wd>i %2,%0,0
    (set_attr "dot" "yes")
    (set_attr "length" "4,4,8")])
 
+(define_peephole2
+  [(set (match_operand:CC 2 "cc_reg_operand")
+       (compare:CC (match_operand:WORD 1 "int_reg_operand")
+                   (const_int 0)))
+   (set (match_operand:WORD 0 "int_reg_operand")
+       (match_dup 1))]
+  "!cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(parallel [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+                  (compare:CC (match_operand:WORD 1 "int_reg_operand" "r")
+                  (const_int 0)))
+             (set (match_operand:WORD 0 "int_reg_operand" "=r")
+                  (match_dup 1))])]
+  ""
+)
+
+(define_peephole2
+  [(set (match_operand:WORD 0 "int_reg_operand")
+       (match_operand:WORD 1 "int_reg_operand"))
+   (set (match_operand:CC 2 "cc_reg_operand")
+       (compare:CC (match_dup 1)
+                   (const_int 0)))]
+  "!cc_reg_not_cr0_operand (operands[2], CCmode)"
+  [(parallel [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+                  (compare:CC (match_operand:GPR 1 "int_reg_operand" "r")
+                  (const_int 0)))
+             (set (match_operand:WORD 0 "int_reg_operand" "=r")
+                  (match_dup 1))])]
+  ""
+)
+
 (define_split
   [(set (match_operand:CC 2 "cc_reg_not_cr0_operand")
-       (compare:CC (match_operand:P 1 "gpc_reg_operand")
+       (compare:CC (match_operand:WORD 1 "gpc_reg_operand")
                    (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand") (match_dup 1))]
+   (set (match_operand:WORD 0 "gpc_reg_operand") (match_dup 1))]
   "reload_completed"
   [(set (match_dup 0) (match_dup 1))
    (set (match_dup 2)
diff --git a/gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_32.c b/gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_32.c
new file mode 100644 (file)
index 0000000..571a311
--- /dev/null
@@ -0,0 +1,60 @@
+/* { dg-do compile { target powerpc*-*-linux* } } */
+/* { dg-skip-if "" { has_arch_ppc64 } } */
+/* { dg-options "-O2 -mregnames" } */
+
+/* Following instruction sequence is found in assembly of
+   Perl_block_start, which is a function of op.c in SPEC2017
+   perlbench.  It can be never combined to a move and compare
+   instruction in combine pass.  A peephole pattern is needed to
+   converted the sequence to a "mr." instruction.
+
+       cmpdi 0,9,0
+       mr 12,9
+
+   This test case is an analogue of the source code and verifies
+   if the peephole2 patterns work.
+*/
+
+int __RTL (startwith ("peephole2")) compare_move_peephole ()
+{
+(function "compare_move_peephole"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 8 (set (reg:CC %cr0)
+                    (compare:CC (reg:SI %r3)
+                        (const_int 0))))
+      (cinsn 2 (set (reg:SI %r4)
+                    (reg:SI %r3)))
+      ;; Extra insn to avoid the above being deleted by DCE.
+      (cinsn 18 (use (reg:SI %r4)))
+      (cinsn 19 (use (reg:CC %cr0)))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function "main"
+}
+
+int __RTL (startwith ("peephole2")) move_compare_peephole ()
+{
+(function "move_compare_peephole"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 2 (set (reg:SI %r4)
+                    (reg:SI %r3)))
+      (cinsn 8 (set (reg:CC %cr0)
+                    (compare:CC (reg:SI %r3)
+                        (const_int 0))))
+      ;; Extra insn to avoid the above being deleted by DCE.
+      (cinsn 18 (use (reg:SI %r4)))
+      (cinsn 19 (use (reg:CC %cr0)))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function "main"
+}
+
+/* { dg-final { scan-assembler-times {\mmr\.} 2 } } */
diff --git a/gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_64.c b/gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_64.c
new file mode 100644 (file)
index 0000000..e25d655
--- /dev/null
@@ -0,0 +1,60 @@
+/* { dg-do compile { target powerpc*-*-linux* } } */
+/* { dg-options "-O2 -mregnames" } */
+/* { dg-require-effective-target has_arch_ppc64 } */
+
+/* Following instruction sequence is found in assembly of
+   Perl_block_start, which is a function of op.c in SPEC2017
+   perlbench.  It can be never combined to a move and compare
+   instruction in combine pass.  A peephole pattern is needed to
+   converted the sequence to a "mr." instruction.
+
+       cmpdi 0,9,0
+       mr 12,9
+
+   This test case is an analogue of the source code and verifies
+   if the peephole2 patterns work.
+*/
+
+int __RTL (startwith ("peephole2")) compare_move_peephole ()
+{
+(function "compare_move_peephole"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 8 (set (reg:CC %cr0)
+                    (compare:CC (reg:DI %r3)
+                        (const_int 0))))
+      (cinsn 2 (set (reg:DI %r4)
+                    (reg:DI %r3)))
+      ;; Extra insn to avoid the above being deleted by DCE.
+      (cinsn 18 (use (reg:DI %r4)))
+      (cinsn 19 (use (reg:CC %cr0)))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function "main"
+}
+
+int __RTL (startwith ("peephole2")) move_compare_peephole ()
+{
+(function "move_compare_peephole"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 2 (set (reg:DI %r4)
+                    (reg:DI %r3)))
+      (cinsn 8 (set (reg:CC %cr0)
+                    (compare:CC (reg:DI %r3)
+                        (const_int 0))))
+      ;; Extra insn to avoid the above being deleted by DCE.
+      (cinsn 18 (use (reg:DI %r4)))
+      (cinsn 19 (use (reg:CC %cr0)))
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function "main"
+}
+
+/* { dg-final { scan-assembler-times {\mmr\.} 2 } } */