]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Use shift instructions to eliminate redundant compare/test instructions on the H8
authorJeff Law <jeffreyalaw@gmail.com>
Fri, 2 Jul 2021 15:58:47 +0000 (11:58 -0400)
committerJeff Law <jeffreyalaw@gmail.com>
Fri, 2 Jul 2021 16:02:31 +0000 (12:02 -0400)
gcc/ChangeLog

* config/h8300/h8300-protos.h (compute_a_shift_cc): Accept
additional argument for the code.
* config/h8300/h8300.c (compute_a_shift_cc): Accept additional
argument for the code.  Just return if the ZN bits are useful or
not rather than the old style CC_* enums.
* config/h8300/shiftrotate.md (shiftqi_noscratch): Move before
more generic shiftqi patterns.
(shifthi_noscratch, shiftsi_noscratch): Similarly.
(shiftqi_noscratch_set_flags): New pattern.
(shifthi_noscratch_set_flags, shiftsi_noscratch_set_flags): Likewise.

gcc/config/h8300/h8300-protos.h
gcc/config/h8300/h8300.c
gcc/config/h8300/shiftrotate.md

index 86bcc3fd3248b7e2bd66cc82ab9bcb8c86c8c3fe..744337d6667189e19daa54b41a88003ef6a29f85 100644 (file)
@@ -41,7 +41,7 @@ extern const char *output_logical_op (machine_mode, rtx_code code,
 extern unsigned int compute_logical_op_length (machine_mode, rtx_code,
                                              rtx *, rtx_insn *);
 
-extern int compute_a_shift_cc (rtx, rtx *);
+extern int compute_a_shift_cc (rtx *, rtx_code);
 #ifdef HAVE_ATTR_cc
 extern enum attr_cc compute_plussi_cc (rtx *);
 #endif
index 0fdc68bf65bea17a963d2825666513fedc72eff2..d2f6548a265122539bbad76e233df542a609ea05 100644 (file)
@@ -4297,11 +4297,9 @@ compute_a_shift_length (rtx operands[3], rtx_code code)
 /* Compute which flag bits are valid after a shift insn.  */
 
 int
-compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
+compute_a_shift_cc (rtx operands[3], rtx_code code)
 {
-  rtx shift = operands[3];
-  machine_mode mode = GET_MODE (shift);
-  enum rtx_code code = GET_CODE (shift);
+  machine_mode mode = GET_MODE (operands[0]);
   enum shift_type shift_type;
   enum shift_mode shift_mode;
   struct shift_info info;
@@ -4358,16 +4356,18 @@ compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
     {
     case SHIFT_SPECIAL:
       if (info.remainder == 0)
-       return info.cc_special;
+       return (info.cc_special == OLD_CC_SET_ZN
+               || info.cc_special == OLD_CC_SET_ZNV);
 
       /* Fall through.  */
 
     case SHIFT_INLINE:
-      return info.cc_inline;
+      return (info.cc_inline == OLD_CC_SET_ZN
+             || info.cc_inline == OLD_CC_SET_ZNV);
       
     case SHIFT_ROT_AND:
       /* This case always ends with an and instruction.  */
-      return OLD_CC_SET_ZNV;
+      return true;
       
     case SHIFT_LOOP:
       /* A loop to shift by a "large" constant value.
@@ -4375,9 +4375,11 @@ compute_a_shift_cc (rtx insn ATTRIBUTE_UNUSED, rtx *operands)
       if (info.shift2 != NULL)
        {
          if (n % 2)
-           return info.cc_inline;
+           return (info.cc_inline == OLD_CC_SET_ZN
+                   || info.cc_inline == OLD_CC_SET_ZNV);
+               
        }
-      return OLD_CC_CLOBBER;
+      return false;
       
     default:
       gcc_unreachable ();
index c5d32cd6271ddae86003154a07ef7e417c61361c..0476324bf22182aae889be81b1df890441102a37 100644 (file)
 }
   [(set_attr "length" "4")])
 
-(define_insn_and_split "*shiftqi"
-  [(set (match_operand:QI 0 "register_operand" "=r,r")
-       (shifts:QI
-         (match_operand:QI 1 "register_operand" "0,0")
-         (match_operand:QI 2 "nonmemory_operand" "R,rn")))
-   (clobber (match_scratch:QI 3 "=X,&r"))]
-  ""
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2)))
-             (clobber (match_dup 3))
-             (clobber (reg:CC CC_REG))])])
-
-(define_insn "*shiftqi_clobber_flags"
-  [(set (match_operand:QI 0 "register_operand" "=r,r")
-       (shifts:QI
-         (match_operand:QI 1 "register_operand" "0,0")
-         (match_operand:QI 2 "nonmemory_operand" "R,rn")))
-   (clobber (match_scratch:QI 3 "=X,&r"))
-   (clobber (reg:CC CC_REG))]
-  ""
-{
-  return output_a_shift (operands, <CODE>);
-}
-  [(set (attr "length")
-       (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
-
 (define_insn_and_split "*shiftqi_noscratch"
   [(set (match_operand:QI 0 "register_operand" "=r,r")
        (shifts:QI
   [(set (attr "length")
        (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
 
-(define_insn_and_split "*shifthi"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-       (shifts:HI
-         (match_operand:HI 1 "register_operand" "0,0")
-         (match_operand:QI 2 "nonmemory_operand" "S,rn")))
+(define_insn "*shiftqi_noscratch_set_flags"
+  [(set (reg:CCZN CC_REG)
+       (compare:CCZN
+         (shifts:QI
+           (match_operand:QI 1 "register_operand" "0,0")
+           (match_operand:QI 2 "nonmemory_operand" "R,rn"))
+         (const_int 0)))
+   (set (match_operand:QI 0 "register_operand" "=r,r")
+       (shifts:QI (match_dup 1) (match_dup 2)))]
+  "(GET_CODE (operands[2]) == CONST_INT
+    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, <CODE>)
+    && compute_a_shift_cc (operands, <CODE>))"
+{
+  return output_a_shift (operands, <CODE>);
+}
+  [(set (attr "length")
+       (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
+
+
+(define_insn_and_split "*shiftqi"
+  [(set (match_operand:QI 0 "register_operand" "=r,r")
+       (shifts:QI
+         (match_operand:QI 1 "register_operand" "0,0")
+         (match_operand:QI 2 "nonmemory_operand" "R,rn")))
    (clobber (match_scratch:QI 3 "=X,&r"))]
   ""
   "#"
   "&& reload_completed"
-  [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2)))
+  [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2)))
              (clobber (match_dup 3))
              (clobber (reg:CC CC_REG))])])
 
-(define_insn "*shifthi_clobber_flags"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-       (shifts:HI
-         (match_operand:HI 1 "register_operand" "0,0")
-         (match_operand:QI 2 "nonmemory_operand" "S,rn")))
+(define_insn "*shiftqi_clobber_flags"
+  [(set (match_operand:QI 0 "register_operand" "=r,r")
+       (shifts:QI
+         (match_operand:QI 1 "register_operand" "0,0")
+         (match_operand:QI 2 "nonmemory_operand" "R,rn")))
    (clobber (match_scratch:QI 3 "=X,&r"))
    (clobber (reg:CC CC_REG))]
   ""
   [(set (attr "length")
        (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
 
-(define_insn_and_split "*shiftsi"
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (shifts:SI
-         (match_operand:SI 1 "register_operand" "0,0")
-         (match_operand:QI 2 "nonmemory_operand" "T,rn")))
+(define_insn "*shifthi_noscratch_setzn"
+  [(set (reg:CCZN CC_REG)
+       (compare:CCZN
+         (shifts:HI (match_operand:HI 1 "register_operand" "0,0")
+                    (match_operand:HI 2 "nonmemory_operand" "S,rn"))
+         (const_int 0)))
+   (set (match_operand:HI 0 "register_operand" "=r,r")
+       (shifts:HI (match_dup 1) (match_dup 2)))]
+  "(GET_CODE (operands[2]) == CONST_INT
+    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>)
+    && compute_a_shift_cc (operands, <CODE>))"
+{
+  return output_a_shift (operands, <CODE>);
+}
+  [(set (attr "length")
+       (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
+
+(define_insn_and_split "*shifthi"
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+       (shifts:HI
+         (match_operand:HI 1 "register_operand" "0,0")
+         (match_operand:QI 2 "nonmemory_operand" "S,rn")))
    (clobber (match_scratch:QI 3 "=X,&r"))]
   ""
   "#"
   "&& reload_completed"
-  [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2)))
+  [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2)))
              (clobber (match_dup 3))
              (clobber (reg:CC CC_REG))])])
 
-(define_insn "*shiftsi_clobber_flags"
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (shifts:SI
-         (match_operand:SI 1 "register_operand" "0,0")
-         (match_operand:QI 2 "nonmemory_operand" "T,rn")))
+(define_insn "*shifthi_clobber_flags"
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+       (shifts:HI
+         (match_operand:HI 1 "register_operand" "0,0")
+         (match_operand:QI 2 "nonmemory_operand" "S,rn")))
    (clobber (match_scratch:QI 3 "=X,&r"))
    (clobber (reg:CC CC_REG))]
   ""
   [(set (attr "length")
        (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
 
+(define_insn "*shiftsi_noscratch_cczn"
+  [(set (reg:CCZN CC_REG)
+       (compare:CCZN
+         (shifts:SI
+           (match_operand:SI 1 "register_operand" "0,0")
+           (match_operand:SI 2 "nonmemory_operand" "T,rn"))
+         (const_int 0)))
+   (set (match_operand:SI 0 "register_operand" "=r,r")
+       (shifts:SI (match_dup 1) (match_dup 2)))]
+  "(GET_CODE (operands[2]) == CONST_INT
+    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>)
+    && compute_a_shift_cc (operands, <CODE>))"
+{
+  return output_a_shift (operands, <CODE>);
+}
+  [(set (attr "length")
+       (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
+
 ;; Split a variable shift into a loop.  If the register containing
 ;; the shift count dies, then we just use that register.
 
+
+(define_insn_and_split "*shiftsi"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (shifts:SI
+         (match_operand:SI 1 "register_operand" "0,0")
+         (match_operand:QI 2 "nonmemory_operand" "T,rn")))
+   (clobber (match_scratch:QI 3 "=X,&r"))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2)))
+             (clobber (match_dup 3))
+             (clobber (reg:CC CC_REG))])])
+
+(define_insn "*shiftsi_clobber_flags"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (shifts:SI
+         (match_operand:SI 1 "register_operand" "0,0")
+         (match_operand:QI 2 "nonmemory_operand" "T,rn")))
+   (clobber (match_scratch:QI 3 "=X,&r"))
+   (clobber (reg:CC CC_REG))]
+  ""
+{
+  return output_a_shift (operands, <CODE>);
+}
+  [(set (attr "length")
+       (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
+
 (define_split
   [(set (match_operand 0 "register_operand" "")
        (match_operator 2 "nshift_operator"