[llvm] f672791 - [StackSafety] Add pass for StackLifetime testing

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 18 16:34:30 PDT 2020


Author: Vitaly Buka
Date: 2020-06-18T16:34:18-07:00
New Revision: f672791e08fc819fd23f6331025570e24773ea82

URL: https://github.com/llvm/llvm-project/commit/f672791e08fc819fd23f6331025570e24773ea82
DIFF: https://github.com/llvm/llvm-project/commit/f672791e08fc819fd23f6331025570e24773ea82.diff

LOG: [StackSafety] Add pass for StackLifetime testing

Summary: lifetime.ll is a copy of SafeStack/X86/coloring2.ll

Reviewers: eugenis

Reviewed By: eugenis

Subscribers: hiraditya, mgrang, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D82043

Added: 
    llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll

Modified: 
    llvm/include/llvm/Analysis/StackLifetime.h
    llvm/lib/Analysis/StackLifetime.cpp
    llvm/lib/Passes/PassBuilder.cpp
    llvm/lib/Passes/PassRegistry.def

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/StackLifetime.h b/llvm/include/llvm/Analysis/StackLifetime.h
index 6622433b4dcd..577d9ba177ea 100644
--- a/llvm/include/llvm/Analysis/StackLifetime.h
+++ b/llvm/include/llvm/Analysis/StackLifetime.h
@@ -14,6 +14,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/PassManager.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <utility>
@@ -55,6 +56,8 @@ class StackLifetime {
   };
 
 public:
+  class LifetimeAnnotationWriter;
+
   /// This class represents a set of interesting instructions where an alloca is
   /// live.
   class LiveRange {
@@ -71,6 +74,8 @@ class StackLifetime {
     }
 
     void join(const LiveRange &Other) { Bits |= Other.Bits; }
+
+    bool test(unsigned Idx) const { return Bits.test(Idx); }
   };
 
 private:
@@ -135,6 +140,8 @@ class StackLifetime {
     assert(NumInst >= 0);
     return LiveRange(NumInst, true);
   }
+
+  void print(raw_ostream &O);
 };
 
 static inline raw_ostream &operator<<(raw_ostream &OS, const BitVector &V) {
@@ -158,6 +165,16 @@ inline raw_ostream &operator<<(raw_ostream &OS,
   return OS << R.Bits;
 }
 
+/// Printer pass for testing.
+class StackLifetimePrinterPass
+    : public PassInfoMixin<StackLifetimePrinterPass> {
+  raw_ostream &OS;
+
+public:
+  explicit StackLifetimePrinterPass(raw_ostream &OS) : OS(OS) {}
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
 } // end namespace llvm
 
 #endif // LLVM_ANALYSIS_STACKLIFETIME_H

diff  --git a/llvm/lib/Analysis/StackLifetime.cpp b/llvm/lib/Analysis/StackLifetime.cpp
index 7dde0ec38d57..efdfcf5c6c5c 100644
--- a/llvm/lib/Analysis/StackLifetime.cpp
+++ b/llvm/lib/Analysis/StackLifetime.cpp
@@ -8,17 +8,26 @@
 
 #include "llvm/Analysis/StackLifetime.h"
 #include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/IR/AssemblyAnnotationWriter.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CFG.h"
+#include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/User.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Pass.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/FormattedStream.h"
+#include <memory>
 #include <tuple>
 
 using namespace llvm;
@@ -284,3 +293,66 @@ void StackLifetime::run() {
   calculateLiveIntervals();
   LLVM_DEBUG(dumpLiveRanges());
 }
+
+class StackLifetime::LifetimeAnnotationWriter
+    : public AssemblyAnnotationWriter {
+  const StackLifetime &SL;
+  SmallVector<StringRef, 16> Names;
+
+  void printInstrAlive(unsigned InstrNo, formatted_raw_ostream &OS) {
+    Names.clear();
+    for (const auto &KV : SL.AllocaNumbering) {
+      if (SL.LiveRanges[KV.getSecond()].test(InstrNo))
+        Names.push_back(KV.getFirst()->getName());
+    }
+    llvm::sort(Names);
+    OS << "  ; Alive: <" << llvm::join(Names, " ") << ">\n";
+  }
+
+  void printBBAlive(const BasicBlock *BB, bool Start,
+                    formatted_raw_ostream &OS) {
+    auto ItBB = SL.BlockInstRange.find(BB);
+    if (ItBB == SL.BlockInstRange.end())
+      return; // Unreachable.
+    unsigned InstrNo =
+        Start ? ItBB->getSecond().first : (ItBB->getSecond().second - 1);
+    printInstrAlive(InstrNo, OS);
+  }
+
+  void emitBasicBlockStartAnnot(const BasicBlock *BB,
+                                formatted_raw_ostream &OS) override {
+    printBBAlive(BB, true, OS);
+  }
+  void emitBasicBlockEndAnnot(const BasicBlock *BB,
+                              formatted_raw_ostream &OS) override {
+    printBBAlive(BB, false, OS);
+  }
+
+  void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {
+    auto It = SL.InstructionNumbering.find(dyn_cast<IntrinsicInst>(&V));
+    if (It == SL.InstructionNumbering.end())
+      return; // Unintresting.
+    OS << "\n";
+    printInstrAlive(It->getSecond(), OS);
+  }
+
+public:
+  LifetimeAnnotationWriter(const StackLifetime &SL) : SL(SL) {}
+};
+
+void StackLifetime::print(raw_ostream &OS) {
+  LifetimeAnnotationWriter AAW(*this);
+  F.print(OS, &AAW);
+}
+
+PreservedAnalyses StackLifetimePrinterPass::run(Function &F,
+                                                FunctionAnalysisManager &AM) {
+  SmallVector<const AllocaInst *, 8> Allocas;
+  for (auto &I : instructions(F))
+    if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I))
+      Allocas.push_back(AI);
+  StackLifetime SL(F, Allocas);
+  SL.run();
+  SL.print(OS);
+  return PreservedAnalyses::all();
+}

diff  --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index c145ec42a960..49866f35e7fd 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -52,6 +52,7 @@
 #include "llvm/Analysis/ScalarEvolution.h"
 #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
 #include "llvm/Analysis/ScopedNoAliasAA.h"
+#include "llvm/Analysis/StackLifetime.h"
 #include "llvm/Analysis/StackSafetyAnalysis.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"

diff  --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index dc037ff1d3ec..a38c651c673c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -239,6 +239,7 @@ FUNCTION_PASS("print<phi-values>", PhiValuesPrinterPass(dbgs()))
 FUNCTION_PASS("print<regions>", RegionInfoPrinterPass(dbgs()))
 FUNCTION_PASS("print<scalar-evolution>", ScalarEvolutionPrinterPass(dbgs()))
 FUNCTION_PASS("print<stack-safety-local>", StackSafetyPrinterPass(dbgs()))
+FUNCTION_PASS("print<stack-lifetime>", StackLifetimePrinterPass(dbgs()))
 FUNCTION_PASS("reassociate", ReassociatePass())
 FUNCTION_PASS("scalarizer", ScalarizerPass())
 FUNCTION_PASS("sccp", SCCPPass())

diff  --git a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll
new file mode 100644
index 000000000000..61d0dc2286f6
--- /dev/null
+++ b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll
@@ -0,0 +1,766 @@
+; RUN: opt -passes='print<stack-lifetime>' -disable-output %s 2>&1 | FileCheck %s
+
+define void @f() {
+; CHECK-LABEL: define void @f()
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+  %z = alloca i32, align 4
+  %x0 = bitcast i32* %x to i8*
+  %y0 = bitcast i32* %y to i8*
+  %z0 = bitcast i32* %z to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
+; CHECK-NEXT: Alive: <z>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x z>
+
+  call void @capture32(i32* %x)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <z>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <y z>
+
+  call void @capture32(i32* %y)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <z>
+
+  call void @capture32(i32* %z)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
+; CHECK-NEXT: Alive: <>
+
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+}
+
+define void @no_markers() {
+; CHECK-LABEL: define void @no_markers()
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <y>
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+  %x0 = bitcast i32* %x to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x y>
+
+  call void @capture32(i32* %x)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <y>
+
+  call void @capture32(i32* %y)
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <y>
+}
+
+define void @g() {
+; CHECK-LABEL: define void @g()
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+  %z = alloca i64, align 4
+  %x0 = bitcast i32* %x to i8*
+  %y0 = bitcast i32* %y to i8*
+  %z0 = bitcast i64* %z to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <x y>
+
+  call void @capture32(i32* %x)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <y>
+
+  call void @capture32(i32* %y)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
+; CHECK-NEXT: Alive: <z>
+
+  call void @capture64(i64* %z)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
+; CHECK-NEXT: Alive: <>
+
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+}
+
+define void @h() {
+; CHECK-LABEL: define void @h()
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %x = alloca i32, align 16
+  %z = alloca i64, align 4
+  %y = alloca i32, align 4
+  %x0 = bitcast i32* %x to i8*
+  %y0 = bitcast i32* %y to i8*
+  %z0 = bitcast i64* %z to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <x y>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %z0)
+; CHECK-NEXT: Alive: <x y z>
+
+  call void @capture32(i32* %x)
+  call void @capture32(i32* %y)
+  call void @capture64(i64* %z)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <y z>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <z>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %z0)
+; CHECK-NEXT: Alive: <>
+
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+}
+
+define void @i(i1 zeroext %a, i1 zeroext %b) {
+; CHECK-LABEL: define void @i(i1 zeroext %a, i1 zeroext %b)
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %x1 = alloca i64, align 8
+  %x2 = alloca i64, align 8
+  %y = alloca i64, align 8
+  %y1 = alloca i64, align 8
+  %y2 = alloca i64, align 8
+  %z = alloca i64, align 8
+  %z1 = alloca i64, align 8
+  %z2 = alloca i64, align 8
+  %0 = bitcast i64* %x1 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
+; CHECK-NEXT: Alive: <x1>
+
+  %1 = bitcast i64* %x2 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1)
+; CHECK-NEXT: Alive: <x1 x2>
+
+  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:
+; CHECK-NEXT: Alive: <x1 x2>
+  %2 = bitcast i64* %y to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %2)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %2)
+; CHECK-NEXT: Alive: <x1 x2 y>
+
+  call void @capture64(i64* nonnull %y)
+  br i1 %b, label %if.then3, label %if.else
+; CHECK: br i1 %b, label %if.then3, label %if.else
+; CHECK-NEXT: Alive: <x1 x2 y>
+
+if.then3:                                         ; preds = %if.then
+; CHECK: if.then3:
+; CHECK-NEXT: Alive: <x1 x2 y>
+  %3 = bitcast i64* %y1 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %3)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %3)
+; CHECK-NEXT: Alive: <x1 x2 y y1>
+
+  call void @capture64(i64* nonnull %y1)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %3)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %3)
+; CHECK-NEXT: Alive: <x1 x2 y>
+
+  br label %if.end
+; CHECK: br label %if.end
+; CHECK-NEXT: Alive: <x1 x2 y>
+
+if.else:                                          ; preds = %if.then
+; CHECK: if.else:
+; CHECK-NEXT: Alive: <x1 x2 y>
+  %4 = bitcast i64* %y2 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %4)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %4)
+; CHECK-NEXT: Alive: <x1 x2 y y2>
+
+  call void @capture64(i64* nonnull %y2)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %4)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %4)
+; CHECK-NEXT: Alive: <x1 x2 y>
+
+  br label %if.end
+; CHECK: br label %if.end
+; CHECK-NEXT: Alive: <x1 x2 y>
+
+if.end:                                           ; preds = %if.else, %if.then3
+; CHECK: if.end:
+; CHECK-NEXT: Alive: <x1 x2 y>
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %2)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %2)
+; CHECK-NEXT: Alive: <x1 x2>
+
+  br label %if.end9
+; CHECK: br label %if.end9
+; CHECK-NEXT: Alive: <x1 x2>
+
+if.else4:                                         ; preds = %entry
+; CHECK: if.else4:
+; CHECK-NEXT: Alive: <x1 x2>
+  %5 = bitcast i64* %z to i8*
+  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>
+
+  call void @capture64(i64* nonnull %z)
+  br i1 %b, label %if.then6, label %if.else7
+; CHECK: br i1 %b, label %if.then6, label %if.else7
+; CHECK-NEXT: Alive: <x1 x2 z>
+
+if.then6:                                         ; preds = %if.else4
+; CHECK: if.then6:
+; CHECK-NEXT: Alive: <x1 x2 z>
+  %6 = bitcast i64* %z1 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6)
+; CHECK-NEXT: Alive: <x1 x2 z z1>
+
+  call void @capture64(i64* nonnull %z1)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %6)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %6)
+; CHECK-NEXT: Alive: <x1 x2 z>
+
+  br label %if.end8
+; CHECK: br label %if.end8
+; CHECK-NEXT: Alive: <x1 x2 z>
+
+if.else7:                                         ; preds = %if.else4
+; CHECK: if.else7:
+; CHECK-NEXT: Alive: <x1 x2 z>
+  %7 = bitcast i64* %z2 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7)
+; CHECK-NEXT: Alive: <x1 x2 z z2>
+
+  call void @capture64(i64* nonnull %z2)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %7)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %7)
+; CHECK-NEXT: Alive: <x1 x2 z>
+
+  br label %if.end8
+; CHECK: br label %if.end8
+; CHECK-NEXT: Alive: <x1 x2 z>
+
+if.end8:                                          ; preds = %if.else7, %if.then6
+; CHECK: if.end8:
+; CHECK-NEXT: Alive: <x1 x2 z>
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %5)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %5)
+; CHECK-NEXT: Alive: <x1 x2>
+
+  br label %if.end9
+; CHECK: br label %if.end9
+; CHECK-NEXT: Alive: <x1 x2>
+
+if.end9:                                          ; preds = %if.end8, %if.end
+; CHECK: if.end9:
+; CHECK-NEXT: Alive: <x1 x2>
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1)
+; CHECK-NEXT: Alive: <x1>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %0)
+; CHECK-NEXT: Alive: <>
+
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+}
+
+define void @no_merge1(i1 %d) {
+; CHECK-LABEL: define void @no_merge1(i1 %d)
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+  %x0 = bitcast i32* %x to i8*
+  %y0 = bitcast i32* %y to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x>
+
+  call void @capture32(i32* %x)
+  br i1 %d, label %bb2, label %bb3
+; CHECK: br i1 %d, label %bb2, label %bb3
+; CHECK-NEXT: Alive: <x>
+
+bb2:                                              ; preds = %entry
+; CHECK: bb2:
+; CHECK-NEXT: Alive: <x>
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <x y>
+
+  call void @capture32(i32* %y)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <x>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <>
+
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+
+bb3:                                              ; preds = %entry
+; CHECK: bb3:
+; CHECK-NEXT: Alive: <x>
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <>
+
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+}
+
+define void @merge1(i1 %d) {
+; CHECK-LABEL: define void @merge1(i1 %d)
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+  %x0 = bitcast i32* %x to i8*
+  %y0 = bitcast i32* %y to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x>
+
+  call void @capture32(i32* %x)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <>
+
+  br i1 %d, label %bb2, label %bb3
+; CHECK: br i1 %d, label %bb2, label %bb3
+; CHECK-NEXT: Alive: <>
+
+bb2:                                              ; preds = %entry
+; CHECK: bb2:
+; CHECK-NEXT: Alive: <>
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <y>
+
+  call void @capture32(i32* %y)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <>
+
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+
+bb3:                                              ; preds = %entry
+; CHECK: bb3:
+; CHECK-NEXT: Alive: <>
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+}
+
+define void @merge2_noend(i1 %d) {
+; CHECK-LABEL: define void @merge2_noend(i1 %d)
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+  %x0 = bitcast i32* %x to i8*
+  %y0 = bitcast i32* %y to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x>
+
+  call void @capture32(i32* %x)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <>
+
+  br i1 %d, label %bb2, label %bb3
+; CHECK: br i1 %d, label %bb2, label %bb3
+; CHECK-NEXT: Alive: <>
+
+bb2:                                              ; preds = %entry
+; CHECK: bb2:
+; CHECK-NEXT: Alive: <>
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <y>
+
+  call void @capture32(i32* %y)
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <y>
+
+bb3:                                              ; preds = %entry
+; CHECK: bb3:
+; CHECK-NEXT: Alive: <>
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+}
+
+define void @merge3_noend(i1 %d) {
+; CHECK-LABEL: define void @merge3_noend(i1 %d)
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+  %x0 = bitcast i32* %x to i8*
+  %y0 = bitcast i32* %y to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x>
+
+  call void @capture32(i32* %x)
+  br i1 %d, label %bb2, label %bb3
+; CHECK: br i1 %d, label %bb2, label %bb3
+; CHECK-NEXT: Alive: <x>
+
+bb2:                                              ; preds = %entry
+; CHECK: bb2:
+; CHECK-NEXT: Alive: <x>
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <y>
+
+  call void @capture32(i32* %y)
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <y>
+
+bb3:                                              ; preds = %entry
+; CHECK: bb3:
+; CHECK-NEXT: Alive: <x>
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <x>
+}
+
+define void @nomerge4_nostart(i1 %d) {
+; CHECK-LABEL: define void @nomerge4_nostart(i1 %d)
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <x>
+  %x = alloca i32, align 4
+  %y = alloca i32, align 4
+  %x0 = bitcast i32* %x to i8*
+  %y0 = bitcast i32* %y to i8*
+  call void @capture32(i32* %x)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %x0)
+; CHECK-NEXT: Alive: <x>
+
+  br i1 %d, label %bb2, label %bb3
+; CHECK: br i1 %d, label %bb2, label %bb3
+; CHECK-NEXT: Alive: <x>
+
+bb2:                                              ; preds = %entry
+; CHECK: bb2:
+; CHECK-NEXT: Alive: <x>
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %y0)
+; CHECK-NEXT: Alive: <x y>
+
+  call void @capture32(i32* %y)
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <x y>
+
+bb3:                                              ; preds = %entry
+; CHECK: bb3:
+; CHECK-NEXT: Alive: <x>
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <x>
+}
+
+define void @array_merge() {
+; CHECK-LABEL: define void @array_merge()
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %A.i1 = alloca [100 x i32], align 4
+  %B.i2 = alloca [100 x i32], align 4
+  %A.i = alloca [100 x i32], align 4
+  %B.i = alloca [100 x i32], align 4
+  %0 = bitcast [100 x i32]* %A.i to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
+; CHECK-NEXT: Alive: <A.i>
+
+  %1 = bitcast [100 x i32]* %B.i to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1)
+; CHECK-NEXT: Alive: <A.i B.i>
+
+  call void @capture100x32([100 x i32]* %A.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)
+; CHECK-NEXT: Alive: <B.i>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1)
+; CHECK-NEXT: Alive: <>
+
+  %2 = bitcast [100 x i32]* %A.i1 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %2)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %2)
+; CHECK-NEXT: Alive: <A.i1>
+
+  %3 = bitcast [100 x i32]* %B.i2 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %3)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %3)
+; CHECK-NEXT: Alive: <A.i1 B.i2>
+
+  call void @capture100x32([100 x i32]* %A.i1)
+  call void @capture100x32([100 x i32]* %B.i2)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %2)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %2)
+; CHECK-NEXT: Alive: <B.i2>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %3)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %3)
+; CHECK-NEXT: Alive: <>
+
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <>
+}
+
+define void @myCall_pr15707() {
+; CHECK-LABEL: define void @myCall_pr15707()
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %buf1 = alloca i8, i32 100000, align 16
+  %buf2 = alloca i8, i32 100000, align 16
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf1)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf1)
+; CHECK-NEXT: Alive: <buf1>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %buf1)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %buf1)
+; CHECK-NEXT: Alive: <>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf1)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf1)
+; CHECK-NEXT: Alive: <buf1>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf2)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %buf2)
+; CHECK-NEXT: Alive: <buf1 buf2>
+
+  call void @capture8(i8* %buf1)
+  call void @capture8(i8* %buf2)
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <buf1 buf2>
+}
+
+define void @bad_range() {
+; CHECK-LABEL: define void @bad_range()
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <A.i1 B.i2>
+  %A.i1 = alloca [100 x i32], align 4
+  %B.i2 = alloca [100 x i32], align 4
+  %A.i = alloca [100 x i32], align 4
+  %B.i = alloca [100 x i32], align 4
+  %0 = bitcast [100 x i32]* %A.i to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
+; CHECK-NEXT: Alive: <A.i A.i1 B.i2>
+
+  %1 = bitcast [100 x i32]* %B.i to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %1)
+; CHECK-NEXT: Alive: <A.i A.i1 B.i B.i2>
+
+  call void @capture100x32([100 x i32]* %A.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)
+; CHECK-NEXT: Alive: <A.i1 B.i B.i2>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %1)
+; CHECK-NEXT: Alive: <A.i1 B.i2>
+
+  br label %block2
+; CHECK: br label %block2
+; CHECK-NEXT: Alive: <A.i1 B.i2>
+
+block2:                                           ; preds = %entry
+; CHECK: block2:
+; CHECK-NEXT: Alive: <A.i1 B.i2>
+  call void @capture100x32([100 x i32]* %A.i)
+  call void @capture100x32([100 x i32]* %B.i)
+  ret void
+; CHECK: ret void
+; CHECK-NEXT: Alive: <A.i1 B.i2>
+}
+
+%struct.Klass = type { i32, i32 }
+
+define i32 @shady_range(i32 %argc, i8** nocapture %argv) {
+; CHECK-LABEL: define i32 @shady_range(i32 %argc, i8** nocapture %argv)
+entry:
+; CHECK: entry:
+; CHECK-NEXT: Alive: <>
+  %a.i = alloca [4 x %struct.Klass], align 16
+  %b.i = alloca [4 x %struct.Klass], align 16
+  %a8 = bitcast [4 x %struct.Klass]* %a.i to i8*
+  %b8 = bitcast [4 x %struct.Klass]* %b.i to i8*
+  %z2 = getelementptr inbounds [4 x %struct.Klass], [4 x %struct.Klass]* %a.i, i64 0, i64 0, i32 0
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a8)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a8)
+; CHECK-NEXT: Alive: <a.i>
+
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b8)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %b8)
+; CHECK-NEXT: Alive: <a.i b.i>
+
+  call void @capture8(i8* %a8)
+  call void @capture8(i8* %b8)
+  %z3 = load i32, i32* %z2, align 16
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %a8)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %a8)
+; CHECK-NEXT: Alive: <b.i>
+
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %b8)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %b8)
+; CHECK-NEXT: Alive: <>
+
+  ret i32 %z3
+; CHECK: ret i32 %z3
+; CHECK-NEXT: Alive: <>
+}
+
+define void @end_loop() {
+; CHECK-LABEL: define void @end_loop()
+entry:
+; 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)
+; CHECK-NEXT: Alive: <x>
+
+  br label %l2
+; CHECK: br label %l2
+; CHECK-NEXT: Alive: <x>
+
+l2:                                               ; preds = %l2, %entry
+; CHECK: l2:
+; CHECK-NEXT: Alive: <x>
+  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)
+; CHECK-NEXT: Alive: <>
+
+  br label %l2
+; CHECK: br label %l2
+; CHECK-NEXT: Alive: <>
+}
+
+define void @start_loop() {
+; CHECK-LABEL: define void @start_loop()
+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* %x)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %x)
+; CHECK-NEXT: Alive: <x>
+
+  br label %l2
+; CHECK: br label %l2
+; CHECK-NEXT: Alive: <x>
+
+l2:                                               ; preds = %l2, %entry
+; CHECK: l2:
+; CHECK-NEXT: Alive: <x>
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* %y)
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* %y)
+; CHECK-NEXT: Alive: <x y>
+
+  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)
+; CHECK-NEXT: Alive: <x>
+
+  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>
+
+  call void @capture8(i8* %x)
+  br label %l2
+; CHECK: br label %l2
+; CHECK-NEXT: Alive: <x>
+}
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+declare void @capture8(i8*)
+declare void @capture32(i32*)
+declare void @capture64(i64*)
+declare void @capture100x32([100 x i32]*)


        


More information about the llvm-commits mailing list