This is an archive of the discontinued LLVM Phabricator instance.

[ValueTracking] Teach computeKnownBits that the result of an absolute value pattern that uses nsw flag is always positive.
ClosedPublic

Authored by craig.topper on May 17 2018, 5:04 PM.

Details

Summary

If the nsw flag is used in the absolute value then it is undefined for INT_MIN. For all other value it will produce a positive number. So we can assume the result is positive.

This breaks some InstCombine abs/nabs combining tests because we simplify the second compare from known bits rather than as the whole pattern. Looks like we can probably fix it by adding a neg+abs/nabs combine to just swap the select operands. Need to check alive to make sure there are no corner cases.

Diff Detail

Repository
rL LLVM

Event Timeline

craig.topper created this revision.May 17 2018, 5:04 PM
efriedma added inline comments.May 17 2018, 5:19 PM
lib/Analysis/ValueTracking.cpp
1086 ↗(On Diff #147411)

Can you write a similar pattern for SPF_NABS?

We could save a bit of computation by not calling ComputeKnownBits on both x and -x, but it's probably not worth bothering...

craig.topper added inline comments.May 17 2018, 6:34 PM
lib/Analysis/ValueTracking.cpp
1086 ↗(On Diff #147411)

I don't think SPF_NABS has a sign bit guarantee. NABS of 0 is still 0. NABS of anything else is negative.

dmgreen added inline comments.
lib/Analysis/ValueTracking.cpp
1085 ↗(On Diff #147411)

Can't RHS be a const?

craig.topper added inline comments.
lib/Analysis/ValueTracking.cpp
1085 ↗(On Diff #147411)

This patch is dependent on another patch where I made matchSelectPattern return the negation portion in RHS. Previously it always returned a 0, 1, or -1 constant which was failry useless.

Add a combine to negate ABS/NABS to recover the broken tests.

Add a simple test case to show (abs(x)) > 0 is always true.

That should have said abs(x) >= 0 is always true.

spatel added inline comments.May 22 2018, 3:34 PM
lib/Transforms/InstCombine/InstCombineAddSub.cpp
1636–1637 ↗(On Diff #148113)

We should copy and then swapProfMetadata for the new select rather than dropping that. Alternatively, we could swap the operands and metadata on the existing select and return it. Since we're checking hasOneUse(), I think it's ok to recycle.

This part can be a separate commit with independent tests like:

define i8 @negate_abs(i8 %x) {
  %n = sub i8 0, %x
  %c = icmp slt i8 %x, 0
  %s = select i1 %c, i8 %n, i8 %x
  %r = sub i8 0, %s
  ret i8 %r
}

define <2 x i8> @negate_nabs(<2 x i8> %x) {
  %n = sub <2 x i8> zeroinitializer, %x
  %c = icmp slt <2 x i8> %x, zeroinitializer
  %s = select <2 x i1> %c, <2 x i8> %x, <2 x i8> %n
  %r = sub <2 x i8> zeroinitializer, %s
  ret <2 x i8> %r
}

On 2nd thought, we're not actually changing the implicit branch here, so this should just propagate the metadata of the existing select.

Rebase to remvoe the InstCombine changes that were split off to another patch and have now been committed

spatel accepted this revision.May 24 2018, 2:13 PM

LGTM.

This revision is now accepted and ready to land.May 24 2018, 2:13 PM
This revision was automatically updated to reflect the committed changes.
vitalybuka reopened this revision.May 25 2018, 11:30 AM
vitalybuka added a subscriber: vitalybuka.

Reverted in r333253

This revision is now accepted and ready to land.May 25 2018, 11:30 AM

It should be safe to reland after r333295

This revision was automatically updated to reflect the committed changes.