This is an archive of the discontinued LLVM Phabricator instance.

Add a pass to eliminate nullchecks after objects have been dereferenced (WIP)
Needs ReviewPublic

Authored by fhahn on Jun 22 2020, 6:59 AM.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Summary

This patch adds a new pass that keeps track of dereferenced objects and
eliminates null checks that are dominated by a memory instruction that
dereferences the underlying object.

Currently this works by collecting all object dereferences and null
checks with known underlying objects. Those are then sorted by DomTree DFS
numbers of their containing blocks and the relative order in a basic
block. Then we iterate over the list and keep track of the currently
dereferenced objects. We remove objects once we encounter a block that
is not dominated by the dereference instruction.

Currently this is O(N * log(N)), where N is the number of memory
instructions that dereference a known underlying object plus number of
null checks of known underlying objects. As it is, the compile time
impact is +0.33% geomean for -O3 ThinLTO
(http://llvm-compile-time-tracker.com/compare.php?from=a5bd75aab861df8cea8d1c6b88e764ad4a2c09ea&to=c02c43b0fe6648772d70c3f3de41a9e5e29e0628&stat=instructions)

It is probably possible to improve that if we would directly traverse
the dominator tree.

This currently results in 1924 compare simplifications on
MultiSource/SPEC2000/SPEC2006 with -O3 -flto.

Diff Detail

Event Timeline

fhahn created this revision.Jun 22 2020, 6:59 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 22 2020, 6:59 AM
nikic added a subscriber: nikic.Jun 22 2020, 1:35 PM

It is probably possible to improve that if we would directly traverse the dominator tree.

Yes, I think that would make more sense. Another possibility would be to traverse in RPO and intersect nonnull objects from visited predecessors (I think that's legal, because these must be nonnull on backedges as well). That would come at the cost of set intersections though.

llvm/lib/Transforms/Scalar/DereferenceNullCheckElimination.cpp
170

For memory intrinsics, it's also necessary to check that the length is non-zero. Per LangRef:

If “len” is 0, the pointers may be NULL or dangling. However, they must still be appropriately aligned.