================
@@ -0,0 +1,341 @@
+//===- LifetimeMove.cpp - Narrowing lifetimes 
-----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The LifetimeMovePass identifies the precise lifetime range of allocas and
+// repositions lifetime markers to stricter positions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/LifetimeMove.h"
+#include "llvm/Analysis/CFG.h"
+#include "llvm/Analysis/CaptureTracking.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/Analysis/PtrUseVisitor.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/Transforms/Coroutines/CoroInstr.h"
+
+#define DEBUG_TYPE "lifetime-move"
+
+namespace llvm {
+namespace {
+class LifetimeMover : public PtrUseVisitor<LifetimeMover> {
+  using This = LifetimeMover;
+  using Base = PtrUseVisitor<LifetimeMover>;
+
+  const DominatorTree &DT;
+  const LoopInfo &LI;
+
+  SmallVector<AllocaInst *, 4> Allocas;
+  // Critical points are instructions where the crossing of a variable's
+  // lifetime makes a difference. We attempt to rise lifetime.end
+  // before critical points and sink lifetime.start after them.
+  SmallVector<Instruction *, 4> CriticalPoints;
+
+  SmallVector<Instruction *, 2> LifetimeStarts;
+  SmallVector<Instruction *, 2> LifetimeEnds;
+  SmallVector<Instruction *, 8> OtherUsers;
+  SmallPtrSet<BasicBlock *, 2> LifetimeStartBBs;
+  SmallPtrSet<BasicBlock *, 2> UserBBs;
+
+public:
+  LifetimeMover(Function &F, const DominatorTree &DT, const LoopInfo &LI);
+
+  bool run();
+
+  void visitInstruction(Instruction &I);
+  void visitPHINode(PHINode &I);
+  void visitSelectInst(SelectInst &I);
+  void visitStoreInst(StoreInst &SI);
+  void visitIntrinsicInst(IntrinsicInst &II);
+  void visitMemIntrinsic(MemIntrinsic &I);
+  void visitCallBase(CallBase &CB);
+
+private:
+  bool sinkLifetimeStartMarkers(AllocaInst *AI);
+  bool riseLifetimeEndMarkers();
+  void reset();
+};
+} // namespace
+
+LifetimeMover::LifetimeMover(Function &F, const DominatorTree &DT,
+                             const LoopInfo &LI)
+    : Base(F.getDataLayout()), DT(DT), LI(LI) {
+  for (Instruction &I : instructions(F)) {
+    if (auto *AI = dyn_cast<AllocaInst>(&I))
+      Allocas.push_back(AI);
+    else if (isa<LifetimeIntrinsic>(I))
+      continue;
+    else if (isa<AnyCoroSuspendInst>(I))
+      CriticalPoints.push_back(&I);
+    else if (isa<CallInst>(I))
+      CriticalPoints.push_back(&I);
+    else if (isa<InvokeInst>(I))
+      CriticalPoints.push_back(&I);
+  }
+}
+
+bool LifetimeMover::run() {
+  bool Changed = false;
+  for (auto *AI : Allocas) {
+    reset();
+    Base::visitPtr(*AI);
+
+    if (!LifetimeStarts.empty())
+      Changed |= sinkLifetimeStartMarkers(AI);
+
+    // Do not move lifetime.end if alloca escapes
+    if (!LifetimeEnds.empty() && !PI.isEscaped())
+      Changed |= riseLifetimeEndMarkers();
----------------
tmiasko wrote:

Should both of those transformation be limited only to allocas that don't have 
their address captured?

There are no executions where allocas are live at the same time and their 
storage overlaps. In contrast, if allocas aren't live at the time, their 
storage might overlap. Therefore shrinking a live range of an alloca that has 
its address captured (relatively to another alloca that also has its address 
captured) could introduce a new observable behavior.

Alive2 demonstration https://alive2.llvm.org/ce/z/uB4MzV.


https://github.com/llvm/llvm-project/pull/144319
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to