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 @@ -121,6 +121,8 @@ DenseMap, 4>> BBMarkers; + bool HasUnknownLifetimeStartOrEnd = false; + void dumpAllocas() const; void dumpBlockLiveness() const; void dumpLiveRanges() 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 @@ -11,6 +11,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/BasicBlock.h" @@ -63,42 +64,27 @@ return getLiveRange(AI).test(InstNum); } -static bool readMarker(const Instruction *I, bool *IsStart) { - if (!I->isLifetimeStartOrEnd()) - return false; - - auto *II = cast(I); - *IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start; - return true; -} - void StackLifetime::collectMarkers() { InterestingAllocas.resize(NumAllocas); DenseMap> BBMarkerSet; // Compute the set of start/end markers per basic block. - for (unsigned AllocaNo = 0; AllocaNo < NumAllocas; ++AllocaNo) { - const AllocaInst *AI = Allocas[AllocaNo]; - SmallVector WorkList; - WorkList.push_back(AI); - while (!WorkList.empty()) { - const Instruction *I = WorkList.pop_back_val(); - for (const User *U : I->users()) { - if (auto *BI = dyn_cast(U)) { - WorkList.push_back(BI); - continue; - } - auto *UI = dyn_cast(U); - if (!UI) - continue; - bool IsStart; - if (!readMarker(UI, &IsStart)) - continue; - if (IsStart) - InterestingAllocas.set(AllocaNo); - BBMarkerSet[UI->getParent()][UI] = {AllocaNo, IsStart}; + for (const BasicBlock *BB : depth_first(&F)) { + for (const Instruction &I : *BB) { + const IntrinsicInst *II = dyn_cast(&I); + if (!II || !II->isLifetimeStartOrEnd()) + continue; + const AllocaInst *AI = llvm::findAllocaForValue(II->getArgOperand(1)); + if (!AI) { + HasUnknownLifetimeStartOrEnd = true; + continue; } + bool IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start; + unsigned AllocaNo = AllocaNumbering[AI]; + if (IsStart) + InterestingAllocas.set(AllocaNo); + BBMarkerSet[BB][II] = {AllocaNo, IsStart}; } } @@ -304,6 +290,20 @@ } void StackLifetime::run() { + if (HasUnknownLifetimeStartOrEnd) { + // There is marker which we can't assign to a specific alloca, so we + // fallback to the most conservative results for the type. + switch (Type) { + case LivenessType::May: + LiveRanges.resize(NumAllocas, getFullLiveRange()); + break; + case LivenessType::Must: + LiveRanges.resize(NumAllocas, LiveRange(Instructions.size())); + break; + } + return; + } + LiveRanges.resize(NumAllocas, LiveRange(Instructions.size())); for (unsigned I = 0; I < NumAllocas; ++I) if (!InterestingAllocas.test(I)) 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 @@ -742,7 +742,7 @@ ; MAY-NEXT: Alive: ; MUST-NEXT: Alive: -ret void + ret void } define void @unreachable() { @@ -778,7 +778,62 @@ ; CHECK: end: ; CHECK-NEXT: Alive: -ret void + ret void +} + +define void @non_alloca(i8* %p) { +; CHECK-LABEL: define void @non_alloca +entry: +; CHECK: entry: +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + %x = alloca i8, align 4 + %y = alloca i8, align 4 + + call void @llvm.lifetime.start.p0i8(i64 4, i8* %p) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %p) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + call void @llvm.lifetime.end.p0i8(i64 4, i8* %p) +; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* %p) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + ret void +} + +define void @select_alloca(i1 %v) { +; CHECK-LABEL: define void @select_alloca +entry: +; CHECK: entry: +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + %x = alloca i8, align 4 + %y = alloca i8, align 4 + %cxcy = select i1 %v, i8* %x, i8* %y + + call void @llvm.lifetime.start.p0i8(i64 1, i8* %cxcy) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %cxcy) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + call void @llvm.lifetime.end.p0i8(i64 1, i8* %x) +; CHECK: call void @llvm.lifetime.end.p0i8(i64 1, i8* %x) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + ret void } declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) diff --git a/llvm/test/CodeGen/AArch64/stack-tagging.ll b/llvm/test/CodeGen/AArch64/stack-tagging.ll --- a/llvm/test/CodeGen/AArch64/stack-tagging.ll +++ b/llvm/test/CodeGen/AArch64/stack-tagging.ll @@ -192,10 +192,9 @@ ; CHECK: alloca { i32, [12 x i8] }, align 16 ; CHECK: call { i32, [12 x i8] }* @llvm.aarch64.tagp ; CHECK: call void @llvm.aarch64.settag( -; SSI: alloca i32, align 4 -; NOSSI: alloca { i32, [12 x i8] }, align 16 -; NOSSI: call { i32, [12 x i8] }* @llvm.aarch64.tagp -; NOSSI: call void @llvm.aarch64.settag( +; CHECK: alloca { i32, [12 x i8] }, align 16 +; CHECK: call { i32, [12 x i8] }* @llvm.aarch64.tagp +; CHECK: call void @llvm.aarch64.settag( ; CHECK: store i32 ; CHECK: call void @noUse32(i32* ; CHECK: store i32 @@ -203,7 +202,7 @@ ; CHECK: call void @noUse32(i32* ; CHECK: call void @llvm.aarch64.settag( ; CHECK: call void @llvm.aarch64.settag( -; NOSSI: call void @llvm.aarch64.settag( +; CHECK: call void @llvm.aarch64.settag( ; CHECK: ret void -!0 = !{} \ No newline at end of file +!0 = !{}