On Fri, Apr 04, 2025 at 03:06:52PM +0100, Richard Sandiford wrote: > > 2025-04-04 Jakub Jelinek <ja...@redhat.com> > > > > PR rtl-optimization/119594 > > * cse.cc (count_reg_usage): If INCR is 0, increment by 1 counts > > of encountered REGs equal to dest rather than incrementing by INCR > > counts of REGs not equal to dest. > > (delete_trivially_dead_insns): For kept non-DEBUG instructions > > call count_reg_usage with INCR 0. > > > > * gcc.dg/pr119594.c: New test.
This bootstrapped/regtested successfully on x86_64-linux and i686-linux. > ...this looks ok to me as well. The reason for suggesting DF_INSN_USES > was that I thought it might be faster, and since it would be ok in that > context to err on the side of counting, without the precision needed > by count_reg_usage. > > On the PARALLEL thing: maybe at this stage it would be better to do the > minimum. Not a strong opinion though. > > So OK from my POV, but please give others time to comment. Though, Eric's version (slightly tweaked) seems to work on the testcase fine as well and is cheaper. Shall we go with that (if it passes bootstrap/regtest)? 2025-04-04 Eric Botcazou <botca...@adacore.com> Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/119594 * cse.cc (count_reg_usage): Count even x == dest regs if they have non-zero counts already and incr is positive. * gcc.dg/pr119594.c: New test. --- gcc/cse.cc.jj 2025-04-04 17:09:41.323742890 +0200 +++ gcc/cse.cc 2025-04-04 18:48:52.228927380 +0200 @@ -6762,7 +6762,18 @@ cse_main (rtx_insn *f ATTRIBUTE_UNUSED, 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 switch (code = GET_CODE (x)) { case REG: - if (x != dest) + if (x != dest || (incr > 0 && counts[REGNO (x)])) counts[REGNO (x)] += incr; return; --- gcc/testsuite/gcc.dg/pr119594.c.jj 2025-04-03 14:19:35.444575677 +0200 +++ gcc/testsuite/gcc.dg/pr119594.c 2025-04-03 14:19:13.962871101 +0200 @@ -0,0 +1,32 @@ +/* PR rtl-optimization/119594 */ +/* { dg-do run } */ +/* { dg-options "-Os -fno-dce -fno-tree-dce -fno-tree-dse" } */ + +int a, b; +static unsigned c = -1; + +void +foo (int e) +{ + a = a ^ e; +} + +void +bar (long e) +{ + foo (e >> 1); +} + +int +main () +{ + int g[2]; + for (int h = 0; h < 2; h++) + g[h] = -1; + for (; b; b++) + ; + g[1] = 0; + bar (c); + if (!a) + __builtin_abort (); +} Jakub