================ @@ -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(); ---------------- NewSigma wrote:
If we want to align with Alive2, restricting to allocas that never escape shall not work. Because 1. Escape is a subset of capturing 2. We do not consider the lifetime of other allocas when optimizing a specific alloca. > I think Alive2 quite correctly points out that this changes observable > behavior. The demo is essentially doing ``` C int src() { char a[1000]; char* p_b; { char b[1000]; p_b = b; } return a == p_b; } int tgt() { char* p_b; { char b[1000]; p_b = b; } char a[1000]; return a == p_b; } ``` The transform looks OK to me. Anyway, what’s the point of comparing alloca pointers except to demonstrate that the optimization works? We might understand the behavior from the backend's perspective. Lifetime markers are hints for optimization, not a requirement, and it is the backend's freedom not to respect them. Correct behavior should not rely on it. 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