[llvm] r316699 - [LICM] Restructure implicit exit handling to be more clear [NFCI]
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 26 14:00:15 PDT 2017
Author: reames
Date: Thu Oct 26 14:00:15 2017
New Revision: 316699
URL: http://llvm.org/viewvc/llvm-project?rev=316699&view=rev
Log:
[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.
Modified:
llvm/trunk/lib/Transforms/Scalar/LICM.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=316699&r1=316698&r2=316699&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Thu Oct 26 14:00:15 2017
@@ -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);
More information about the llvm-commits
mailing list