http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53942
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-07-16 11:31:59 UTC --- C testcase for just -O2 -m32 -mtune=pentium2: struct S { unsigned short data[3]; unsigned int x; unsigned int y; }; struct S *baz (void); __attribute__ ((noinline)) static unsigned char foo (struct S *x, unsigned char y) { unsigned char c = 0; unsigned char v = x->data[0]; c |= v; v = ((x->data[1]) & (1 << y)) ? 1 : 0; c |= v << 1; v = ((x->data[2]) & 0xff) & (1 << y); c |= v << 2; return c; } void bar (void) { struct S *s = baz (); s->x = foo (s, 6); s->y = foo (s, 7); } cant_combine_insn_p already handles hard regs likely spilled correctly if they are just seen in a simple register move, unfortunately in this case there is no simple reg move, but instead a zero extension already in the *.expand dump: (insn 4 3 5 2 (set (reg:SI 80 [ ISRA.4 ]) (zero_extend:SI (reg:HI 2 cx [ ISRA.4 ]))) pr53942.c:12 -1 (nil)) I wonder if either we shouldn't force the HI cx register first into pseudo and have separate zero extension afterwards (the other alternative would be if we have a zero or sign extension from hard register likely spilled, force the hard register into a pseudo in the combiner at the spot where it used to be zero extended).