diff --git a/src/analysis/function_analysis.cpp b/src/analysis/function_analysis.cpp
index faf323be604b7996d6adccdb51c8968153daeab2..32ffc4f79462abedd20f67e0cc3ee784bf8a15dc 100644
--- a/src/analysis/function_analysis.cpp
+++ b/src/analysis/function_analysis.cpp
@@ -18,6 +18,9 @@
 #include <unordered_set>
 #include <deque>
 
+#include <llvm/ADT/SetVector.h>
+#include <llvm/ADT/SmallSet.h>
+
 #include "core/common.h"
 
 #include "core/ast.h"
@@ -32,7 +35,7 @@ namespace pyston {
 
 class LivenessBBVisitor : public NoopASTVisitor {
 public:
-    typedef std::unordered_set<std::string> StrSet;
+    typedef llvm::SmallSet<std::string, 4> StrSet;
 
 private:
     StrSet _loads;
@@ -91,10 +94,11 @@ bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) {
     // for each query, trace forward through all possible control flow paths.
     // if we hit a store to the name, stop tracing that path
     // if we hit a load to the name, return true.
-    std::unordered_set<CFGBlock*> visited;
+    // to improve performance we cache the liveness result of every visited BB.
+    llvm::SmallPtrSet<CFGBlock*, 1> visited;
     std::deque<CFGBlock*> q;
-    for (int i = 0; i < block->successors.size(); i++) {
-        q.push_back(block->successors[i]);
+    for (CFGBlock* successor : block->successors) {
+        q.push_back(successor);
     }
 
     while (q.size()) {
@@ -102,22 +106,29 @@ bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) {
         q.pop_front();
         if (visited.count(thisblock))
             continue;
-        visited.insert(thisblock);
 
-        LivenessBBVisitor visitor;
-        for (int i = 0; i < thisblock->body.size(); i++) {
-            thisblock->body[i]->accept(&visitor);
+        LivenessBBVisitor* visitor = nullptr;
+        LivenessCacheMap::iterator it = livenessCache.find(thisblock);
+        if (it != livenessCache.end()) {
+            visitor = it->second.get();
+        } else {
+            visitor = new LivenessBBVisitor; // livenessCache unique_ptr will delete it.
+            for (AST_stmt* stmt : thisblock->body) {
+                stmt->accept(visitor);
+            }
+            livenessCache.insert(std::make_pair(thisblock, std::unique_ptr<LivenessBBVisitor>(visitor)));
         }
+        visited.insert(thisblock);
 
-        if (visitor.loads().count(name)) {
-            assert(!visitor.stores().count(name));
+        if (visitor->loads().count(name)) {
+            assert(!visitor->stores().count(name));
             return true;
         }
 
-        if (!visitor.stores().count(name)) {
-            assert(!visitor.loads().count(name));
-            for (int i = 0; i < thisblock->successors.size(); i++) {
-                q.push_back(thisblock->successors[i]);
+        if (!visitor->stores().count(name)) {
+            assert(!visitor->loads().count(name));
+            for (CFGBlock* successor : thisblock->successors) {
+                q.push_back(successor);
             }
         }
     }
diff --git a/src/analysis/function_analysis.h b/src/analysis/function_analysis.h
index 50e7e15d01dfaed50de8c2534b289bbea04b9450..b0108f8b61554dafb6bc5e8794f1c65f84ac6594 100644
--- a/src/analysis/function_analysis.h
+++ b/src/analysis/function_analysis.h
@@ -25,10 +25,15 @@ class AST_Jump;
 class CFG;
 class CFGBlock;
 class ScopeInfo;
+class LivenessBBVisitor;
 
 class LivenessAnalysis {
 public:
     bool isLiveAtEnd(const std::string& name, CFGBlock* block);
+
+private:
+    typedef std::unordered_map<CFGBlock*, std::unique_ptr<LivenessBBVisitor> > LivenessCacheMap;
+    LivenessCacheMap livenessCache;
 };
 class DefinednessAnalysis {
 public: