[SafeStack,NFC] Print liveness for all instrunctions
authorVitaly Buka <vitalybuka@google.com>
Fri, 19 Jun 2020 07:49:23 +0000 (00:49 -0700)
committerVitaly Buka <vitalybuka@google.com>
Fri, 19 Jun 2020 09:32:17 +0000 (02:32 -0700)
llvm/include/llvm/Analysis/StackLifetime.h
llvm/lib/Analysis/StackLifetime.cpp
llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll

index 5ebc6c8..ad0e3d6 100644 (file)
@@ -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) {
index 0bc40c1..d335821 100644 (file)
@@ -27,6 +27,7 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/FormattedStream.h"
+#include <algorithm>
 #include <memory>
 #include <tuple>
 
@@ -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<StringRef, 16> 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<Instruction>(&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();
 }
index e25b3a6..1c7eeb5 100644 (file)
@@ -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: <x1 x2>
 
 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: <x1 x2>
+
   %5 = bitcast i64* %z to i8*
+; CHECK: %5 = bitcast i64* %z to i8*
+; CHECK-NEXT: Alive: <x1 x2>
+
   call void @llvm.lifetime.start.p0i8(i64 -1, i8* %5)
 ; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %5)
 ; CHECK-NEXT: Alive: <x1 x2 z>
@@ -494,6 +506,9 @@ entry:
 ; CHECK-NEXT: Alive: <A.i B.i>
 
   call void @capture100x32([100 x i32]* %A.i)
+; CHECK: call void @capture100x32([100 x i32]* %A.i)
+; CHECK-NEXT: Alive: <A.i B.i>
+
   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: <y>
 
   br label %if.end
+; CHECK: br label %if.end
+; CHECK-NEXT: Alive: <y>
 
 if.else:
 ; CHECK: if.else:
@@ -715,6 +734,8 @@ if.else:
 ; CHECK-NEXT: Alive: <x y>
 
   br label %if.end
+; CHECK: br label %if.end
+; CHECK-NEXT: Alive: <x y>
 
 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: <y>
+
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* %x)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %x)
+; CHECK-NEXT: Alive: <x y>
+
+  br label %end
+; CHECK: br label %end
+; CHECK-NEXT: Alive: <x y>
+
+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: <x y>
+
+ret void
+}
+
 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
 declare void @capture8(i8*)