[PATCH] [target/25114] Improve comparisons against some small integers for m68k

Jeff Law law@redhat.com
Wed Jan 20 07:54:00 GMT 2016


A Christmas gift to the m68k folks (or how an older box in the basement 
has spent the last 3 weeks).


Essentially this BZ is a request to turn certain inequality comparisons 
against small integers (2^n - 1 for small n) into right shifts then a 
test of the Z bit.

So for example a <= 3 (given a is unsigned) currently generates

moveq #3, %d1
cmpl %d0, %d1
jbcs somewhere

Instead we can

lsr #2, %d0
jbne somewhere

On m68000/10 this is a lose because of the poor shifter.
On m68020/30 and it's a mixed bag, but I'd classify it as a minor loss.
On m68040/60, it's a win.
It's also a win when optimizing for size.

So not surprisingly, this transformation is enabled for 040/060 or when 
optimizing for size.

Due to the way the m68k machine description works, we have to have two 
patterns because some constants are shoved into registers first while 
other times the constant will appear in the comparison itself.  And we 
need two of each of those to match the GTU and LEU cases.  GEU and LTU 
do not occur in practice.

m68k (tuned for 68040) bootstrap is well into the stage3 libraries. 
This will trigger a few thousand times during a bootstrap tuned for 
68040.  Not bad.   Installed on the trunk.



Jeff
-------------- next part --------------
commit 00ef080b82f49eab149cdafb5adccd32f3008b3c
Author: Jeff Law <law@redhat.com>
Date:   Wed Jan 20 00:51:42 2016 -0700

    [PATCH] [target/25114] Improve comparisons against some small integers for m68k
    
    	* config/m68k/predicates.md (pow2_m1_operand): New predicate
    	extracted from ...
    	(reg_or_pow2_m1_operand): Call pow2_m1_operand.
    	(pc_or_label_operand): New predicate.
    	* config/m68k/m68k.md: Add new peephole2 patterns for GTU/LEU
    	tests for small integers that are 2^n - 1.
    
    	* gcc.target/m68k/pr25114.c: New test.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac6232c..764b209 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2016-01-20  Jeff Law  <law@redhat.com>
+
+	* config/m68k/predicates.md (pow2_m1_operand): New predicate
+	extracted from ...
+	(reg_or_pow2_m1_operand): Call pow2_m1_operand.
+	(pc_or_label_operand): New predicate.
+	* config/m68k/m68k.md: Add new peephole2 patterns for GTU/LEU
+	tests for small integers that are 2^n - 1.
+	
 2016-01-20  Jonathan Wakely  <jwakely@redhat.com>
 
 	* doc/invoke.texi (Options Summary): Add '.' after @xref.
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index a56cc9f..5731780 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -7634,3 +7634,88 @@
    (set (mem:QI (match_dup 5))
 	(const_int 0))]
   "operands[5] = (operands[0] == operands[3]) ? operands[4] : operands[3];")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "pow2_m1_operand" ""))
