filter expensive
diff --git a/src/passes/hash-stringify-walker.cpp b/src/passes/hash-stringify-walker.cpp
index bad594e..b8e664e 100644
--- a/src/passes/hash-stringify-walker.cpp
+++ b/src/passes/hash-stringify-walker.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "ir/stack-utils.h"
 #include "stringify-walker.h"
 
 namespace wasm {
@@ -207,4 +208,64 @@
   return substrings;
 }
 
+uint32_t StringifyProcessor::savings(SuffixTree::RepeatedSubstring substring,
+                                     std::vector<Expression*> exprs) {
+  struct MeasureStringifyWalker
+    : public StringifyWalker<MeasureStringifyWalker> {
+    uint32_t exprSize = 0;
+
+    void addUniqueSymbol(SeparatorCtx ctx) {}
+
+    void visitExpression(Expression* curr) {
+      if (Properties::isControlFlowStructure(curr)) {
+        exprSize += Measurer::measure(curr);
+      } else {
+        exprSize += Measurer::BytesPerExpr;
+      }
+    }
+  };
+
+  uint32_t exprSize = 0;
+  for (uint32_t idx = substring.StartIndices[0];
+       idx < substring.StartIndices[0] + substring.Length;
+       idx++) {
+    Expression* curr = exprs[idx];
+    if (Properties::isControlFlowStructure(curr)) {
+      exprSize += Measurer::measure(curr);
+    } else {
+      exprSize += 1;
+    }
+  }
+
+  return exprSize * Measurer::BytesPerExpr * substring.StartIndices.size();
+}
+
+uint32_t StringifyProcessor::cost(SuffixTree::RepeatedSubstring substring,
+                                  std::vector<Expression*> exprs) {
+  StackSignature blockSig;
+  for (uint32_t idx = substring.StartIndices[0];
+       idx < substring.StartIndices[0] + substring.Length;
+       idx++) {
+    Expression* curr = exprs[idx];
+    StackSignature sig(curr);
+    blockSig += sig;
+  }
+
+  return (substring.StartIndices.size() * 3) + 8 + (blockSig.params.size() * 2);
+}
+
+std::vector<SuffixTree::RepeatedSubstring> StringifyProcessor::filterExpensive(
+  const std::vector<SuffixTree::RepeatedSubstring> substrings,
+  std::vector<Expression*> exprs) {
+  std::vector<SuffixTree::RepeatedSubstring> result;
+  for (auto substring : substrings) {
+    int32_t total = StringifyProcessor::savings(substring, exprs) -
+                    StringifyProcessor::cost(substring, exprs);
+    if (total > 0) {
+      result.push_back(substring);
+    }
+  }
+  return result;
+}
+
 } // namespace wasm
diff --git a/src/passes/outlining.cpp b/src/passes/outlining.cpp
index 30433e4..96f41bb 100644
--- a/src/passes/outlining.cpp
+++ b/src/passes/outlining.cpp
@@ -15,25 +15,30 @@
     auto result = StringifyProcessor::dedupe(substrings);
     result = StringifyProcessor::filterBranches(result, stringify.exprs);
     result = StringifyProcessor::filterLocalSets(result, stringify.exprs);
+    result = StringifyProcessor::filterExpensive(result, stringify.exprs);
     printStats(substrings, result, &stringify);
   }
 
   void printStats(std::vector<SuffixTree::RepeatedSubstring> substrings,
                   std::vector<SuffixTree::RepeatedSubstring> result,
                   HashStringifyWalker* stringify) {
-    std::cout << substrings.size() << " substrings found, ";
+    std::cout << substrings.size() << " repeat sequences found, ";
     std::cout << "reduced to " << result.size() << std::endl;
+    std::cout << "sequences: " << std::endl;
+    uint32_t totalSavings = 0;
     for (auto rs : result) {
       size_t startIndex = rs.StartIndices[0];
-      std::cout << rs.StartIndices.size() << "x, ~"
-                << rs.StartIndices.size() * rs.Length * Measurer::BytesPerExpr
-                << " size:";
+      uint32_t sizeSaved = StringifyProcessor::savings(rs, stringify->exprs) -
+                           StringifyProcessor::cost(rs, stringify->exprs);
+      totalSavings += sizeSaved;
+      std::cout << "length " << rs.Length << " repeats "
+                << rs.StartIndices.size() << "x, ~" << sizeSaved << " bytes:";
       for (size_t i = startIndex; i < startIndex + rs.Length; i++) {
-        std::cout << stringify->hashString[i] << " ("
-                  << ShallowExpression{stringify->exprs[i]} << "), ";
+        std::cout << " (" << ShallowExpression{stringify->exprs[i]} << "),";
       }
       std::cout << std::endl;
     }
+    std::cout << "Total Savings: ~" << totalSavings << " bytes" << std::endl;
   }
 };
 
diff --git a/src/passes/stringify-walker.h b/src/passes/stringify-walker.h
index d846bf2..a848f84 100644
--- a/src/passes/stringify-walker.h
+++ b/src/passes/stringify-walker.h
@@ -238,6 +238,13 @@
                  std::vector<Expression*> exprs);
   static std::vector<SuffixTree::RepeatedSubstring>
   repeatSubstrings(std::vector<uint32_t> hashString);
+  static uint32_t savings(SuffixTree::RepeatedSubstring substring,
+                          std::vector<Expression*> exprs);
+  static uint32_t cost(SuffixTree::RepeatedSubstring substring,
+                       std::vector<Expression*> exprs);
+  static std::vector<SuffixTree::RepeatedSubstring>
+  filterExpensive(const std::vector<SuffixTree::RepeatedSubstring> substrings,
+                  std::vector<Expression*> exprs);
 };
 
 } // namespace wasm