public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/riscv/heads/ext-dce)] Add more comments. Fix various formatting problems. Add extensions as safe to propagate through.
@ 2023-11-15 19:01 Jeff Law
0 siblings, 0 replies; only message in thread
From: Jeff Law @ 2023-11-15 19:01 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:c3fda9f9af9749c46f7d60e62b598427ae05a77f
commit c3fda9f9af9749c46f7d60e62b598427ae05a77f
Author: Jeff Law <jlaw@ventanamicro.com>
Date: Wed Nov 15 11:58:09 2023 -0700
Add more comments. Fix various formatting problems. Add extensions as safe to propagate through.
Diff:
---
gcc/ext-dce.cc | 450 ++++++++++++++++++++++++++++++---------------------------
1 file changed, 234 insertions(+), 216 deletions(-)
diff --git a/gcc/ext-dce.cc b/gcc/ext-dce.cc
index 8a91f1ebbfc..9cf0a3c2ae3 100644
--- a/gcc/ext-dce.cc
+++ b/gcc/ext-dce.cc
@@ -60,6 +60,8 @@ safe_for_live_propagation (rtx_code code)
case NOT:
case PLUS:
case MULT:
+ case ZERO_EXTEND:
+ case SIGN_EXTEND:
/* ?!? These should be double-checked. */
case MINUS:
@@ -265,7 +267,7 @@ ext_dce_try_optimize_insn (rtx_insn *insn, rtx set, bitmap changed_pseudos)
/* Some operators imply that their second operand is fully live,
regardless of how many bits in the output are live. An example
would be the shift count on a target without SHIFT_COUNT_TRUCATED
- defined.
+ defined.
Return TRUE if CODE is such an operator. FALSE otherwise. */
@@ -307,250 +309,266 @@ ext_dce_process_uses (rtx_insn *insn, bitmap livenow, bitmap live_tmp,
bitmap_set_range (livenow, HARD_FRAME_POINTER_REGNUM * 4, 4);
}
- for (rtx pat = PATTERN (insn);;)
+ restart:
+ subrtx_var_iterator::array_type array_var;
+ rtx pat = PATTERN (insn);
+ FOR_EACH_SUBRTX_VAR (iter, array_var, pat, NONCONST)
{
- subrtx_var_iterator::array_type array_var;
- FOR_EACH_SUBRTX_VAR (iter, array_var, pat, NONCONST)
+ /* An EXPR_LIST (from call fusage) ends in NULL_RTX. */
+ rtx x = *iter;
+ if (x == NULL_RTX)
+ continue;
+
+ /* So the basic idea in this FOR_EACH_SUBRTX_VAR loop is to
+ handle SETs explicitly, possibly propagating live information
+ into the uses.
+
+ We may continue the loop at various points which will cause
+ iteration into the next level of RTL. Breaking from the loop
+ is never safe as it can lead us to fail to process some of the
+ RTL and thus not make objects live when necessary. */
+ enum rtx_code xcode = GET_CODE (x);
+ if (GET_CODE (x) == SET)
{
- rtx x = *iter;
- /* An EXPR_LIST (from call fusage) ends in NULL_RTX. */
- if (x == NULL_RTX)
- continue;
- enum rtx_code xcode = GET_CODE (x);
+ const_rtx dst = SET_DEST (x);
+ rtx src = SET_SRC (x);
+ const_rtx y;
+ unsigned HOST_WIDE_INT bit = 0;
+
+ /* The code of the RHS of a SET. */
+ enum rtx_code code = GET_CODE (src);
- if (GET_CODE (x) == SET)
+ /* ?!? How much of this should mirror SET handling, potentially
+ being shared? */
+ if (SUBREG_P (dst))
{
- const_rtx dst = SET_DEST (x);
- rtx src = SET_SRC (x);
- const_rtx y;
- unsigned HOST_WIDE_INT bit = 0;
- enum rtx_code code = GET_CODE (src);
-
- /* ?!? How much of this should mirror SET handling, potentially
- being shared? */
- if (SUBREG_P (dst))
- {
- bit = SUBREG_BYTE (dst).to_constant () * BITS_PER_UNIT;
- if (WORDS_BIG_ENDIAN)
- bit = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (dst))).to_constant ()
- - GET_MODE_BITSIZE (GET_MODE (dst)).to_constant () - bit);
- if (bit >= HOST_BITS_PER_WIDE_INT)
- bit = HOST_BITS_PER_WIDE_INT - 1;
- dst = SUBREG_REG (dst);
- }
- else if (GET_CODE (dst) == ZERO_EXTRACT
- || GET_CODE (dst) == STRICT_LOW_PART)
- dst = XEXP (dst, 0);
-
- /* Main processing of the uses. Two major goals here.
-
- First, we want to try and propagate liveness (or the lack
- thereof) from the destination register to the source
- register(s).
-
- Second, if the source is an extension, try to optimize
- it into a SUBREG. The SUBREG form indicates we don't
- care about the upper bits and will usually be copy
- propagated away. */
- /* ?!? What to do with SUBREGs that aren't REGS? */
- if (REG_P (dst) && safe_for_live_propagation (code))
- {
- /* Create a mask representing the bits of this output
- operand that are live after this insn. We can use
- this information to refine the live in state of
- inputs to this insn.
-
- We have to do this on a per SET basis, we might have
- an INSN with multiple SETS, some of which can narrow
- the source operand liveness, some of which may not. */
- unsigned HOST_WIDE_INT dst_mask = 0;
- HOST_WIDE_INT rn = REGNO (dst);
- unsigned HOST_WIDE_INT mask_array[]
- = { 0xff, 0xff00, 0xffff0000ULL, -0x100000000ULL };
- for (int i = 0; i < 4; i++)
- if (bitmap_bit_p (live_tmp, 4 * rn + i))
- dst_mask |= mask_array[i];
- dst_mask >>= bit;
-
- /* ??? Could also handle ZERO_EXTRACT / SIGN_EXTRACT
- of the source specially to improve optimization. */
- if (code == SIGN_EXTEND || code == ZERO_EXTEND)
- {
- rtx inner = XEXP (src, 0);
- unsigned HOST_WIDE_INT src_mask
- = GET_MODE_MASK (GET_MODE (inner));
+ bit = SUBREG_BYTE (dst).to_constant () * BITS_PER_UNIT;
+ if (WORDS_BIG_ENDIAN)
+ bit = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (dst))).to_constant ()
+ - GET_MODE_BITSIZE (GET_MODE (dst)).to_constant () - bit);
+ if (bit >= HOST_BITS_PER_WIDE_INT)
+ bit = HOST_BITS_PER_WIDE_INT - 1;
+ dst = SUBREG_REG (dst);
+ }
+ else if (GET_CODE (dst) == ZERO_EXTRACT
+ || GET_CODE (dst) == STRICT_LOW_PART)
+ dst = XEXP (dst, 0);
-#if 0
- /* ?!? This seems like it shouldn't be necessary. */
- /* Pretend there is one additional higher bit set in
- MASK2 to account for the sign bit propagation from the
- input value into the output value. */
- if (code == SIGN_EXTEND)
- {
- src_mask <<= 1;
- src_mask |= 1;
- }
-#endif
+ /* Main processing of the uses. Two major goals here.
- /* (subreg (mem)) is technically valid RTL, but is
- severely discouraged. So give up if we're about to
- create one.
+ First, we want to try and propagate liveness (or the lack
+ thereof) from the destination register to the source
+ register(s).
- If this were to be loosened, then we'd still need to
- reject mode dependent addresses and volatile memory
- accesses. */
- if (!REG_P (inner))
- continue;
+ Second, if the source is an extension, try to optimize
+ it into a SUBREG. The SUBREG form indicates we don't
+ care about the upper bits and will usually be copy
+ propagated away.
- /* DST_MASK could be zero if we had something in the SET
- that we couldn't handle. */
- if (modify && dst_mask && (dst_mask & ~src_mask) == 0)
- ext_dce_try_optimize_insn (insn, x, changed_pseudos);
+ If we fail to handle something in here, the expectation
+ is the iterator will dive into the sub-components and
+ mark all the chunks in any found REGs as live. */
+ if (REG_P (dst) && safe_for_live_propagation (code))
+ {
+ /* Create a mask representing the bits of this output
+ operand that are live after this insn. We can use
+ this information to refine the live in state of
+ inputs to this insn in many cases.
+
+ We have to do this on a per SET basis, we might have
+ an INSN with multiple SETS, some of which can narrow
+ the source operand liveness, some of which may not. */
+ unsigned HOST_WIDE_INT dst_mask = 0;
+ HOST_WIDE_INT rn = REGNO (dst);
+ unsigned HOST_WIDE_INT mask_array[]
+ = { 0xff, 0xff00, 0xffff0000ULL, -0x100000000ULL };
+ for (int i = 0; i < 4; i++)
+ if (bitmap_bit_p (live_tmp, 4 * rn + i))
+ dst_mask |= mask_array[i];
+ dst_mask >>= bit;
+
+ /* ??? Could also handle ZERO_EXTRACT / SIGN_EXTRACT
+ of the source specially to improve optimization. */
+ if (code == SIGN_EXTEND || code == ZERO_EXTEND)
+ {
+ rtx inner = XEXP (src, 0);
+ unsigned HOST_WIDE_INT src_mask
+ = GET_MODE_MASK (GET_MODE (inner));
- dst_mask &= src_mask;
- src = XEXP (src, 0);
- code = GET_CODE (src);
+#if 0
+ /* ?!? This seems like it shouldn't be necessary. */
+ /* Pretend there is one additional higher bit set in
+ MASK2 to account for the sign bit propagation from the
+ input value into the output value. */
+ if (code == SIGN_EXTEND)
+ {
+ src_mask <<= 1;
+ src_mask |= 1;
}
+#endif
+ /* (subreg (mem)) is technically valid RTL, but is
+ severely discouraged. So give up if we're about to
+ create one.
- /* ?!? What is the point of this adjustment to DST_MASK? */
- if (code == PLUS || code == MINUS || code == MULT
- || code == ASHIFT)
- dst_mask
- = dst_mask ? ((2ULL << floor_log2 (dst_mask)) - 1) : 0;
+ If this were to be loosened, then we'd still need to
+ reject mode dependent addresses and volatile memory
+ accesses. */
+ if (MEM_P (inner))
+ continue;
- /* We will handle the other operand of a binary operator
- at the bottom of the loop by resetting Y. */
- if (BINARY_P (src))
- y = XEXP (src, 0);
- else
- y = src;
+ /* DST_MASK could be zero if we had something in the SET
+ that we couldn't handle. */
+ if (modify && dst_mask && (dst_mask & ~src_mask) == 0)
+ ext_dce_try_optimize_insn (insn, x, changed_pseudos);
- for (;;)
- {
- if (paradoxical_subreg_p (y))
- y = SUBREG_REG (y);
- else if (SUBREG_P (y))
- {
- bit = (SUBREG_BYTE (y).to_constant ()
- * BITS_PER_UNIT);
- if (WORDS_BIG_ENDIAN)
- bit = (GET_MODE_BITSIZE
- (GET_MODE (SUBREG_REG (y))).to_constant ()
- - GET_MODE_BITSIZE (GET_MODE (y)).to_constant () - bit);
- if (dst_mask)
- {
- dst_mask <<= bit;
- if (!dst_mask)
- dst_mask = -0x100000000ULL;
- }
- y = SUBREG_REG (y);
- }
+ dst_mask &= src_mask;
+ src = XEXP (src, 0);
+ code = GET_CODE (src);
+ }
- if (REG_P (y))
- {
- rn = 4 * REGNO (y);
- unsigned HOST_WIDE_INT tmp_mask = dst_mask;
-
- if (!safe_for_live_propagation (code))
- tmp_mask = GET_MODE_MASK (GET_MODE (y));
-
- if (tmp_mask & 0xff)
- bitmap_set_bit (livenow, rn);
- if (tmp_mask & 0xff00)
- bitmap_set_bit (livenow, rn + 1);
- if (tmp_mask & 0xffff0000ULL)
- bitmap_set_bit (livenow, rn + 2);
- if (tmp_mask & -0x100000000ULL)
- bitmap_set_bit (livenow, rn + 3);
-
-
- /* Some operators imply their second operand
- is fully live. */
- if (binop_implies_op2_fully_live (code))
- {
- rtx x = XEXP (src, 1);
- if (GET_CODE (x) == SUBREG)
- x = SUBREG_REG (x);
- if (REG_P (x))
- {
- bitmap_set_range (livenow, REGNO (x) * 4, 4);
- break;
- }
- }
- }
- /* !?! This looks wrong. Y does not have to be a leaf
- here. Consider a shift-add as an example or a PLUS
- where one or both operands are sign/zero extended.
- Breaking out of the loop would cause us to fail to
- set liveness correctly. */
- else if (!CONSTANT_P (y))
+ /* Optimization is done at this point. We just want to make
+ sure everything that should get marked as live is marked
+ from here onward. */
+
+ /* ?!? What is the point of this adjustment to DST_MASK? */
+ if (code == PLUS || code == MINUS
+ || code == MULT || code == ASHIFT)
+ dst_mask
+ = dst_mask ? ((2ULL << floor_log2 (dst_mask)) - 1) : 0;
+
+ /* We will handle the other operand of a binary operator
+ at the bottom of the loop by resetting Y. */
+ if (BINARY_P (src))
+ y = XEXP (src, 0);
+ else
+ y = src;
+
+ /* We're inside a SET and want to process the source operands
+ making things live. Breaking from this loop will cause
+ the iterator to work on sub-rtxs, so it is safe to break
+ if we see something we don't know how to handle. */
+ for (;;)
+ {
+ if (paradoxical_subreg_p (y))
+ y = SUBREG_REG (y);
+ else if (SUBREG_P (y))
+ {
+ /* For anything but (subreg (reg)), break the inner loop
+ and process normally (conservatively). */
+ if (!REG_P (SUBREG_REG (y)))
break;
- /* We might have (ashift (const_int 1) (reg...)) */
- else if (CONSTANT_P (y)
- && binop_implies_op2_fully_live (GET_CODE (src)))
+ bit = (SUBREG_BYTE (y).to_constant () * BITS_PER_UNIT);
+ if (WORDS_BIG_ENDIAN)
+ bit = (GET_MODE_BITSIZE
+ (GET_MODE (SUBREG_REG (y))).to_constant ()
+ - GET_MODE_BITSIZE (GET_MODE (y)).to_constant () - bit);
+ if (dst_mask)
{
- rtx x = XEXP (src, 1);
- if (GET_CODE (x) == SUBREG)
- x = SUBREG_REG (x);
-
- if (REG_P (x))
- {
- bitmap_set_range (livenow, REGNO (x) * 4, 4);
- break;
- }
+ dst_mask <<= bit;
+ if (!dst_mask)
+ dst_mask = -0x100000000ULL;
}
- /* This looks wrong for ternary operators. */
- if (!BINARY_P (src))
- break;
- y = XEXP (src, 1), src = pc_rtx;
+ y = SUBREG_REG (y);
}
- if (REG_P (y) || CONSTANT_P (y))
- iter.skip_subrtxes ();
+ if (REG_P (y))
+ {
+ rn = 4 * REGNO (y);
+ unsigned HOST_WIDE_INT tmp_mask = dst_mask;
+
+ /* If the RTX code for the SET_SRC is not one we can
+ propagate destination liveness through, then just
+ set the mask to the mode's mask. */
+ if (!safe_for_live_propagation (code))
+ tmp_mask = GET_MODE_MASK (GET_MODE (y));
+
+ if (tmp_mask & 0xff)
+ bitmap_set_bit (livenow, rn);
+ if (tmp_mask & 0xff00)
+ bitmap_set_bit (livenow, rn + 1);
+ if (tmp_mask & 0xffff0000ULL)
+ bitmap_set_bit (livenow, rn + 2);
+ if (tmp_mask & -0x100000000ULL)
+ bitmap_set_bit (livenow, rn + 3);
+
+ /* Some operators imply their second operand
+ is fully live, break this inner loop which
+ will cause the iterator to descent into the
+ sub-rtxs which should be safe. */
+ if (binop_implies_op2_fully_live (code))
+ break;
+ }
+ else if (!CONSTANT_P (y))
+ break;
+ /* We might have (ashift (const_int 1) (reg...)) */
+ else if (CONSTANT_P (y)
+ && binop_implies_op2_fully_live (GET_CODE (src)))
+ break;
+
+ /* If this was anything but a binary operand, break the inner
+ loop. This is conservatively correct as it will cause the
+ iterator to look at the sub-rtxs. */
+ if (!BINARY_P (src))
+ break;
+
+ /* We processed the first operand of a binary operator. Now
+ handle the second. */
+ y = XEXP (src, 1), src = pc_rtx;
}
- else if (REG_P (dst))
- iter.substitute (src);
- }
- /* If we are reading the low part of a SUBREG, then we can
- refine liveness of the input register, otherwise let the
- iterator continue into SUBREG_REG. */
- else if (xcode == SUBREG
- && REG_P (SUBREG_REG (x))
- && subreg_lowpart_p (x)
- && GET_MODE_BITSIZE (GET_MODE (x)).to_constant () <= 32)
- {
- HOST_WIDE_INT size
- = GET_MODE_BITSIZE (GET_MODE (x)).to_constant ();
-
- HOST_WIDE_INT rn = 4 * REGNO (SUBREG_REG (x));
-
- bitmap_set_bit (livenow, rn);
- if (size > 8)
- bitmap_set_bit (livenow, rn+1);
- if (size > 16)
- bitmap_set_bit (livenow, rn+2);
- if (size > 32)
- bitmap_set_bit (livenow, rn+3);
- iter.skip_subrtxes ();
+
+ if (REG_P (y) || CONSTANT_P (y))
+ iter.skip_subrtxes ();
}
- else if (REG_P (x))
- bitmap_set_range (livenow, REGNO (x) * 4, 4);
- else if (GET_CODE (x) == CLOBBER)
- continue;
+ else if (REG_P (dst))
+ iter.substitute (src);
}
- if (GET_CODE (insn) != CALL_INSN || seen_fusage)
- break;
- pat = CALL_INSN_FUNCTION_USAGE (insn);
+ /* If we are reading the low part of a SUBREG, then we can
+ refine liveness of the input register, otherwise let the
+ iterator continue into SUBREG_REG. */
+ else if (xcode == SUBREG
+ && REG_P (SUBREG_REG (x))
+ && subreg_lowpart_p (x)
+ && GET_MODE_BITSIZE (GET_MODE (x)).to_constant () <= 32)
+ {
+ HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (x)).to_constant ();
+ HOST_WIDE_INT rn = 4 * REGNO (SUBREG_REG (x));
+
+ bitmap_set_bit (livenow, rn);
+ if (size > 8)
+ bitmap_set_bit (livenow, rn + 1);
+ if (size > 16)
+ bitmap_set_bit (livenow, rn + 2);
+ if (size > 32)
+ bitmap_set_bit (livenow, rn + 3);
+ iter.skip_subrtxes ();
+ }
+ /* If we have a register reference that is not otherwise handled,
+ just assume all the chunks are live. */
+ else if (REG_P (x))
+ bitmap_set_range (livenow, REGNO (x) * 4, 4);
+ }
+
+ /* A bit of special handling for CALL_INSNs. We need to look
+ at their fusage as well as set some implicit references. */
+ if (GET_CODE (insn) == CALL_INSN && !seen_fusage)
+ {
+ /* We only need to do this processing once per call. */
seen_fusage = true;
+
if (!FAKE_CALL_P (insn))
bitmap_set_range (livenow, STACK_POINTER_REGNUM * 4, 4);
- /* Unless this is a call to a const function, it can read any
- global register. */
- if (RTL_CONST_CALL_P (insn))
+
+ /* If this is not a call to a const fucntion, then assume it
+ can read any global register. */
+ if (!RTL_CONST_CALL_P (insn))
for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i])
bitmap_set_range (livenow, i * 4, 4);
+
+ /* Process CALL_INSN_USAGE. */
+ pat = CALL_INSN_FUNCTION_USAGE (insn);
+ goto restart;
}
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-11-15 19:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-15 19:01 [gcc(refs/vendors/riscv/heads/ext-dce)] Add more comments. Fix various formatting problems. Add extensions as safe to propagate through Jeff Law
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).