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.

Reply via email to