https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108640
Mikael Pettersson <mikpelinux at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |mikpelinux at gmail dot com --- Comment #5 from Mikael Pettersson <mikpelinux at gmail dot com> --- Further reduced test case: > cat pr108640v2.i int x; void iorsi3(void) { x |= (1 << 16); } > gcc/xgcc -Bgcc -O1 -S pr108640v2.i during RTL pass: final ../pr108640v2.i: In function 'iorsi3': ../pr108640v2.i:2:38: internal compiler error: in change_address_1, at emit-rtl.cc:2299 2 | void iorsi3(void) { x |= (1 << 16); } | ^ 0x40dc15 change_address_1 /mnt/scratch/other/mikpe-gcc.git/gcc/emit-rtl.cc:2299 0x668f79 adjust_address_1(rtx_def*, machine_mode, poly_int<1u, long>, int, int, int, poly_int<1u, long>) /mnt/scratch/other/mikpe-gcc.git/gcc/emit-rtl.cc:2433 0xd3ae93 output_iorsi3(rtx_def**) /mnt/scratch/other/mikpe-gcc.git/gcc/config/m68k/m68k.cc:5513 ... In output_iorsi3() the m68k backend wants to change "x |= (1 << 16)" to "*(((char *) &x) + 1) |= 1". It calls adjust_address() to offset x by 1, but it keeps the mode as SImode (4-byte). This address expr reaches m68k_legitimate_constant_address_p(). On the uclinux target M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P is 1 so it calls offset_within_block_p(x, 4) which fails because that is out of bounds, causing the assert in change_address_1() to fail. The other m68k targets don't define M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P so this works there. The bug is that the adjust_address() call should have specified QImode as mode since the resulting address is to be used in a 1-byte RMW operation. It gets it right in the nearby code which rewrites to a HImode (2-byte) RMW. output_andsi3() and output_xorsi3() have the exact same bug. I have a patch.