https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126199
Bug ID: 126199
Summary: [SH] Add redundancy elimination via value numbering
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: olegendo at gcc dot gnu.org
Target Milestone: ---
On SH1 and SH2 there are no dynamic shifts and it supports a couple of shift
insn by a constant like 1, 2, 4, 8, 16. Operations for other shift amounts
need to use "shift stitching". If there are multiple shift operations that use
the same source operand, some of the intermediate values could be re-used, but
currently are not.
This has been noted before
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54089#c29
Another, similar case where re-using (intermediate) values would be beneficial:
extern void h (void *, ...);
extern void i (int);
void j (void)
{
unsigned a, b, c, d, e;
char f;
h (j, "", 0, &a, 0, &b, &d, 0, 0, 0, &e, 0, 0, &f, 0, 0, 0, 0, 0, 0);
c = a;
i (8 * c);
h (0, c, 8 * c);
}
compiled with "-O2 -m2 -ml" contains the following sequence:
mov.l r2,@(36,r15)
mov r15,r2
add #88,r2 // r2 = r15 + 88
mov.l r2,@(24,r15)
mov r15,r2
mov.l .L3,r8
add #84,r2 // r2 = r15 + 84
mov.l r2,@(8,r15)
the 2nd computation of "r2 = r15 + 84" can be optimized to re-use the previous
value of r2.
As for the shifts instructions (and similar cases), those are formed during
combine + following split1 pass.
The stack-frame related example arises only after RA.
I think on SH it would make sense to run a CSE(-like) pass after
combine+split1, before RA and once more after RA to catch those cases.
In fact, in PR 54089 attachment 55543 a similar thing has been tried and showed
beneficial: run a pass after combine+split1 to hoist newly formed (shift)
constant loads out of loops.
Other backends might also benefit from this.