Source: int g1,g2,g3; int f1(int a, int b) { a &= 1; if (a) return g1; return g2; } int f2(int a, int b) { a &= 1; if (b) g3++; if (a) return g1; return g2; } Compiled with: > gcc -O3 -fomit-frame-pointer -S and_flags.c f1 is ok but f2 generates this: _f2: andl $1, %edi <-- #1 testl %esi, %esi je L7 movq _g3@GOTPCREL(%rip), %rax incl (%rax) L7: testl %edi, %edi <-- #2 jne L10 movq _g2@GOTPCREL(%rip), %rax movl (%rax), %eax ret .align 4,0x90 L10: movq _g1@GOTPCREL(%rip), %rax movl (%rax), %eax ret The andl and testl should be folded into one andl. Code is reduced from ffmpeg h264 decoder. It's easy to work around by reordering source lines, so not too important.
Confirmed, this is a case where a def could be sunk closer to its first use.
This also happens on aarch64 where we could use tbnz.