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.