Closed
Description
Condition like (a == 0 && b != 0) || (a != 0 && b == 0))
could be folded into (a == 0) != (b == 0)
, but llvm misses this optimization.
For following function
int test2(int a, int b)
{
if ((a == 0 && b != 0) || (a != 0 && b == 0))
return 1;
return 0;
}
llvm generates
define dso_local range(i32 0, 2) i32 @src(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {
%3 = icmp eq i32 %0, 0
%4 = icmp ne i32 %1, 0
%5 = and i1 %3, %4
%6 = icmp ne i32 %0, 0
%7 = icmp eq i32 %1, 0
%8 = and i1 %6, %7
%9 = or i1 %5, %8
%10 = zext i1 %9 to i32
ret i32 %10
}
While there exists more optimal IR for such function:
define dso_local range(i32 0, 2) i32 @dst(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {
%3 = icmp eq i32 %0, 0
%4 = icmp eq i32 %1, 0
%5 = xor i1 %3, %4
%6 = zext i1 %5 to i32
ret i32 %6
}
Alive shows that such transformation is correct: https://alive2.llvm.org/ce/z/5AUAao
Odd enough that clang performs such folding if 0
is not a constant, but a function argument: https://godbolt.org/z/PsWh1rP8d