https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106594
Bug ID: 106594
Summary: [13 Regression] sign-extensions no longer merged into
addressing mode
Product: gcc
Version: 13.0
Status: UNCONFIRMED
Keywords: missed-optimization
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: tnfchris at gcc dot gnu.org
Target Milestone: ---
Target: aarch64*
Since around the 5th of August (need to bisect) we no longer generate
addressing modes on load merging the sign extends.
The following example:
extern const int constellation_64qam[64];
void foo(int nbits,
const char *p_src,
int *p_dst) {
while (nbits > 0U) {
char first = *p_src++;
char index1 = ((first & 0x3) << 4) | (first >> 4);
*p_dst++ = constellation_64qam[index1];
nbits--;
}
}
used to generate
orr w3, w4, w3, lsr 4
ldr w3, [x6, w3, sxtw 2]
and now generates:
orr w0, w4, w0, lsr 4
sxtw x0, w0
ldr w0, [x6, x0, lsl 2]
at -O2 (-O1 seems to still be fine). This is causing a regression in perf in
some of our libraries.
Looks like there's a change in how the operation is expressed. It used to be
first_17 = *p_src_28;
_1 = (int) first_17;
_2 = _1 << 4;
_3 = (signed char) _2;
where the shift is done as an int, whereas now it's
first_16 = *p_src_27;
first.1_1 = (signed char) first_16;
_2 = first.1_1 << 4;