https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111252
--- Comment #4 from Xi Ruoyao <xry111 at gcc dot gnu.org> --- (In reply to Andrew Pinski from comment #2) > Interesting: > int test(int a, int b) > { > return (a & ~0x80000000) | (b & 0x80000000); > } > > Produces better code: > lu12i.w $r12,-2147483648>>12 # 0xffffffff80000000 > and $r12,$r12,$r5 > bstrpick.w $r4,$r4,30,0 > or $r4,$r4,$r12 > slli.w $r4,$r4,0 > jr $r1 Hmm, this seems a separate issue. The compiler knows to optimize (a & mask) if mask is ((1 << a) - 1) << b iff a + b = 32 or b = 0, but not for any other masks even if it's "expensive" to materialize the mask: long test(long a, long b) { return a & 0xfffff0000l; } compiles to: lu12i.w $r12,-65536>>12 # 0xffffffffffff0000 lu32i.d $r12,0xf00000000>>32 and $r4,$r4,$r12 jr $r1 But the following is better: bstrpick.d $r12, $r12, 35, 16 slli.d $r12, $r12, 16