On Sat, Jul 8, 2017 at 12:30 AM, Michael Clark <michaeljcl...@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