[LICM] Separate check for writability and thread-safety (NFCI)
authorNikita Popov <npopov@redhat.com>
Mon, 5 Sep 2022 07:39:59 +0000 (09:39 +0200)
committerNikita Popov <npopov@redhat.com>
Mon, 5 Sep 2022 07:43:17 +0000 (09:43 +0200)
This used a single check to make sure that the object is both
writable and thread-local. Separate them out to make the
deficiencies in the current code more obvious.

llvm/lib/Transforms/Scalar/LICM.cpp

index 9d98bea..29e14d8 100644 (file)
@@ -1890,6 +1890,29 @@ bool isNotVisibleOnUnwindInLoop(const Value *Object, const Loop *L,
          isNotCapturedBeforeOrInLoop(Object, L, DT);
 }
 
+bool isWritableObject(const Value *Object) {
+  // TODO: Alloca might not be writable after its lifetime ends.
+  // See https://github.com/llvm/llvm-project/issues/51838.
+  if (isa<AllocaInst>(Object))
+    return true;
+
+  // TODO: Also handle sret.
+  if (auto *A = dyn_cast<Argument>(Object))
+    return A->hasByValAttr();
+
+  // TODO: Noalias has nothing to do with writability, this should check for
+  // an allocator function.
+  return isNoAliasCall(Object);
+}
+
+bool isThreadLocalObject(const Value *Object, const Loop *L,
+                         DominatorTree *DT) {
+  // The object must be function-local to start with, and then not captured
+  // before/in the loop.
+  return isIdentifiedFunctionLocal(Object) &&
+         isNotCapturedBeforeOrInLoop(Object, L, DT);
+}
+
 } // namespace
 
 /// Try to promote memory values to scalars by sinking stores out of the
@@ -2109,14 +2132,12 @@ bool llvm::promoteLoopAccessesToScalars(
   }
 
   // We know we can hoist the load, but don't have a guaranteed store.
-  // Check whether the location is thread-local. If it is, then we can insert
-  // stores along paths which originally didn't have them without violating the
-  // memory model.
+  // Check whether the location is writable and thread-local. If it is, then we
+  // can insert stores along paths which originally didn't have them without
+  // violating the memory model.
   if (StoreSafety == StoreSafetyUnknown) {
     Value *Object = getUnderlyingObject(SomePtr);
-    if ((isNoAliasCall(Object) || isa<AllocaInst>(Object) ||
-         (isa<Argument>(Object) && cast<Argument>(Object)->hasByValAttr())) &&
-        isNotCapturedBeforeOrInLoop(Object, CurLoop, DT))
+    if (isWritableObject(Object) && isThreadLocalObject(Object, CurLoop, DT))
       StoreSafety = StoreSafe;
   }