x86 branches vs conditional moves
Yuri Gribov
tetra2005@gmail.com
Sat Jul 8 07:31:00 GMT 2017
On Sat, Jul 8, 2017 at 12:30 AM, Michael Clark <michaeljclark@mac.com> wrote:
> Hi,
>
> Curious about this codegen:
>
> - https://godbolt.org/g/5XxP5S
>
> Why does gcc branch on _Bool, but emits a conditional move for an integer? can it emit cmovne instead of branching? also curious where one would change this to learn about GCC internals.
Seems to be caused by a limitation in ifconvert pass which can not
handle slightly more complex code in select_bool.
Return there contains implicit != operations on a and b which clobbers
CC register:
(insn 8 7 9 3 (set (reg:CCZ 17 flags)
(compare:CCZ (mem/c:SI (symbol_ref:DI ("a"))
(const_int 0 [0]))))
(insn 9 8 13 3 (set (reg:QI 90 [ <retval> ])
(ne:QI (reg:CCZ 17 flags)
(const_int 0 [0]))))
(RTL filtered for brevity). This aborts if-conversion in
noce_process_if_block here
if (!bb_valid_for_noce_process_p (then_bb, cond, &then_cost,
&if_info->then_simple))
return false;
because insn_valid_noce_process_p returns false for the first insn above.
> It’s not a bug, but it is a performance issue (*1).
Well, it a performance bug then.
> I was just curious under which conditions the ternary operator is lowered to cmov on x86 and found this difference in lowering.
>
> Michael
>
> [1] https://github.com/xiadz/cmov
>
>
> #include <stdbool.h>
>
> extern int a;
> extern int b;
> extern int c;
> extern _Bool C;
>
> int select_int()
> {
> return c ? a : b;
> }
>
> _Bool select_bool()
> {
> return C ? a : b;
> }
>
> _Bool a_bool()
> {
> return 2;
> }
>
> select_int():
> mov eax, DWORD PTR c[rip]
> test eax, eax
> mov eax, DWORD PTR a[rip]
> cmove eax, DWORD PTR b[rip]
> ret
> select_bool():
> cmp BYTE PTR C[rip], 0
> jne .L8
> mov eax, DWORD PTR b[rip]
> test eax, eax
> setne al
> ret
> .L8:
> mov edx, DWORD PTR a[rip]
> test edx, edx
> setne al
> ret
> a_bool():
> mov eax, 1
> ret
More information about the Gcc
mailing list