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 @@ -64,18 +64,44 @@ return getLiveRange(AI).test(InstNum); } +// Returns unique alloca annotated by lifetime marker only if +// markers has the same size and points to the alloca start. +static const AllocaInst *findMatchingAlloca(const IntrinsicInst &II, + const DataLayout &DL) { + const AllocaInst *AI = findAllocaForValue(II.getArgOperand(1), true); + if (!AI) + return nullptr; + + auto AllocaSizeInBits = AI->getAllocationSizeInBits(DL); + if (!AllocaSizeInBits) + return nullptr; + int64_t AllocaSize = AllocaSizeInBits.getValue() / 8; + + auto *Size = dyn_cast(II.getArgOperand(0)); + if (!Size) + return nullptr; + int64_t LifetimeSize = Size->getSExtValue(); + + if (LifetimeSize != -1 && LifetimeSize != AllocaSize) + return nullptr; + + return AI; +} + void StackLifetime::collectMarkers() { InterestingAllocas.resize(NumAllocas); DenseMap> BBMarkerSet; + const DataLayout &DL = F.getParent()->getDataLayout(); + // Compute the set of start/end markers per basic block. 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)); + const AllocaInst *AI = findMatchingAlloca(*II, DL); if (!AI) { HasUnknownLifetimeStartOrEnd = true; continue; 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 @@ -648,8 +648,8 @@ ; CHECK: entry: ; CHECK-NEXT: Alive: <> %x = alloca i8, align 4 - call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) -; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) ; CHECK-NEXT: Alive: br label %l2 @@ -659,8 +659,8 @@ ; 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) + call void @llvm.lifetime.end.p0i8(i64 1, i8* %x) +; CHECK: call void @llvm.lifetime.end.p0i8(i64 1, i8* %x) ; CHECK-NEXT: Alive: <> br label %l2 @@ -673,8 +673,8 @@ ; CHECK-NEXT: Alive: <> %x = alloca i8, align 4 %y = alloca i8, align 4 - call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) -; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) ; CHECK-NEXT: Alive: br label %l2 @@ -682,17 +682,17 @@ l2: ; preds = %l2, %entry ; CHECK: l2: ; CHECK-NEXT: Alive: - call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) -; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) ; CHECK-NEXT: Alive: call void @capture8(i8* %y) - call void @llvm.lifetime.end.p0i8(i64 4, i8* %y) -; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* %y) + call void @llvm.lifetime.end.p0i8(i64 1, i8* %y) +; CHECK: call void @llvm.lifetime.end.p0i8(i64 1, 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) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) ; CHECK-NEXT: Alive: call void @capture8(i8* %x) @@ -758,8 +758,8 @@ 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) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) ; CHECK-NEXT: Alive: br label %if.end @@ -769,12 +769,12 @@ 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) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, 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) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) ; CHECK-NEXT: Alive: br label %if.end @@ -797,12 +797,12 @@ %x = alloca i8, align 4 %y = alloca i8, align 4 - call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) -; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, 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) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) +; CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) ; CHECK-NEXT: Alive: br label %end @@ -880,8 +880,54 @@ ret void } +define void @alloca_offset() { +; CHECK-LABEL: define void @alloca_offset +entry: +; CHECK: entry: +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + %x = alloca [5 x i32], align 4 + %x2 = getelementptr [5 x i32], [5 x i32]* %x, i64 0, i64 1 + + call void @llvm.lifetime.start.p0i32(i64 20, i32* %x2) +; CHECK: call void @llvm.lifetime.start.p0i32(i64 20, i32* %x2) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + call void @llvm.lifetime.end.p0i32(i64 20, i32* %x2) +; CHECK: call void @llvm.lifetime.end.p0i32(i64 20, i32* %x2) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + ret void +} + +define void @alloca_size() { +; CHECK-LABEL: define void @alloca_size +entry: +; CHECK: entry: +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + %x = alloca [5 x i32], align 4 + %x2 = getelementptr [5 x i32], [5 x i32]* %x, i64 0, i64 0 + + call void @llvm.lifetime.start.p0i32(i64 15, i32* %x2) +; CHECK: call void @llvm.lifetime.start.p0i32(i64 15, i32* %x2) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + call void @llvm.lifetime.end.p0i32(i64 15, i32* %x2) +; CHECK: call void @llvm.lifetime.end.p0i32(i64 15, i32* %x2) +; MAY-NEXT: Alive: +; MUST-NEXT: Alive: <> + + ret void +} + declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) +declare void @llvm.lifetime.start.p0i32(i64, i32* nocapture) +declare void @llvm.lifetime.end.p0i32(i64, i32* nocapture) declare void @capture8(i8*) declare void @capture32(i32*) declare void @capture64(i64*) diff --git a/llvm/test/Transforms/SafeStack/X86/layout-frag.ll b/llvm/test/Transforms/SafeStack/X86/layout-frag.ll --- a/llvm/test/Transforms/SafeStack/X86/layout-frag.ll +++ b/llvm/test/Transforms/SafeStack/X86/layout-frag.ll @@ -14,16 +14,16 @@ %x0a = bitcast i64* %x0 to i8* %x2a = bitcast i64* %x2 to i8* - call void @llvm.lifetime.start.p0i8(i64 4, i8* %x0a) + call void @llvm.lifetime.start.p0i8(i64 8, i8* %x0a) call void @capture64(i64* %x0) - call void @llvm.lifetime.end.p0i8(i64 4, i8* %x0a) + call void @llvm.lifetime.end.p0i8(i64 8, i8* %x0a) - call void @llvm.lifetime.start.p0i8(i64 4, i8* %x1) - call void @llvm.lifetime.start.p0i8(i64 4, i8* %x2a) + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x1) + call void @llvm.lifetime.start.p0i8(i64 8, i8* %x2a) call void @capture8(i8* %x1) call void @capture64(i64* %x2) - call void @llvm.lifetime.end.p0i8(i64 4, i8* %x1) - call void @llvm.lifetime.end.p0i8(i64 4, i8* %x2a) + call void @llvm.lifetime.end.p0i8(i64 1, i8* %x1) + call void @llvm.lifetime.end.p0i8(i64 8, i8* %x2a) ; Test that i64 allocas share space. ; CHECK: getelementptr i8, i8* %unsafe_stack_ptr, i32 -8