This is an archive of the discontinued LLVM Phabricator instance.

[DAGCombiner] eliminate setcc bool math when input is low-bit of some value
ClosedPublic

Authored by spatel on Jun 22 2018, 3:36 PM.

Details

Summary

This patch has the same motivating example as D48466, but I'm trying to kill the setcc bool math sooner rather than later.

By matching a larger pattern that includes both the low-bit mask and the trailing add/sub, we can create a universally good fold because we always eliminate the condition code intermediate value.

Here are Alive proofs for these (currently instcombine folds the 'add' variants, but misses the 'sub' patterns):
https://rise4fun.com/Alive/Gsyp

Name: sub of zext cmp mask
  %a = and i8 %x, 1
  %c = icmp eq i8 %a, 0
  %z = zext i1 %c to i32
  %r = sub i32 C1, %z
  =>
  %optional_cast = zext i8 %a to i32
  %r = add i32 %optional_cast, C1-1

Name: add of zext cmp mask
  %a = and i32 %x, 1
  %c = icmp eq i32 %a, 0
  %z = zext i1 %c to i8
  %r = add i8 %z, C1
  =>
  %optional_cast = trunc i32 %a to i8
  %r = sub i8 C1+1, %optional_cast

All of the tests look like improvements or neutral to me. But it is possible that x86 test+set+bitop is better than what we now show here. I suspect we could do better by adding another fold for the 'sub' variants in particular.

We start with select-of-constant in IR in the larger motivating test, so that's why I included tests with selects. Proofs for those variants:
https://rise4fun.com/Alive/Bx1

Name: true const is bigger
Pre: C2 == (C1 + 1)
  %a = and i8 %x, 1
  %c = icmp eq i8 %a, 0
  %r = select i1 %c, i64 C2, i64 C1
  =>
  %z = zext i8 %a to i64
  %r = sub i64 C2, %z

Name: false const is bigger
Pre: C2 == (C1 + 1)
  %a = and i8 %x, 1
  %c = icmp eq i8 %a, 0
  %r = select i1 %c, i64 C1, i64 C2
  =>
  %z = zext i8 %a to i64
  %r = add i64 C1, %z

I have not stepped through the PPC tests to see how the 3 unchanged select tests escaped any diffs. It's possible that those are not folded the same as x86 initially or something later reverses what we're doing here.

Diff Detail

Event Timeline

spatel created this revision.Jun 22 2018, 3:36 PM
craig.topper added inline comments.Jun 22 2018, 5:17 PM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
2068

Why not "getValueType() == MVT::i1"?

spatel updated this revision to Diff 152592.Jun 23 2018, 8:28 AM
spatel marked an inline comment as done.

Patch updated - no functional change intended from the previous rev (test diffs are identical):

  1. Refactored to reduce code duplication and improve readability.
  2. Replaced getValueSizeInBits() == 1 with getValueType() == MVT::i1.
craig.topper accepted this revision.Jun 23 2018, 10:39 AM

LGTM

test/CodeGen/X86/bool-math.ll
159

I wonder if we can turn the subb here into xor to allow the constant to fold?

This revision is now accepted and ready to land.Jun 23 2018, 10:39 AM
spatel added inline comments.Jun 24 2018, 7:39 AM
test/CodeGen/X86/bool-math.ll
159

Yes, there's probably a demanded / common bits check missing.