This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: x86 branches vs conditional moves
- From: Yuri Gribov <tetra2005 at gmail dot com>
- To: Michael Clark <michaeljclark at mac dot com>
- Cc: GCC Development <gcc at gcc dot gnu dot org>
- Date: Sat, 8 Jul 2017 08:31:08 +0100
- Subject: Re: x86 branches vs conditional moves
- Authentication-results: sourceware.org; auth=none
- References: <D1A81E24-0F38-42E0-9348-C558ED81980F@mac.com>
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