This is an archive of the discontinued LLVM Phabricator instance.

folding compares for distinct allocations
ClosedPublic

Authored by anna on Apr 21 2016, 2:15 PM.

Details

Summary

We can fold compares to false when two distinct allocations within a function are compared for equality.

Diff Detail

Repository
rL LLVM

Event Timeline

anna updated this revision to Diff 54575.Apr 21 2016, 2:15 PM
anna retitled this revision from to folding compares for distinct allocations.
anna updated this object.
anna set the repository for this revision to rL LLVM.
anna updated this object.Apr 21 2016, 2:20 PM
anna added a subscriber: llvm-commits.
anna added a comment.Apr 21 2016, 2:43 PM

Sanjoy pointed out a case that might cause the comparison of the pointer to itself to be incorrect, basically this check: PI == ICI->getOperand(OtherIndex) is not enough. Will update the diff to take care of such cases

sanjoy edited edge metadata.Apr 21 2016, 4:04 PM

For the record, this is the example I was talking about:

%v0 = malloc()
%other = (bitcast (bitcast %v0))
;; two bitcasts to allow bitcasting i8* -> i32* -> i8* or something like that
;; to allow the equality to be properly typed
%result = %other == %v0

Now, as written, I think the above example is fine, since the
traversal order guarantees that we'll visit the %result with PI as
%v0 (and bail out of the loop) before we visit %result with PI
as %other. And I think we _can_ make a general argument that if
isAllocFn returns true for the non PI operand then the non PI
operand is different from AI since if the non PI operand was equal
to AI then we'd have visited the comparison earlier and bailed out
of the loop. However, this argument is somewhat subtle (for instance,
passing in true for LookThroughBitCast to isAllocFn will break
that), so if we go down that path we should add some relevant asserts
and test cases.

anna updated this revision to Diff 54644.Apr 22 2016, 7:17 AM
anna edited edge metadata.
anna removed rL LLVM as the repository for this revision.

Added tests to catch cases in future when ordering of optimization changes (or changes to LikeAllocFn with LookThroughBitCast is set to true) which causes LikeAllocFn to return true.
Also, improved the check to see if 2 allocations are actually of the same pointer, by stripping through bitcasts and zero GEPs.

majnemer added inline comments.Apr 22 2016, 7:22 AM
lib/Transforms/InstCombine/InstructionCombining.cpp
1905–1909 ↗(On Diff #54644)

I don't think this will do the right thing if %x = allocation is compared with gep(gep(%x, 1), -1).

anna added inline comments.Apr 22 2016, 9:32 AM
lib/Transforms/InstCombine/InstructionCombining.cpp
1905–1909 ↗(On Diff #54644)

Thats true!

I think this would handle all cases of GEP and bitcasts:
PI == ICI->getOperand(OtherIndex)->stripInBoundsOffsets()
Mainly, the GEP indices could be non-contant: gep(gep(%x, y), z) and still point to %x if y and z are 1 and -1 respectively.

majnemer added inline comments.Apr 22 2016, 9:47 AM
lib/Transforms/InstCombine/InstructionCombining.cpp
1905–1909 ↗(On Diff #54644)

In that case, what if we have gep(0, %x) ? I am not an expert on the GEP rules but someone else (@sanjoy?) might know.

I think the code would be more obviously correct if we pass in AI explicitly to isNeverEqualToUnescapedAlloc, and change the check in isNeverEqualToUnescapedAlloc to isAllocLikeFn(V, TLI) && V != AI. Does that sound better? Then we wouldn't have to worry about comparing an allocation against itself. Might also add a comment stating that we rely on LookThroughBitCast being false.

anna added a comment.Apr 22 2016, 11:09 AM

agreed. This would work since GEPs are not considered in isAllocLikeFn.

Also, LookThroughBitCast being true just calls stripPointerCast(), so we can have the check as V->stripPointerCast() != AI && isAllocLikeFn(V, TLI). Does that work?

In D19390#409243, @anna wrote:

agreed. This would work since GEPs are not considered in isAllocLikeFn.

Also, LookThroughBitCast being true just calls stripPointerCast(), so we can have the check as V->stripPointerCast() != AI && isAllocLikeFn(V, TLI). Does that work?

That would work, but I think given that we're passing in false for LookThroughBitCast anyway (that's the default), I'd say lets not bother with that.

anna updated this revision to Diff 54689.Apr 22 2016, 11:45 AM
anna set the repository for this revision to rL LLVM.
sanjoy accepted this revision.Apr 22 2016, 12:58 PM
sanjoy edited edge metadata.

lgtm with some nits inline. I'll check this in for you once you upload the fixed version.

lib/Transforms/InstCombine/InstructionCombining.cpp
1873 ↗(On Diff #54689)

I'd one line here on why we have that dependency. Also, it looks like you have a double space here.

test/Transforms/InstCombine/compare-unescaped.ll
89 ↗(On Diff #54689)

Needs to be CHECK-NEXT:, not CHECK_NEXT:. The latter is an no-op.

This revision is now accepted and ready to land.Apr 22 2016, 12:58 PM
anna updated this revision to Diff 54710.Apr 22 2016, 1:25 PM
anna edited edge metadata.
anna marked 2 inline comments as done.
This revision was automatically updated to reflect the committed changes.