aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <jeffreyalaw@gmail.com>2021-07-02 11:58:47 -0400
committerJeff Law <jeffreyalaw@gmail.com>2021-07-02 12:02:31 -0400
commit7aa5fb17a30ff0ce9928e5eac35b892d95e7eba5 (patch)
tree6dd7cbabbc404d1b6d45a45e0b07d66cfc034ab3 /gcc
parent84f7bab89279ca1234fef88929c74caeda8cb55e (diff)
downloadgcc-7aa5fb17a30ff0ce9928e5eac35b892d95e7eba5.zip
gcc-7aa5fb17a30ff0ce9928e5eac35b892d95e7eba5.tar.gz
gcc-7aa5fb17a30ff0ce9928e5eac35b892d95e7eba5.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/h8300/h8300-protos.h2
-rw-r--r--gcc/config/h8300/h8300.c20
-rw-r--r--gcc/config/h8300/shiftrotate.md153
3 files changed, 116 insertions, 59 deletions
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index 86bcc3f..744337d 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 0fdc68b..d2f6548 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 c5d32cd..0476324 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, <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
@@ -204,24 +177,43 @@
[(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))]
""
@@ -257,24 +249,41 @@
[(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))]
""
@@ -310,9 +319,55 @@
[(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"