+   (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
+		       (match_operand:SI 3 "register_operand" "")))
+   (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+			   (match_operand 4 "pc_or_label_operand")
+			   (match_operand 5 "pc_or_label_operand")))]
+  "INTVAL (operands[1]) <= 255
+   && operands[0] == operands[3]
+   && peep2_reg_dead_p (2, operands[0])
+   && peep2_reg_dead_p (2, operands[2])
+   && (operands[4] == pc_rtx || operands[5] == pc_rtx)
+   && (optimize_size || TUNE_68040_60)
+   && DATA_REG_P (operands[2])"
+  [(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
+   (set (cc0) (compare (match_dup 7) (const_int 0)))
+   (set (pc) (if_then_else (ne (cc0) (const_int 0))
+			   (match_dup 4) (match_dup 5)))]
+  "
+{
+  operands[6] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
+  operands[7] = operands[2];
+}")
+
+(define_peephole2
+  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
+		       (match_operand:SI 1 "pow2_m1_operand" "")))
+   (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+			   (match_operand 2 "pc_or_label_operand")
+			   (match_operand 3 "pc_or_label_operand")))]
+  "INTVAL (operands[1]) <= 255
+   && peep2_reg_dead_p (1, operands[0])
+   && (operands[2] == pc_rtx || operands[3] == pc_rtx)
+   && (optimize_size || TUNE_68040_60)
+   && DATA_REG_P (operands[0])"
+  [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
+   (set (cc0) (compare (match_dup 0) (const_int 0)))
+   (set (pc) (if_then_else (ne (cc0) (const_int 0))
+			   (match_dup 2) (match_dup 3)))]
+  "{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "pow2_m1_operand" ""))
+   (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
+		       (match_operand:SI 3 "register_operand" "")))
+   (set (pc) (if_then_else (leu (cc0) (const_int 0))
+			   (match_operand 4 "pc_or_label_operand")
+			   (match_operand 5 "pc_or_label_operand")))]
+  "INTVAL (operands[1]) <= 255
+   && operands[0] == operands[3]
+   && peep2_reg_dead_p (2, operands[0])
+   && peep2_reg_dead_p (2, operands[2])
+   && (operands[4] == pc_rtx || operands[5] == pc_rtx)
+   && (optimize_size || TUNE_68040_60)
+   && DATA_REG_P (operands[2])"
+  [(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
+   (set (cc0) (compare (match_dup 7) (const_int 0)))
+   (set (pc) (if_then_else (eq (cc0) (const_int 0))
+			   (match_dup 4) (match_dup 5)))]
+  "
+{
+  operands[6] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
+  operands[7] = operands[2];
+}")
+
+(define_peephole2
+  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
+		       (match_operand:SI 1 "pow2_m1_operand" "")))
+   (set (pc) (if_then_else (leu (cc0) (const_int 0))
+			   (match_operand 2 "pc_or_label_operand")
+			   (match_operand 3 "pc_or_label_operand")))]
+  "INTVAL (operands[1]) <= 255
+   &&  peep2_reg_dead_p (1, operands[0])
+   && (operands[2] == pc_rtx || operands[3] == pc_rtx)
+   && (optimize_size || TUNE_68040_60)
+   && DATA_REG_P (operands[0])"
+  [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
+   (set (cc0) (compare (match_dup 0) (const_int 0)))
+   (set (pc) (if_then_else (eq (cc0) (const_int 0))
+			   (match_dup 2) (match_dup 3)))]
+  "{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
+
diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
index 18411d6..186436c 100644
--- a/gcc/config/m68k/predicates.md
+++ b/gcc/config/m68k/predicates.md
@@ -253,7 +253,17 @@
 (define_predicate "reg_or_pow2_m1_operand"
   (match_code "reg,const_int")
 {
-  return (REG_P (op)
-	  || (GET_CODE (op) == CONST_INT
-	      && exact_log2 (INTVAL (op) + 1) >= 0));
+  return (REG_P (op) || pow2_m1_operand (op, VOIDmode));
 })
+
+;; Used to detect a constant that is all ones in its lower bits.
+(define_predicate "pow2_m1_operand"
+  (match_code "const_int")
+{
+  return (GET_CODE (op) == CONST_INT && exact_log2 (INTVAL (op) + 1) >= 0);
+})
+
+;; Used to detect valid targets for conditional branches
+;; Used to detect (pc) or (label_ref) in some jumping patterns to cut down
+(define_predicate "pc_or_label_operand"
+  (match_code "pc,label_ref"))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 63baf4e..dfad960 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-20  Jeff Law  <law@redhat.com>
+
+	* gcc.target/m68k/pr25114.c: New test.
+
 2016-01-20  Andre Vieira  <andre.simoesdiasvieira@arm.com>
 
 	* gcc.target/arm/memset-inline-10.c: Added
diff --git a/gcc/testsuite/gcc.target/m68k/pr25114.c b/gcc/testsuite/gcc.target/m68k/pr25114.c
new file mode 100644
index 0000000..bb722d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/pr25114.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -m68040" } */
+/* There should be 16 logical right shift instructions.  One for each function*/
+/* { dg-final { scan-assembler-times "lsr" 16 } } */
+
+unsigned int bar (void);
+
+#define F(C) void foo##C (void) { unsigned int a = bar (); if (a <= C) bar (); }
+#define G(C) void foo2##C (void) { unsigned int a = bar (); if (a > C) bar (); }
+
+F(0x1)
+F(0x3)
+F(0x7)
+F(0xf)
+F(0x1f)
+F(0x3f)
+F(0x7f)
+F(0xff)
+G(0x1)
+G(0x3)
+G(0x7)
+G(0xf)
+G(0x1f)
+G(0x3f)
+G(0x7f)
+G(0xff)


More information about the Gcc-patches mailing list