aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaochen Gui <guihaoc@gcc.gnu.org>2023-06-28 16:45:50 +0800
committerHaochen Gui <guihaoc@gcc.gnu.org>2023-06-28 16:49:32 +0800
commit1554ab958afd4f4a94f776f3a7a03b40918bf424 (patch)
treef59e80cc2b9a0c859ae78e6c578c2bc4ca62c29e
parentb7ab876fa96ce3b48120c14f327c1e199356e955 (diff)
downloadgcc-1554ab958afd4f4a94f776f3a7a03b40918bf424.zip
gcc-1554ab958afd4f4a94f776f3a7a03b40918bf424.tar.gz
gcc-1554ab958afd4f4a94f776f3a7a03b40918bf424.tar.bz2
rs6000: Add two peephole patterns for "mr." insn
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.
-rw-r--r--gcc/config/rs6000/rs6000.md39
-rw-r--r--gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_32.c60
-rw-r--r--gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_64.c60
3 files changed, 155 insertions, 4 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 75c5e5f..cdab49f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -491,6 +491,7 @@
; 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)
@@ -7879,9 +7880,9 @@
(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
@@ -7891,11 +7892,41 @@
(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
index 0000000..571a311
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_32.c
@@ -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
index 0000000..e25d655
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/powerpc/move_compare_peephole_64.c
@@ -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 } } */