In C++, a bool is guaranteed to be 0 or 1
C++ (§4.5/4):
An rvalue of type bool can be converted to an rvalue of type int, with
false becoming zero and true becoming one.
Consider the following function and what g++5.2 generates with -O3
int foo(bool a, bool b)
{
if(a&b) return 3;
else return 5;
}
0000000000000000 <_Z3foobb>:
0: 40 84 ff test %dil,%dil
3: 74 13 je 18 <_Z3foobb+0x18>
5: 40 84 f6 test %sil,%sil
8: b8 03 00 00 00 mov $0x3,%eax
d: 74 09 je 18 <_Z3foobb+0x18>
f: f3 c3 repz retq
11: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
18: b8 05 00 00 00 mov $0x5,%eax
1d: c3 retq
As seen, above, it is generating two test instructions which indicates that it is still treating the if as a if(a&&b) instead of a bitwise and.
Even if I first explicitly convert the two bools to two chars , it still generates the same output as above.
Since I know that the two operands a and b can only have 0/1 as values, is there some way to get gcc to generate just one test instruction. This is indeed what it does if the function takes two ints instead of two bools.
With &
, some compiler already produces different asm without jump:
clang 3.6 (rc2):
foo(bool, bool): # @foo(bool, bool)
testb %sil, %dil
sete %al
movzbl %al, %eax
leal 3(%rax,%rax), %eax
retq
A hack, in your case is to use *
which has the same true-table for true/false
int foo(bool a, bool b)
{
if (a * b) return 3;
else return 5;
}
Which produces:
foo(bool, bool):
movzbl %sil, %esi # b, b
movzbl %dil, %edi # a, tmp70
imull %esi, %edi # b, tmp70
cmpl $1, %edi #, tmp70
sbbl %eax, %eax # D.1960
andl $2, %eax #, D.1960
addl $3, %eax #, D.1960
ret