[PR target/25512] Optimize certain equality tests on m68k

Jeff Law law@redhat.com
Fri Nov 18 21:53:00 GMT 2016


The yearly m68k day or two of bugfixing for the retro-computing folks is 
under way.  It's earlier than last year, so I can do more than just fix 
regressions.

This BZ is a simple request to optimize sequences like:

moveq #1,%d1
cmp.l %d0, %d1
beq/bne

into

subq.l #1, %d0
beq/bne

When d0/d1 are both dead at the cmp.l.

Similarly for small negative numbers which get turned into an addq.l.

I've chosen to implement this as a 3 insn -> 3 insn peephole2.  That may 
not seem useful at first.  But when done right, the 2nd insn (the 
compare) becomes trivial for final to eliminate resulting in the desired 
code.

Each time this applies we save 2 bytes and some number of cycles 
depending on the particular m68k implementation we're on.

This hits just over 4000 times building newlib.  Of course we have so 
many multilib configurations that any one target is going to see 
considerably less impact.

Tested with m68k.exp in the GCC testsuite and by building GCC's target 
libraries as well as newlib/libgloss for the m68k-elf toolchain 
(libgfortran doesn't build due to an unrelated issue).

It'll get further testing once I start my yearly m68k bootstrap.  But 
obviously that'll be running for a good long while.

Installing on the trunk.

Jeff


-------------- next part --------------
commit fe059a93ff2768570cab30c2bcf58e71cfb59a66
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Fri Nov 18 21:52:32 2016 +0000

    	PR target/25112
    	* config/m68k/m68k.c (moveq feeding equality comparison): New
    	peepholes.
    	* config/m68k/predicates.md (addq_subq_operand): New predicate.
    	(equality_comparison_operator): Likewise.
    
    	PR target/25112
    	* gcc.target/m68k/pr25112: New test.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@242605 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ff3da21..534ef4b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2016-11-18  Jeff Law  <law@redhat.com>
+
+	PR target/25112
+	* config/m68k/m68k.c (moveq feeding equality comparison): New
+	peepholes.
+	* config/m68k/predicates.md (addq_subq_operand): New predicate.
+	(equality_comparison_operator): Likewise.
+
 2016-11-18  Richard Sandiford  <richard.sandiford@arm.com>
 
 	* rtlanal.c (load_extend_op): Move to...
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 3d7895d..7b7f373 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -7641,6 +7641,46 @@
 	(const_int 0))]
   "operands[5] = (operands[0] == operands[3]) ? operands[4] : operands[3];")
 
+;; We want to turn
+;;   moveq const,dX
+;;   cmp.l dX,dY
+;;   je/jne
+;;
+;; into
+;;   addq/subq -const,dY
+;;   cmp.l dY, 0
+;;   je/jne
+;;
+;; dX and dY must both be dead at the end of the sequence and the constant
+;; must be valid for addq/subq.
+;;
+;; Essentially we're making it trivial for final to realize the comparison
+;; is not needed
+;;
+;; Testing has shown a variant where the operands are reversed in the
+;; comparison never hits, so I have not included that variant.
+;;
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "addq_subq_operand" ""))
+   (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
+		       (match_dup 0)))
+   (set (pc) (if_then_else (match_operator 5 "equality_comparison_operator"
+			    [(cc0) (const_int 0)])
+			   (match_operand 3 "pc_or_label_operand")
+			   (match_operand 4 "pc_or_label_operand")))]
+  "peep2_reg_dead_p (2, operands[0])
+   && peep2_reg_dead_p (2, operands[2])
+   && (operands[3] == pc_rtx || operands[4] == pc_rtx)
+   && DATA_REG_P (operands[2])"
+  [(set (match_dup 2) (plus:SI (match_dup 2) (match_dup 6)))
+   (set (cc0) (compare (match_dup 2) (const_int 0)))
+   (set (pc) (if_then_else (match_op_dup 5 [(cc0) (const_int 0)])
+			   (match_dup 3)
+			   (match_dup 4)))]
+  "operands[6] = GEN_INT (-INTVAL (operands[1]));")
+
 (define_peephole2
   [(set (match_operand:SI 0 "register_operand" "")
 	(match_operand:SI 1 "pow2_m1_operand" ""))
diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
index 186436c..bfb548a 100644
--- a/gcc/config/m68k/predicates.md
+++ b/gcc/config/m68k/predicates.md
@@ -245,6 +245,18 @@
 		 || reload_completed));
 })
 
+;; Used to detect constants that are valid for addq/subq instructions
+(define_predicate "addq_subq_operand"
+  (match_code "const_int")
+{
+  return ((INTVAL (op) <= 8 && INTVAL (op) > 0)
+	  || (INTVAL (op) >= -8 && INTVAL (op) < 0));
+})
+
+;; Used to detect equality and non-equality operators
+(define_predicate "equality_comparison_operator"
+  (match_code "eq,ne"))
+
 ;; Used to detect when an operand is either a register
 ;; or a constant that is all ones in its lower bits.
 ;; Used by insv pattern to help detect when we're initializing
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d6b70fa..729c2e9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-11-18  Jeff Law  <law@redhat.com>
+
+	PR target/25112
+	* gcc.target/m68k/pr25112: New test.
+
 2016-11-18  David Edelsohn  <dje.gcc@gmail.com>
 
 	* gcc.dg/tree-ssa/pr71179.c: Prune ABI message.
diff --git a/gcc/testsuite/gcc.target/m68k/pr25112.c b/gcc/testsuite/gcc.target/m68k/pr25112.c
new file mode 100644
index 0000000..0633cc1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/pr25112.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-times "addq" 16 } } */
+/* { dg-final { scan-assembler-times "subq" 16 } } */
+/* { dg-final { scan-assembler-times "moveq" 4 } } */
+extern int bar (void);
+
+#define FOO(x) \
+  void foo##x (void) { int a = bar (); if (a == x) bar (); } \
+  void bar##x (void) { int a = bar (); if (a == -x) bar (); } \
+  void foon##x (void) { int a = bar (); if (a != x) bar (); } \
+  void barn##x (void) { int a = bar (); if (a != -x) bar (); } \
+  
+
+FOO (1)
+FOO (2)
+FOO (3)
+FOO (4)
+FOO (5)
+FOO (6)
+FOO (7)
+FOO (8)
+FOO (9)
+
+


More information about the Gcc-patches mailing list