; 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)
--- /dev/null
+/* { 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 } } */
--- /dev/null
+/* { 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 } } */