https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125708
Bug ID: 125708
Summary: Missed optimization: division by (2 - bool) emits
idivl instead of shift/select
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: liuhongt at gcc dot gnu.org
Target Milestone: ---
GCC fails to use value-range information for an integer division whose divisor
is 2 - bool. Since a bool is constrained to {0, 1}, the divisor 2 - b has range
[1, 2], so the division is equivalent to b ? a : a/2. GCC currently emits a
full signed idivl (~20+ cycle latency) instead of lowering it to a cheap shift
+ select (or branch).
Reduced test case
#include <stdbool.h>
int foo (int a, bool b)
{
return a / (2 - b);
}
int foo1 (int a, bool b)
{
return b ? a : a / 2;
}
foo and foo1 are semantically identical:
b == 1 -> a / 1 -> a
b == 0 -> a / 2
foo(int, bool):
movl %edi, %eax
movzbl %sil, %esi
movl $2, %ecx
subl %esi, %ecx
cltd
idivl %ecx
ret
foo1(int, bool):
movl %edi, %eax
shrl $31, %eax
addl %edi, %eax
sarl %eax
testb %sil, %sil
cmovne %edi, %eax
ret