https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68282
--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> --- clang can now produce: andl $-4, %edi movl table+4(%rdi), %eax retq GCC no longer has the sign extend but still not the above: shrb $2, %dil addl $1, %edi andl $127, %edi movl table(,%rdi,4), %eax ret Trying 8, 9, 11 -> 12: 8: {r90:QI=r95:SI#0 0>>0x2;clobber flags:CC;} REG_DEAD r95:SI REG_UNUSED flags:CC 9: {r91:QI=r90:QI+0x1;clobber flags:CC;} REG_DEAD r90:QI REG_UNUSED flags:CC 11: {r93:DI=r91:QI#0&0x7f;clobber flags:CC;} REG_UNUSED flags:CC REG_DEAD r91:QI 12: r94:SI=[r93:DI*0x4+`table'] REG_DEAD r93:DI Failed to match this instruction: (set (reg:SI 94 [ table[_3] ]) (mem:SI (plus:DI (and:DI (plus:DI (mult:DI (subreg:DI (lshiftrt:QI (subreg:QI (reg:SI 95) 0) (const_int 2 [0x2])) 0) (const_int 4 [0x4])) (const_int 4 [0x4])) (const_int 508 [0x1fc])) (symbol_ref:DI ("table") [flags 0x2] <var_decl 0x7fa70c191bd0 table>)) [1 table[_3]+0 S4 A32])) Note I think the -4 is incorrect even because I think the upper 24bits of eax is undefined when comining into the function. If we do this: int func(unsigned long c) { c&=0xff; return table[(c >> 2) + 1]; } We get the correct code even: andl $252, %edi movl table+4(%rdi), %eax ret