Consider: int bar (void);
int foo (int b) { int a = bar (); return a | (1 << (b & 31)); } ./cc1 -quiet -O2 -m5200 -fomit-frame-pointer generates foo: move.l %d2,-(%sp) move.l 8(%sp),%d2 jbsr bar moveq #31,%d1 and.l %d1,%d2 move.b #1,%d1 lsl.l %d2,%d1 or.l %d1,%d0 move.l (%sp)+,%d2 rts Note that bset could be used in place of the five instructions between moveq and or.l, inclusive. Of course, the five instructions are too many for the combiner, but the combiner already suggests an intermediate insn like so (set (reg:SI 36) (ashift:SI (reg:SI 37) (and:SI (reg/v:SI 32 [ b ]) (const_int 31 [0x1f])))) which we can implement using clr and bset. Once this combination is established, going to (set (reg:SI) (ior:SI (reg:SI) (ashift:SI (const_int 1) (and:SI (reg:SI) (const_int 31))))) shouldn't be difficult. Interestingly, if we feed A as an argument instead of a return value, the combiner does not produce the ashift insn mentioned above. -- Summary: [m68k] bset is not used for A = 1 << (B & 31) on ColdFire Product: gcc Version: 4.1.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: enhancement Priority: P3 Component: target AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: kazu at gcc dot gnu dot org GCC target triplet: m68k-elf http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25111