aboutsummaryrefslogtreecommitdiff
path: root/gcc/cse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cse.cc')
-rw-r--r--gcc/cse.cc15
1 files changed, 13 insertions, 2 deletions
diff --git a/gcc/cse.cc b/gcc/cse.cc
index 70d5caa..7bdd3b0 100644
--- a/gcc/cse.cc
+++ b/gcc/cse.cc
@@ -6762,7 +6762,18 @@ cse_main (rtx_insn *f ATTRIBUTE_UNUSED, int nregs)
modify the liveness of DEST.
DEST is set to pc_rtx for a trapping insn, or for an insn with side effects.
We must then count uses of a SET_DEST regardless, because the insn can't be
- deleted here. */
+ deleted here.
+ Also count uses of a SET_DEST if it has been used by an earlier insn,
+ but in that case only when incrementing and not when decrementing, effectively
+ making setters of such a pseudo non-eliminable. This is for cases like
+ (set (reg x) (expr))
+ ...
+ (set (reg y) (expr (reg (x))))
+ ...
+ (set (reg x) (expr (reg (x))))
+ where we can't eliminate the last insn because x is is still used, if y
+ is unused we can eliminate the middle insn and when considering the first insn
+ we used to eliminate it despite it being used in the last insn. */
static void
count_reg_usage (rtx x, int *counts, rtx dest, int incr)
@@ -6778,7 +6789,7 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
switch (code = GET_CODE (x))
{
case REG:
- if (x != dest)
+ if (x != dest || (incr > 0 && counts[REGNO (x)]))
counts[REGNO (x)] += incr;
return;