This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Fix bug in canonicalization of Pow2 Tests (From: D152673)
ClosedPublic

Authored by goldstein.w.n on Jul 23 2023, 9:09 AM.

Details

Summary

D152673 Incorrectly didn't account for operand position in the icmp,
i.e it treated icmp uge x, y the same as icmp uge y, x which is
incorrect:
https://reviews.llvm.org/rG142f7448e770f25b774b058a7eab1f107c4daad9

The fix takes operand position into account. The new tests
exhaustively cover all operand positions for ule, uge, ult,
ugt (the set of predicates) and all transform verify with the new
commit.

Diff Detail

Event Timeline

goldstein.w.n created this revision.Jul 23 2023, 9:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 23 2023, 9:09 AM
goldstein.w.n requested review of this revision.Jul 23 2023, 9:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 23 2023, 9:09 AM

I kept this out of the commit message because its a bit too verbose, but heres the alive2 output for all the transforms:

----------------------------------------
define i1 @blsmsk_is_p2_or_z_ule_xy(i8 %xx, i8 %yy) {
%0:
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, 255
  %y = xor i8 %x, %xm1
  %r = icmp ule i8 %x, %y
  ret i1 %r
}
=>
define i1 @blsmsk_is_p2_or_z_ule_xy(i8 %xx, i8 %yy) nofree willreturn memory(none) {
%0:
  %x = or i8 %yy, %xx
  %1 = ctpop i8 %x
  %1_range = !range i8 %1, i8 0, i8 9
  %r = icmp ult i8 %1_range, 2
  ret i1 %r
}
Transformation seems to be correct!

----------------------------------------
define i1 @blsmsk_is_p2_or_z_ule_yx_fail(i8 %xx, i8 %yy) {
%0:
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, 255
  %y = xor i8 %x, %xm1
  %r = icmp ule i8 %y, %x
  ret i1 %r
}
=>
define i1 @blsmsk_is_p2_or_z_ule_yx_fail(i8 %xx, i8 %yy) nofree willreturn memory(none) {
%0:
  %x = or i8 %yy, %xx
  %xm1 = add i8 %x, 255
  %y = xor i8 %xm1, %x
  %r = icmp ule i8 %y, %x
  ret i1 %r
}
Transformation seems to be correct!

----------------------------------------
define i1 @blsmsk_is_p2_or_z_uge_yx(i8 %xx, i8 %yy) {
%0:
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, 255
  %y = xor i8 %x, %xm1
  %r = icmp uge i8 %y, %x
  ret i1 %r
}
=>
define i1 @blsmsk_is_p2_or_z_uge_yx(i8 %xx, i8 %yy) nofree willreturn memory(none) {
%0:
  %x = or i8 %yy, %xx
  %1 = ctpop i8 %x
  %1_range = !range i8 %1, i8 0, i8 9
  %r = icmp ult i8 %1_range, 2
  ret i1 %r
}
Transformation seems to be correct!

----------------------------------------
define i1 @blsmsk_is_p2_or_z_uge_xy_fail(i8 %xx, i8 %yy) {
%0:
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, 255
  %y = xor i8 %x, %xm1
  %r = icmp uge i8 %x, %y
  ret i1 %r
}
=>
define i1 @blsmsk_is_p2_or_z_uge_xy_fail(i8 %xx, i8 %yy) nofree willreturn memory(none) {
%0:
  %x = or i8 %yy, %xx
  %xm1 = add i8 %x, 255
  %y = xor i8 %xm1, %x
  %r = icmp uge i8 %x, %y
  ret i1 %r
}
Transformation seems to be correct!

----------------------------------------
define i1 @blsmsk_isnt_p2_or_z_ugt_xy(i8 %xx, i8 %yy) {
%0:
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, 255
  %y = xor i8 %x, %xm1
  %r = icmp ugt i8 %x, %y
  ret i1 %r
}
=>
define i1 @blsmsk_isnt_p2_or_z_ugt_xy(i8 %xx, i8 %yy) nofree willreturn memory(none) {
%0:
  %x = or i8 %yy, %xx
  %1 = ctpop i8 %x
  %1_range = !range i8 %1, i8 0, i8 9
  %r = icmp ugt i8 %1_range, 1
  ret i1 %r
}
Transformation seems to be correct!

