As I've mentioned elsewhere, the H8, particularly early models has very limited shift capabilities -- including no inherent support for shift by a variable amount. Naturally GCC accommodates this by emitting a suitable loop.

The shift loop has a typical sequence.  Shift, decrement counter, test counter, branch to top of loop if counter hasn't reached zero.  These are emitted as RTL fairly late in the pipeline (after prologue/epilogue generation).   Prior to removal of cc0 the existing machinery was capable of removing the test of the counter and instead relying on the condition codes set by the decrement.

Because this expansion happens so late (after cmpelim) we were failing to remove the unnecessary test.  My first attempt moved the expansion to a slightly earlier point, but the point where we want it doesn't necessarily have register lifetime information, which the patterns will try to exploit to generate better code.

This is a slightly different approach.  It leaves the expansion where it is, but generates condition code aware RTL.  So the expansion has the shift, decrement counter & update condition codes, branch to top of loop if counter hasn't reached zero.  ie, it natively handles the condition codes.

This eliminates one cmp insn in every shift-by-variable-amount loop.

Committed to the trunk after the usual testing.

Jeff
commit 1562c7987be115311a75b1074c3768a1b006adb6
Author: Jeff Law <jeffreya...@gmail.com>
Date:   Mon Jul 5 17:23:43 2021 -0400

    Remove redundant compare in shift loop on H8
    
    gcc/ChangeLog
    
            * config/h8300/shiftrotate.md (shift-by-variable patterns): Update 
to
            generate condition code aware RTL directly.

diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md
index 0476324bf22..485303cb906 100644
--- a/gcc/config/h8300/shiftrotate.md
+++ b/gcc/config/h8300/shiftrotate.md
@@ -385,10 +385,15 @@
    (parallel
      [(set (match_dup 0)
           (match_op_dup 2 [(match_dup 0) (const_int 1)]))
-      (clobber (scratch:QI))])
-   (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))
+      (clobber (reg:CC CC_REG))])
+   (parallel
+     [(set (reg:CCZN CC_REG)
+          (compare:CCZN
+            (plus:QI (match_dup 1) (const_int -1))
+            (const_int 0)))
+      (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))])
    (set (pc)
-        (if_then_else (ne (match_dup 1) (const_int 0))
+        (if_then_else (ne (reg:CCZN CC_REG) (const_int 0))
                      (label_ref (match_dup 4))
                      (pc)))
    (match_dup 5)]
@@ -416,10 +421,15 @@
    (parallel
      [(set (match_dup 0)
           (match_op_dup 2 [(match_dup 0) (const_int 1)]))
-      (clobber (scratch:QI))])
-   (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1)))
+      (clobber (reg:CC CC_REG))])
+   (parallel
+     [(set (reg:CCZN CC_REG)
+          (compare:CCZN
+            (plus:QI (match_dup 3) (const_int -1))
+            (const_int 0)))
+      (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1)))])
    (set (pc)
-        (if_then_else (ne (match_dup 3) (const_int 0))
+        (if_then_else (ne (reg:CCZN CC_REG) (const_int 0))
                      (label_ref (match_dup 4))
                      (pc)))
    (match_dup 5)]

Reply via email to