So in this patch we're correcting a failure to mark objects live in
scenarios like
(set (dest) (plus (dest) (src))
When handling set pseudos, we transfer the liveness information from
LIVENOW into LIVE_TMP. LIVE_TMP is subsequently used to narrow what bit
groups are live for the inputs.
The first time we process the block we may not have DEST in the LIVENOW
set (it may be live across the loop, but not live after the loop). Thus
we can totally miss making certain objects live, resulting in incorrect
code.
The fix is pretty simple. If LIVE_TMP is empty, then we should go ahead
and mark all the bit groups for the set object in LIVE_TMP. This also
removes an invalid gcc_assert on the state of the liveness bitmaps.
This showed up on pru, rl78 and/or msp430 in the testsuite. So no new test.
Bootstrapped and regression tested on x86_64 and also run through my
tester on all the cross platforms.
Pushing to the trunk.
jeff
commit ad642d2c950657539777ea436b787e7fff4ec09e
Author: Jeff Law <j...@ventanamicro.com>
Date: Mon Jul 22 21:48:28 2024 -0600
[5/n][PR rtl-optimization/115877] Fix handling of input/output operands
So in this patch we're correcting a failure to mark objects live in
scenarios
like
(set (dest) (plus (dest) (src))
When handling set pseudos, we transfer the liveness information from LIVENOW
into LIVE_TMP. LIVE_TMP is subsequently used to narrow what bit groups are
live for the inputs.
The first time we process the block we may not have DEST in the LIVENOW set
(it
may be live across the loop, but not live after the loop). Thus we can
totally
miss making certain objects live, resulting in incorrect code.
The fix is pretty simple. If LIVE_TMP is empty, then we should go ahead and
mark all the bit groups for the set object in LIVE_TMP. This also removes
an
invalid gcc_assert on the state of the liveness bitmaps.
This showed up on pru, rl78 and/or msp430 in the testsuite. So no new test.
Bootstrapped and regression tested on x86_64 and also run through my tester
on
all the cross platforms.
Pushing to the trunk.
PR rtl-optimization/115877
gcc/
* ext-dce.cc (ext_dce_process_sets): Reasonably handle input/output
operands.
(ext_dce_rd_transfer_n): Drop bogus assertion.
diff --git a/gcc/ext-dce.cc b/gcc/ext-dce.cc
index 21feabd9ce3..c56dfb505b8 100644
--- a/gcc/ext-dce.cc
+++ b/gcc/ext-dce.cc
@@ -245,13 +245,25 @@ ext_dce_process_sets (rtx_insn *insn, rtx obj, bitmap
live_tmp)
continue;
}
- /* Transfer all the LIVENOW bits for X into LIVE_TMP. */
+ /* LIVE_TMP contains the set groups that are live-out and set in
+ this insn. It is used to narrow the groups live-in for the
+ inputs of this insn.
+
+ The simple thing to do is mark all the groups as live, but
+ that will significantly inhibit optimization.
+
+ We also need to be careful in the case where we have an in-out
+ operand. If we're not careful we'd clear LIVE_TMP
+ incorrectly. */
HOST_WIDE_INT rn = REGNO (SUBREG_REG (x));
int limit = group_limit (SUBREG_REG (x));
for (HOST_WIDE_INT i = 4 * rn; i < 4 * rn + limit; i++)
if (bitmap_bit_p (livenow, i))
bitmap_set_bit (live_tmp, i);
+ if (bitmap_empty_p (live_tmp))
+ make_reg_live (live_tmp, rn);
+
/* The mode of the SUBREG tells us how many bits we can
clear. */
machine_mode mode = GET_MODE (x);
@@ -316,14 +328,25 @@ ext_dce_process_sets (rtx_insn *insn, rtx obj, bitmap
live_tmp)
/* Now handle the actual object that was changed. */
if (REG_P (x))
{
- /* Transfer the appropriate bits from LIVENOW into
- LIVE_TMP. */
+ /* LIVE_TMP contains the set groups that are live-out and set in
+ this insn. It is used to narrow the groups live-in for the
+ inputs of this insn.
+
+ The simple thing to do is mark all the groups as live, but
+ that will significantly inhibit optimization.
+
+ We also need to be careful in the case where we have an in-out
+ operand. If we're not careful we'd clear LIVE_TMP
+ incorrectly. */
HOST_WIDE_INT rn = REGNO (x);
int limit = group_limit (x);
for (HOST_WIDE_INT i = 4 * rn; i < 4 * rn + limit; i++)
if (bitmap_bit_p (livenow, i))
bitmap_set_bit (live_tmp, i);
+ if (bitmap_empty_p (live_tmp))
+ make_reg_live (live_tmp, rn);
+
/* Now clear the bits known written by this instruction.
Note that BIT need not be a power of two, consider a
ZERO_EXTRACT destination. */
@@ -935,8 +958,6 @@ ext_dce_rd_transfer_n (int bb_index)
the generic dataflow code that something changed. */
if (!bitmap_equal_p (&livein[bb_index], livenow))
{
- gcc_assert (!bitmap_intersect_compl_p (&livein[bb_index], livenow));
-
bitmap_copy (&livein[bb_index], livenow);
return true;
}