diff --git a/llvm/include/llvm/Analysis/StackLifetime.h b/llvm/include/llvm/Analysis/StackLifetime.h --- a/llvm/include/llvm/Analysis/StackLifetime.h +++ b/llvm/include/llvm/Analysis/StackLifetime.h @@ -78,6 +78,7 @@ private: const Function &F; + const bool MustLive; /// Maps active slots (per bit) for each basic block. using LivenessMap = DenseMap; @@ -122,7 +123,8 @@ void calculateLiveIntervals(); public: - StackLifetime(const Function &F, ArrayRef Allocas); + StackLifetime(const Function &F, ArrayRef Allocas, + bool MustLive); void run(); std::vector getMarkers() const; diff --git a/llvm/lib/Analysis/StackLifetime.cpp b/llvm/lib/Analysis/StackLifetime.cpp --- a/llvm/lib/Analysis/StackLifetime.cpp +++ b/llvm/lib/Analysis/StackLifetime.cpp @@ -34,6 +34,9 @@ #define DEBUG_TYPE "stack-lifetime" +static cl::opt ClMustLive("stack-lifetime-must", cl::Hidden, + cl::init(false)); + const StackLifetime::LiveRange & StackLifetime::getLiveRange(const AllocaInst *AI) const { const auto IT = AllocaNumbering.find(AI); @@ -166,7 +169,14 @@ // If a predecessor is unreachable, ignore it. if (I == BlockLiveness.end()) continue; - LocalLiveIn |= I->second.LiveOut; + if (MustLive) { + if (LocalLiveIn.empty()) + LocalLiveIn = I->second.LiveOut; + else + LocalLiveIn &= I->second.LiveOut; + } else { + LocalLiveIn |= I->second.LiveOut; + } } // Compute LiveOut by subtracting out lifetimes that end in this @@ -272,8 +282,9 @@ #endif StackLifetime::StackLifetime(const Function &F, - ArrayRef Allocas) - : F(F), Allocas(Allocas), NumAllocas(Allocas.size()) { + ArrayRef Allocas, + bool MustLive) + : F(F), MustLive(MustLive), Allocas(Allocas), NumAllocas(Allocas.size()) { LLVM_DEBUG(dumpAllocas()); for (unsigned I = 0; I < NumAllocas; ++I) @@ -383,7 +394,7 @@ for (auto &I : instructions(F)) if (const AllocaInst *AI = dyn_cast(&I)) Allocas.push_back(AI); - Result = std::make_unique(F, Allocas); + Result = std::make_unique(F, Allocas, ClMustLive); Result->run(); return false; } diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp --- a/llvm/lib/CodeGen/SafeStack.cpp +++ b/llvm/lib/CodeGen/SafeStack.cpp @@ -497,7 +497,7 @@ DIBuilder DIB(*F.getParent()); - StackLifetime SSC(F, StaticAllocas); + StackLifetime SSC(F, StaticAllocas, false); static const StackLifetime::LiveRange NoColoringRange(1, true); if (ClColoring) SSC.run(); diff --git a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll --- a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll +++ b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll @@ -1,4 +1,5 @@ -; RUN: opt -analyze -stack-lifetime -S < %s -o - | FileCheck %s +; RUN: opt -analyze -stack-lifetime -stack-lifetime-must=0 -S < %s -o - | FileCheck %s --check-prefixes=CHECK,MAY +; RUN: opt -analyze -stack-lifetime -stack-lifetime-must=1 -S < %s -o - | FileCheck %s --check-prefixes=CHECK,MUST define void @f() { ; CHECK-LABEL: define void @f() @@ -710,7 +711,8 @@ l2: ; preds = %l2, %entry ; CHECK: l2: -; CHECK-NEXT: Alive: +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> call void @capture8(i8* %x) call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) ; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) @@ -758,6 +760,55 @@ ; CHECK-NEXT: Alive: } +define void @if_must(i1 %a) { +; CHECK-LABEL: define void @if_must +entry: +; CHECK: entry: +; CHECK-NEXT: Alive: <> + %x = alloca i8, align 4 + %y = alloca i8, align 4 + + br i1 %a, label %if.then, label %if.else +; CHECK: br i1 %a +; CHECK-NEXT: Alive: <> + +if.then: +; CHECK: if.then: +; CHECK-NEXT: Alive: <> + call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) +; CHECK-NEXT: Alive: + + br label %if.end +; CHECK: br label %if.end +; CHECK-NEXT: Alive: + +if.else: +; CHECK: if.else: +; CHECK-NEXT: Alive: <> + call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) +; CHECK-NEXT: Alive: + + call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) +; CHECK-NEXT: Alive: + + br label %if.end +; CHECK: br label %if.end +; CHECK-NEXT: Alive: + +if.end: +; CHECK: if.end: +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: + +ret void +; CHECK: ret void +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: +} + declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) declare void @capture8(i8*)