We can fold compares to false when two distinct allocations within a function are compared for equality.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
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
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.
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.
lib/Transforms/InstCombine/InstructionCombining.cpp | ||
---|---|---|
1909–1910 | I don't think this will do the right thing if %x = allocation is compared with gep(gep(%x, 1), -1). |
lib/Transforms/InstCombine/InstructionCombining.cpp | ||
---|---|---|
1909–1910 | Thats true! I think this would handle all cases of GEP and bitcasts: |
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.
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.
lgtm with some nits inline. I'll check this in for you once you upload the fixed version.
lib/Transforms/InstCombine/InstructionCombining.cpp | ||
---|---|---|
1873 | 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 | Needs to be CHECK-NEXT:, not CHECK_NEXT:. The latter is an no-op. |
I'd one line here on why we have that dependency. Also, it looks like you have a double space here.