----------------------------------------
define i1 @blsmsk_isnt_p2_or_z_ugt_yx_fail(i8 %xx, i8 %yy) {
%0:
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, 255
  %y = xor i8 %x, %xm1
  %r = icmp ugt i8 %y, %x
  ret i1 %r
}
=>
define i1 @blsmsk_isnt_p2_or_z_ugt_yx_fail(i8 %xx, i8 %yy) nofree willreturn memory(none) {
%0:
  %x = or i8 %yy, %xx
  %xm1 = add i8 %x, 255
  %y = xor i8 %xm1, %x
  %r = icmp ugt i8 %y, %x
  ret i1 %r
}
Transformation seems to be correct!

----------------------------------------
define i1 @blsmsk_isnt_p2_or_z_ult_yx(i8 %xx, i8 %yy) {
%0:
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, 255
  %y = xor i8 %x, %xm1
  %r = icmp ult i8 %y, %x
  ret i1 %r
}
=>
define i1 @blsmsk_isnt_p2_or_z_ult_yx(i8 %xx, i8 %yy) nofree willreturn memory(none) {
%0:
  %x = or i8 %yy, %xx
  %1 = ctpop i8 %x
  %1_range = !range i8 %1, i8 0, i8 9
  %r = icmp ugt i8 %1_range, 1
  ret i1 %r
}
Transformation seems to be correct!

----------------------------------------
define i1 @blsmsk_isnt_p2_or_z_ult_xy_fail(i8 %xx, i8 %yy) {
%0:
  %x = or i8 %xx, %yy
  %xm1 = add i8 %x, 255
  %y = xor i8 %x, %xm1
  %r = icmp ult i8 %x, %y
  ret i1 %r
}
=>
define i1 @blsmsk_isnt_p2_or_z_ult_xy_fail(i8 %xx, i8 %yy) nofree willreturn memory(none) {
%0:
  %x = or i8 %yy, %xx
  %xm1 = add i8 %x, 255
  %y = xor i8 %xm1, %x
  %r = icmp ult i8 %x, %y
  ret i1 %r
}
Transformation seems to be correct!

Summary:
  8 correct transformations
  0 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors

Also for the other two test changes:

----------------------------------------
define i1 @blsmsk_is_p2_or_z_fail(i32 %xx, i32 %yy) {
%0:
  %x = or i32 %xx, %yy
  %xm1 = add i32 %x, 4294967295
  %y = xor i32 %x, %xm1
  %r = icmp ugt i32 %x, %y
  ret i1 %r
}
=>
define i1 @blsmsk_is_p2_or_z_fail(i32 %xx, i32 %yy) nofree willreturn memory(none) {
%0:
  %x = or i32 %yy, %xx
  %1 = ctpop i32 %x
  %1_range = !range i32 %1, i32 0, i32 33
  %r = icmp ugt i32 %1_range, 1
  ret i1 %r
}
Transformation seems to be correct!


----------------------------------------
define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) {
%0:
  %x = or i32 %xx, %yy
  %xm1 = add i32 %x, 4294967295
  %y = xor i32 %x, %xm1
  %r = icmp uge i32 %x, %y
  ret i1 %r
}
=>
define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) nofree willreturn memory(none) {
%0:
  %x = or i32 %yy, %xx
  %xm1 = add i32 %x, 4294967295
  %y = xor i32 %xm1, %x
  %r = icmp uge i32 %x, %y
  ret i1 %r
}
Transformation seems to be correct!

Summary:
  2 correct transformations
  0 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
This revision is now accepted and ready to land.Jul 23 2023, 9:21 AM
This revision was landed with ongoing or failed builds.Jul 23 2023, 9:57 AM
This revision was automatically updated to reflect the committed changes.