[LICM] Restructure implicit exit handling to be more clear [NFCI]

When going to explain this to someone else, I got tripped up by the complicated meaning of IsKnownNonEscapingObject in load-store promotion.  Extract a helper routine and clarify naming/scopes to make this a bit more obvious.

llvm-svn: 316699
This commit is contained in:
Philip Reames 2017-10-26 21:00:15 +00:00
parent e4b9ae666e
commit 21cc2fa3f6
1 changed files with 34 additions and 27 deletions

View File

@ -1033,6 +1033,30 @@ public:
}
void instructionDeleted(Instruction *I) const override { AST.deleteValue(I); }
};
/// Return true iff we can prove that a caller of this function can not inspect
/// the contents of the provided object in a well defined program.
bool isKnownNonEscaping(Value *Object, const TargetLibraryInfo *TLI) {
if (isa<AllocaInst>(Object))
// Since the alloca goes out of scope, we know the caller can't retain a
// reference to it and be well defined. Thus, we don't need to check for
// capture.
return true;
// For all other objects we need to know that the caller can't possibly
// have gotten a reference to the object. There are two components of
// that:
// 1) Object can't be escaped by this function. This is what
// PointerMayBeCaptured checks.
// 2) Object can't have been captured at definition site. For this, we
// need to know the return value is noalias. At the moment, we use a
// weaker condition and handle only AllocLikeFunctions (which are
// known to be noalias). TODO
return isAllocLikeFn(Object, TLI) &&
!PointerMayBeCaptured(Object, true, true);
}
} // namespace
/// Try to promote memory values to scalars by sinking stores out of the
@ -1107,35 +1131,19 @@ bool llvm::promoteLoopAccessesToScalars(
const DataLayout &MDL = Preheader->getModule()->getDataLayout();
// Do we know this object does not escape ?
bool IsKnownNonEscapingObject = false;
bool IsKnownThreadLocalObject = false;
if (SafetyInfo->MayThrow) {
// If a loop can throw, we have to insert a store along each unwind edge.
// That said, we can't actually make the unwind edge explicit. Therefore,
// we have to prove that the store is dead along the unwind edge.
//
// If the underlying object is not an alloca, nor a pointer that does not
// escape, then we can not effectively prove that the store is dead along
// the unwind edge. i.e. the caller of this function could have ways to
// access the pointed object.
// we have to prove that the store is dead along the unwind edge. We do
// this by proving that the caller can't have a reference to the object
// after return and thus can't possibly load from the object.
Value *Object = GetUnderlyingObject(SomePtr, MDL);
// If this is a base pointer we do not understand, simply bail.
// We only handle alloca and return value from alloc-like fn right now.
if (!isa<AllocaInst>(Object)) {
if (!isAllocLikeFn(Object, TLI))
return false;
// If this is an alloc like fn. There are more constraints we need to
// verify. More specifically, we must make sure that the pointer can not
// escape.
//
// NOTE: PointerMayBeCaptured is not enough as the pointer may have
// escaped even though its not captured by the enclosing function.
// Standard allocation functions like malloc, calloc, and operator new
// return values which can be assumed not to have previously escaped.
if (PointerMayBeCaptured(Object, true, true))
return false;
IsKnownNonEscapingObject = true;
}
if (!isKnownNonEscaping(Object, TLI))
return false;
// Subtlety: Alloca's aren't visible to callers, but *are* potentially
// visible to other threads if captured and used during their lifetimes.
IsKnownThreadLocalObject = !isa<AllocaInst>(Object);
}
// Check that all of the pointers in the alias set have the same type. We
@ -1247,8 +1255,7 @@ bool llvm::promoteLoopAccessesToScalars(
// stores along paths which originally didn't have them without violating the
// memory model.
if (!SafeToInsertStore) {
// If this is a known non-escaping object, it is safe to insert the stores.
if (IsKnownNonEscapingObject)
if (IsKnownThreadLocalObject)
SafeToInsertStore = true;
else {
Value *Object = GetUnderlyingObject(SomePtr, MDL);