diff --git a/llvm/include/llvm/Analysis/StackLifetime.h b/llvm/include/llvm/Analysis/StackLifetime.h index 5ebc6c81172f..ad0e3d69cedb 100644 --- a/llvm/include/llvm/Analysis/StackLifetime.h +++ b/llvm/include/llvm/Analysis/StackLifetime.h @@ -156,7 +156,7 @@ public: return LiveRange(Instructions.size(), true); } - void print(raw_ostream &O); + void print(raw_ostream &O, bool AllInstructions = false); }; static inline raw_ostream &operator<<(raw_ostream &OS, const BitVector &V) { diff --git a/llvm/lib/Analysis/StackLifetime.cpp b/llvm/lib/Analysis/StackLifetime.cpp index 0bc40c10597d..d3358219e9f4 100644 --- a/llvm/lib/Analysis/StackLifetime.cpp +++ b/llvm/lib/Analysis/StackLifetime.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" +#include #include #include @@ -297,6 +298,8 @@ void StackLifetime::run() { class StackLifetime::LifetimeAnnotationWriter : public AssemblyAnnotationWriter { const StackLifetime &SL; + bool AllInstructions; + void printInstrAlive(unsigned InstrNo, formatted_raw_ostream &OS) { SmallVector Names; for (const auto &KV : SL.AllocaNumbering) { @@ -316,19 +319,33 @@ class StackLifetime::LifetimeAnnotationWriter } void printInfoComment(const Value &V, formatted_raw_ostream &OS) override { - auto It = llvm::find(SL.Instructions, &V); - if (It == SL.Instructions.end()) - return; // Unintresting. + const Instruction *Instr = dyn_cast(&V); + if (!Instr) + return; + auto ItBB = SL.BlockInstRange.find(Instr->getParent()); + if (ItBB == SL.BlockInstRange.end()) + return; // Unreachable. + // Find the first instruction after the V. + auto It = + std::upper_bound(SL.Instructions.begin() + ItBB->getSecond().first + 1, + SL.Instructions.begin() + ItBB->getSecond().second, + Instr, [](const Instruction *L, const Instruction *R) { + return L->comesBefore(R); + }); + --It; + if (!AllInstructions && *It != Instr) + return; OS << "\n"; printInstrAlive(It - SL.Instructions.begin(), OS); } public: - LifetimeAnnotationWriter(const StackLifetime &SL) : SL(SL) {} + LifetimeAnnotationWriter(const StackLifetime &SL, bool AllInstructions) + : SL(SL), AllInstructions(AllInstructions) {} }; -void StackLifetime::print(raw_ostream &OS) { - LifetimeAnnotationWriter AAW(*this); +void StackLifetime::print(raw_ostream &OS, bool AllInstructions) { + LifetimeAnnotationWriter AAW(*this, AllInstructions); F.print(OS, &AAW); } @@ -340,6 +357,6 @@ PreservedAnalyses StackLifetimePrinterPass::run(Function &F, Allocas.push_back(AI); StackLifetime SL(F, Allocas, Type); SL.run(); - SL.print(OS); + SL.print(OS, true); return PreservedAnalyses::all(); } diff --git a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll index e25b3a67c9a8..1c7eeb5ac69c 100644 --- a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll +++ b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll @@ -8,6 +8,8 @@ entry: ; CHECK-NEXT: Alive: <> %x = alloca i32, align 4 %y = alloca i32, align 4 +; CHECK: %y = alloca i32, align 4 +; CHECK-NEXT: Alive: <> %z = alloca i32, align 4 %x0 = bitcast i32* %x to i8* %y0 = bitcast i32* %y to i8* @@ -102,6 +104,8 @@ entry: ; CHECK-NEXT: Alive: <> ret void +; CHECK: ret void +; CHECK-NEXT: Alive: <> } define void @h() { @@ -110,6 +114,8 @@ entry: ; CHECK: entry: ; CHECK-NEXT: Alive: <> %x = alloca i32, align 16 +; CHECK: %x = alloca i32, align 16 +; CHECK-NEXT: Alive: <> %z = alloca i64, align 4 %y = alloca i32, align 4 %x0 = bitcast i32* %x to i8* @@ -171,6 +177,8 @@ entry: call void @capture64(i64* nonnull %x1) call void @capture64(i64* nonnull %x2) br i1 %a, label %if.then, label %if.else4 +; CHECK: br i1 %a, label %if.then, label %if.else4 +; CHECK-NEXT: Alive: if.then: ; preds = %entry ; CHECK: if.then: @@ -225,7 +233,11 @@ if.end: ; preds = %if.else, %if.then3 if.else4: ; preds = %entry ; CHECK: if.else4: ; CHECK-NEXT: Alive: + %5 = bitcast i64* %z to i8* +; CHECK: %5 = bitcast i64* %z to i8* +; CHECK-NEXT: Alive: + call void @llvm.lifetime.start.p0i8(i64 -1, i8* %5) ; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %5) ; CHECK-NEXT: Alive: @@ -494,6 +506,9 @@ entry: ; CHECK-NEXT: Alive: call void @capture100x32([100 x i32]* %A.i) +; CHECK: call void @capture100x32([100 x i32]* %A.i) +; CHECK-NEXT: Alive: + call void @capture100x32([100 x i32]* %B.i) call void @llvm.lifetime.end.p0i8(i64 -1, i8* %0) ; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %0) @@ -693,6 +708,8 @@ entry: %y = alloca i8, align 4 br i1 %a, label %if.then, label %if.else +; CHECK: br i1 %a, label %if.then, label %if.else +; CHECK-NEXT: Alive: <> if.then: ; CHECK: if.then: @@ -702,6 +719,8 @@ if.then: ; CHECK-NEXT: Alive: br label %if.end +; CHECK: br label %if.end +; CHECK-NEXT: Alive: if.else: ; CHECK: if.else: @@ -715,6 +734,8 @@ if.else: ; CHECK-NEXT: Alive: br label %if.end +; CHECK: br label %if.end +; CHECK-NEXT: Alive: if.end: ; CHECK: if.end: @@ -724,6 +745,42 @@ if.end: ret void } +define void @unreachable() { +; CHECK-LABEL: define void @unreachable +entry: +; CHECK: entry: +; CHECK-NEXT: Alive: <> + %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) +; 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 %end +; CHECK: br label %end +; CHECK-NEXT: Alive: + +dead: +; CHECK: dead: +; CHECK-NOT: Alive: + call void @llvm.lifetime.start.p0i8(i64 4, i8* %y) + + br label %end +; CHECK: br label %end +; CHECK-NOT: Alive: + +end: +; CHECK: end: +; CHECK-NEXT: Alive: + +ret void +} + declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) declare void @capture8(i8*)