re PR target/25112 ([m68k] Suboptimal equality comparisons with small integers)
authorJeff Law <law@redhat.com>
Fri, 18 Nov 2016 21:52:32 +0000 (14:52 -0700)
committerJeff Law <law@gcc.gnu.org>
Fri, 18 Nov 2016 21:52:32 +0000 (14:52 -0700)
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.

From-SVN: r242605

gcc/ChangeLog
gcc/config/m68k/m68k.md
gcc/config/m68k/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/m68k/pr25112.c [new file with mode: 0644]

index ff3da21..534ef4b 100644 (file)
@@ -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...
index 3d7895d..7b7f373 100644 (file)
        (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" ""))
index 186436c..bfb548a 100644 (file)
                 || 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
index d6b70fa..729c2e9 100644 (file)
@@ -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 (file)
index 0000000..0633cc1
--- /dev/null
@@ -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)
+
+