Skip to content

Missed optimization for (a == 0 && b != 0) || (a != 0 && b == 0)) #92966

Closed
@pskrgag

Description

@pskrgag

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions