From: Jeff Law Date: Fri, 2 Jul 2021 15:58:47 +0000 (-0400) Subject: Use shift instructions to eliminate redundant compare/test instructions on the H8 X-Git-Tag: basepoints/gcc-13~6326 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7aa5fb17a30ff0ce9928e5eac35b892d95e7eba5;p=thirdparty%2Fgcc.git Use shift instructions to eliminate redundant compare/test instructions on the H8 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. --- diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 86bcc3fd3248..744337d66671 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -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 diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 0fdc68bf65be..d2f6548a2651 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -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 (); diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md index c5d32cd6271d..0476324bf221 100644 --- a/gcc/config/h8300/shiftrotate.md +++ b/gcc/config/h8300/shiftrotate.md @@ -150,33 +150,6 @@ } [(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, ); -} - [(set (attr "length") - (symbol_ref "compute_a_shift_length (operands, )"))]) - (define_insn_and_split "*shiftqi_noscratch" [(set (match_operand:QI 0 "register_operand" "=r,r") (shifts:QI @@ -204,24 +177,43 @@ [(set (attr "length") (symbol_ref "compute_a_shift_length (operands, )"))]) -(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, ) + && compute_a_shift_cc (operands, ))" +{ + return output_a_shift (operands, ); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (operands, )"))]) + + +(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))] "" @@ -257,24 +249,41 @@ [(set (attr "length") (symbol_ref "compute_a_shift_length (operands, )"))]) -(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, ) + && compute_a_shift_cc (operands, ))" +{ + return output_a_shift (operands, ); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (operands, )"))]) + +(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))] "" @@ -310,9 +319,55 @@ [(set (attr "length") (symbol_ref "compute_a_shift_length (operands, )"))]) +(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, ) + && compute_a_shift_cc (operands, ))" +{ + return output_a_shift (operands, ); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (operands, )"))]) + ;; 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, ); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (operands, )"))]) + (define_split [(set (match_operand 0 "register_operand" "") (match_operator 2 "nshift_operator"