https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99089
Bug ID: 99089 Summary: unnecessary zero extend before AND Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: wilson at gcc dot gnu.org Target Milestone: --- Given this testcase extracted from newlib struct s { short s; int i; }; extern void sub2 (void); extern void sub3 (void); int sub (struct s* t) { short i = t->s; if ((i & 0x8) == 0) t->s |= 0x800; if ((t->s & 0x3) == 0) sub3 (); t->i = i; return 0; } compiling for riscv32-elf with -O2 -S and looking at assembly code, I see two places where we have slli a5,a5,16 srli a5,a5,16 andi a5,a5,3 The zero extend before the AND is clearly unnecessary. It seems a complex set of circumstances leads to here. The tree level optimizer extends the lifetime of the first zero extend into a phi, which means the operation is split across basic blocks. This also means no REG_DEAD note and no combine. It isn't until 309 bbro that the zero extend and AND end up back in the same basic block again, and that is too late to optimize it as nothing after 309 bbro can fix this. So it appears we need a global rtl pass that can notice and fix redundant zero extends feeding into AND operations across basic blocks.