https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99114
Bug ID: 99114
Summary: [WORD_REGISTER_OPERATIONS] wrong code for (u16_var &
3) == (u32)1
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: pipcet at gmail dot com
Target Milestone: ---
I was seeing a miscompilation issue with my wasm32 backend (which was
somewhat difficult to track down because it was actually the
cross-compiled native compiler miscompiling JIT code).
The symptom is that combine.c replaces the correct RTL
(gtu (and:SI (subreg:SI (reg:HI 593)) (const_int 3))
(const_int 1))
with the incorrect RTL
(gtu (subreg:SI (reg:HI 593)) (const_int 1))
when reg:HI 593 is known to be <= 3.
The culprit is this code, in combine.c:
op0 = simplify_gen_binary (AND, tmode,
SUBREG_REG (XEXP (op0, 0)),
gen_int_mode (c1, tmode));
op0 = gen_lowpart (mode, op0);
The assumption here is that op0 will be an (and:HI) after the first
statement (and we assume (subreg:SI (and:HI ... (const_int 3))) is
defined because of WORD_REGISTER_OPERATIONS) but it's actually
simplified to be just the (reg:HI 593), and (subreg:SI (reg:HI 593))
is not defined.
I'm unsure whether this can cause wrong code for in-tree backends or backends
which don't define WORD_REGISTER_OPERATIONS.