This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Missed possible branch elimination
- From: Stefan Ring <stefanrin at gmail dot com>
- To: GCC <gcc at gcc dot gnu dot org>
- Date: Thu, 26 Oct 2017 20:23:27 +0200
- Subject: Missed possible branch elimination
- Authentication-results: sourceware.org; auth=none
While poring over the Transport Tycoon Deluxe disassembly, commonly
known to have been hand-written in assembler, I stumbled across this
tidbit, which I think is kinda neat:
004057F7 83 7D B8 01 cmp dword ptr [ebp-48h],1
004057FB 1B C0 sbb eax,eax
004057FD F7 D8 neg eax
004057FF 85 05 20 A9 41 00 test dword ptr ds:[41A920h],eax
00405805 0F 84 91 00 00 00 je 0040589C
which basically says:
if (((DWORD*) $ebp)[-0x12] == 0 && (*(DWORD*) 0x41a920 & 1)) { <whatever> }
... leaving aside possible side effects of the memory access, so
treating short circuit eval like an arithmetic operation might not be
legal in this specific case. But for the function
void a(void (*fnc)(void), int *x, int y) { if ((*x == 0) && (y&1)) fnc(); }
& and && should be absolutely equivalent. In fact, gcc realizes this
equivalency and produces the exact same code for both variants. It is
just using the two-branch version instead of a one-branch strategy
(x86_64 now):
0000000000000000 <a>:
0: 8b 06 mov (%rsi),%eax
2: 85 c0 test %eax,%eax
4: 75 0a jne 10 <a+0x10>
6: 83 e2 01 and $0x1,%edx
9: 74 05 je 10 <a+0x10>
b: ff e7 jmpq *%rdi
d: 0f 1f 00 nopl (%rax)
10: c3 retq
I would rather see:
0000000000000000 <a>:
0: 31 c0 xor %eax,%eax
2: 8b 0e mov (%rsi),%ecx
4: 85 c9 test %ecx,%ecx
6: 0f 94 c0 sete %al
9: 85 c2 test %eax,%edx
b: 74 03 je 10 <a+0x10>
d: ff e7 jmpq *%rdi
f: 90 nop
10: c3 retq
Either that, or even:
0000000000000000 <a>:
0: 8b 0e mov (%rsi),%ecx
2: 85 c9 test %ecx,%ecx
4: 0f 94 c0 sete %al
7: 84 c2 test %al,%dl
9: 74 05 je 10 <a+0x10>
b: ff e7 jmpq *%rdi
d: 0f 1f 00 nopl (%rax)
10: c3 retq
Although this is touching an entirely different topic now.
I'm just wondering if it should not rather lean towards eliminating
the branch. I'd
guess that this almost always a worthy goal.