https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112398
--- Comment #8 from Jeffrey A. Law <law at gcc dot gnu.org> --- So Alexey's patch helps the first case, generating the more efficient lbu+xori sequence. I suspect it's not helping the 2nd case because the constant is going to be out of range. Given the 2nd case also suffers from a lack of HI->DI zero extension, there is some budget to improve that code. If someone wanted to tackle that, be my guest. But be aware that with Zbb enabled the code as it stands is probably optimal. Hints for anyone wanting to tackle the second testcase. You'll need a define_insn_and_split for this construct: (set (reg:DI 141) (xor:DI (reg:DI 140) (const_int 65535 [0xffff]))) It has to be a define_insn_and_split because it would be a 2->2 split which isn't generally profitable. It would need to be conditional on !Zbb and only apply before register allocation. The 3rd case can't be optimized in this way because the result of the NOT is used as a source operand in multiple instructions.