aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <jeffreyalaw@gmail.com>2021-06-22 15:25:11 -0400
committerJeff Law <jeffreyalaw@gmail.com>2021-06-23 10:18:30 -0400
commit402c818ac0b19d168e9ffc0b3413344dd6020f6a (patch)
tree8e0bb68651a33f643a3abba12f8dec90d3e836b6 /gcc
parent37e93925366676201b526624e9f8dc32d82b4ff2 (diff)
downloadgcc-402c818ac0b19d168e9ffc0b3413344dd6020f6a.zip
gcc-402c818ac0b19d168e9ffc0b3413344dd6020f6a.tar.gz
gcc-402c818ac0b19d168e9ffc0b3413344dd6020f6a.tar.bz2
Use more logicals to eliminate useless test/compare instructions
gcc/ * config/h8300/logical.md (<code><mode>3<ccnz>): Use <cczn> so this pattern can be used for test/compare removal. Pass current insn to compute_logical_op_length and output_logical_op. * config/h8300/h8300.c (compute_logical_op_cc): Remove. (h8300_and_costs): Add argument to compute_logical_op_length. (output_logical_op): Add new argument. Use it to determine if the condition codes are used and adjust the output accordingly. (compute_logical_op_length): Add new argument and update length computations when condition codes are used. * config/h8300/h8300-protos.h (compute_logical_op_length): Update prototype. (output_logical_op): Likewise.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/h8300/h8300-protos.h7
-rw-r--r--gcc/config/h8300/h8300.c136
-rw-r--r--gcc/config/h8300/logical.md7
3 files changed, 55 insertions, 95 deletions
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index af65329..d7efa97 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -36,10 +36,11 @@ extern const char *output_simode_bld (int, rtx[]);
extern void final_prescan_insn (rtx_insn *, rtx *, int);
extern int h8300_expand_movsi (rtx[]);
extern machine_mode h8300_select_cc_mode (RTX_CODE, rtx, rtx);
-extern const char *output_logical_op (machine_mode, rtx_code code, rtx *);
-extern unsigned int compute_logical_op_length (machine_mode, rtx_code, rtx *);
+extern const char *output_logical_op (machine_mode, rtx_code code,
+ rtx *, rtx_insn *);
+extern unsigned int compute_logical_op_length (machine_mode, rtx_code,
+ rtx *, rtx_insn *);
-extern int compute_logical_op_cc (machine_mode, rtx *);
extern int compute_a_shift_cc (rtx, rtx *);
#ifdef HAVE_ATTR_cc
extern enum attr_cc compute_plussi_cc (rtx *);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 2b88325..511c2b2 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -1100,7 +1100,7 @@ h8300_and_costs (rtx x)
operands[1] = XEXP (x, 0);
operands[2] = XEXP (x, 1);
operands[3] = x;
- return compute_logical_op_length (GET_MODE (x), AND, operands) / 2;
+ return compute_logical_op_length (GET_MODE (x), AND, operands, NULL) / 2;
}
/* Compute the cost of a shift insn. */
@@ -2881,7 +2881,7 @@ compute_plussi_cc (rtx *operands)
/* Output a logical insn. */
const char *
-output_logical_op (machine_mode mode, rtx_code code, rtx *operands)
+output_logical_op (machine_mode mode, rtx_code code, rtx *operands, rtx_insn *insn)
{
/* Pretend that every byte is affected if both operands are registers. */
const unsigned HOST_WIDE_INT intval =
@@ -2906,6 +2906,19 @@ output_logical_op (machine_mode mode, rtx_code code, rtx *operands)
const char *opname;
char insn_buf[100];
+ /* INSN is the current insn, we examine its overall form to see if we're
+ supposed to set or clobber the condition codes.
+
+ This is important to know. If we are setting condition codes, then we
+ must do the operation in MODE and not in some smaller size.
+
+ The key is to look at the second object in the PARALLEL. If it is not
+ a CLOBBER, then we care about the condition codes. */
+ rtx pattern = PATTERN (insn);
+ gcc_assert (GET_CODE (pattern) == PARALLEL);
+ rtx second_op = XVECEXP (pattern, 0, 1);
+ bool cc_meaningful = (GET_CODE (second_op) != CLOBBER);
+
switch (code)
{
case AND:
@@ -2928,8 +2941,9 @@ output_logical_op (machine_mode mode, rtx_code code, rtx *operands)
output_asm_insn (insn_buf, operands);
break;
case E_HImode:
- /* First, see if we can finish with one insn. */
- if (b0 != 0 && b1 != 0)
+ /* First, see if we can (or must) finish with one insn. */
+ if (cc_meaningful
+ || (b0 != 0 && b1 != 0))
{
sprintf (insn_buf, "%s.w\t%%T2,%%T0", opname);
output_asm_insn (insn_buf, operands);
@@ -2964,10 +2978,11 @@ output_logical_op (machine_mode mode, rtx_code code, rtx *operands)
/* Check if doing everything with one insn is no worse than
using multiple insns. */
- if (w0 != 0 && w1 != 0
- && !(lower_half_easy_p && upper_half_easy_p)
- && !(code == IOR && w1 == 0xffff
- && (w0 & 0x8000) != 0 && lower_half_easy_p))
+ if (cc_meaningful
+ || (w0 != 0 && w1 != 0
+ && !(lower_half_easy_p && upper_half_easy_p)
+ && !(code == IOR && w1 == 0xffff
+ && (w0 & 0x8000) != 0 && lower_half_easy_p)))
{
sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname);
output_asm_insn (insn_buf, operands);
@@ -3037,7 +3052,7 @@ output_logical_op (machine_mode mode, rtx_code code, rtx *operands)
/* Compute the length of a logical insn. */
unsigned int
-compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands)
+compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands, rtx_insn *insn)
{
/* Pretend that every byte is affected if both operands are registers. */
const unsigned HOST_WIDE_INT intval =
@@ -3061,6 +3076,23 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands)
/* Insn length. */
unsigned int length = 0;
+ /* INSN is the current insn, we examine its overall form to see if we're
+ supposed to set or clobber the condition codes.
+
+ This is important to know. If we are setting condition codes, then we
+ must do the operation in MODE and not in some smaller size.
+
+ The key is to look at the second object in the PARALLEL. If it is not
+ a CLOBBER, then we care about the condition codes. */
+ bool cc_meaningful = false;
+ if (insn)
+ {
+ rtx pattern = PATTERN (insn);
+ gcc_assert (GET_CODE (pattern) == PARALLEL);
+ rtx second_op = XVECEXP (pattern, 0, 1);
+ cc_meaningful = (GET_CODE (second_op) != CLOBBER);
+ }
+
switch (mode)
{
case E_QImode:
@@ -3068,7 +3100,8 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands)
case E_HImode:
/* First, see if we can finish with one insn. */
- if (b0 != 0 && b1 != 0)
+ if (cc_meaningful
+ || (b0 != 0 && b1 != 0))
{
length = h8300_length_from_table (operands[1], operands[2],
&logicw_length_table);
@@ -3098,10 +3131,11 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands)
/* Check if doing everything with one insn is no worse than
using multiple insns. */
- if (w0 != 0 && w1 != 0
- && !(lower_half_easy_p && upper_half_easy_p)
- && !(code == IOR && w1 == 0xffff
- && (w0 & 0x8000) != 0 && lower_half_easy_p))
+ if (cc_meaningful
+ || (w0 != 0 && w1 != 0
+ && !(lower_half_easy_p && upper_half_easy_p)
+ && !(code == IOR && w1 == 0xffff
+ && (w0 & 0x8000) != 0 && lower_half_easy_p)))
{
length = h8300_length_from_table (operands[1], operands[2],
&logicl_length_table);
@@ -3158,80 +3192,6 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands)
return length;
}
-/* Compute which flag bits are valid after a logical insn. */
-
-int
-compute_logical_op_cc (machine_mode mode, rtx *operands)
-{
- /* Figure out the logical op that we need to perform. */
- enum rtx_code code = GET_CODE (operands[3]);
- /* Pretend that every byte is affected if both operands are registers. */
- const unsigned HOST_WIDE_INT intval =
- (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
- /* Always use the full instruction if the
- first operand is in memory. It is better
- to use define_splits to generate the shorter
- sequence where valid. */
- && register_operand (operands[1], VOIDmode)
- ? INTVAL (operands[2]) : 0x55555555);
- /* The determinant of the algorithm. If we perform an AND, 0
- affects a bit. Otherwise, 1 affects a bit. */
- const unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
- /* Break up DET into pieces. */
- const unsigned HOST_WIDE_INT b0 = (det >> 0) & 0xff;
- const unsigned HOST_WIDE_INT b1 = (det >> 8) & 0xff;
- const unsigned HOST_WIDE_INT w0 = (det >> 0) & 0xffff;
- const unsigned HOST_WIDE_INT w1 = (det >> 16) & 0xffff;
- int lower_half_easy_p = 0;
- int upper_half_easy_p = 0;
- /* Condition code. */
- enum attr_old_cc cc = OLD_CC_CLOBBER;
-
- switch (mode)
- {
- case E_HImode:
- /* First, see if we can finish with one insn. */
- if (b0 != 0 && b1 != 0)
- {
- cc = OLD_CC_SET_ZNV;
- }
- break;
- case E_SImode:
- /* Determine if the lower half can be taken care of in no more
- than two bytes. */
- lower_half_easy_p = (b0 == 0
- || b1 == 0
- || (code != IOR && w0 == 0xffff));
-
- /* Determine if the upper half can be taken care of in no more
- than two bytes. */
- upper_half_easy_p = ((code != IOR && w1 == 0xffff)
- || (code == AND && w1 == 0xff00));
-
- /* Check if doing everything with one insn is no worse than
- using multiple insns. */
- if (w0 != 0 && w1 != 0
- && !(lower_half_easy_p && upper_half_easy_p)
- && !(code == IOR && w1 == 0xffff
- && (w0 & 0x8000) != 0 && lower_half_easy_p))
- {
- cc = OLD_CC_SET_ZNV;
- }
- else
- {
- if (code == IOR
- && w1 == 0xffff
- && (w0 & 0x8000) != 0)
- {
- cc = OLD_CC_SET_ZNV;
- }
- }
- break;
- default:
- gcc_unreachable ();
- }
- return cc;
-}
#if 0
/* Expand a conditional branch. */
diff --git a/gcc/config/h8300/logical.md b/gcc/config/h8300/logical.md
index 07d36cf..f07c79e 100644
--- a/gcc/config/h8300/logical.md
+++ b/gcc/config/h8300/logical.md
@@ -251,17 +251,16 @@
(logicals:QHSI (match_dup 1) (match_dup 2)))
(clobber (reg:CC CC_REG))])])
-(define_insn "*<code><mode>3_clobber_flags"
+(define_insn "*<code><mode>3<cczn>"
[(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
(logicals:QHSI
(match_operand:QHSI 1 "h8300_dst_operand" "%0")
(match_operand:QHSI 2 "h8300_src_operand" "rQi")))
(clobber (reg:CC CC_REG))]
"h8300_operands_match_p (operands)"
- { return output_logical_op (<MODE>mode, <CODE>, operands); }
+ { return output_logical_op (<MODE>mode, <CODE>, operands, insn); }
[(set (attr "length")
- (symbol_ref "compute_logical_op_length (<MODE>mode, <CODE>, operands)"))])
-
+ (symbol_ref "compute_logical_op_length (<MODE>mode, <CODE>, operands, insn)"))])
;; ----------------------------------------------------------------------
;; NOT INSTRUCTIONS