diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 9cbce17ca864f6f13ba22c8d14b6298e33aae058..02bb036a0a9e47261aa211224369cf6419b5b104 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -193,6 +193,9 @@ private:
   /// \sa getGraphTrimInterval
   llvm::Optional<unsigned> GraphTrimInterval;
 
+  /// \sa getMaxTimesInlineLarge
+  llvm::Optional<unsigned> MaxTimesInlineLarge;
+
   /// Interprets an option's string value as a boolean.
   ///
   /// Accepts the strings "true" and "false".
@@ -276,6 +279,11 @@ public:
   /// node reclamation, set the option to "0".
   unsigned getGraphTrimInterval();
 
+  /// Returns the maximum times a large function could be inlined.
+  ///
+  /// This is controlled by the 'max-times-inline-large' config option.
+  unsigned getMaxTimesInlineLarge();
+
 public:
   AnalyzerOptions() : CXXMemberInliningMode() {
     AnalysisStoreOpt = RegionStoreModel;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
index 9e2505fe60d4310d9ecd6db6d8d8c6d62ff8fce4..546cec568f960ce9fbc267a7859a2ff27e7777e5 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
@@ -37,10 +37,14 @@ class FunctionSummariesTy {
     /// Marks the IDs of the basic blocks visited during the analyzes.
     llvm::BitVector VisitedBasicBlocks;
 
+    /// The number of times the function has been inlined.
+    unsigned TimesInlined;
+
     FunctionSummary() :
       MayReachMaxBlockCount(false),
       TotalBasicBlocks(0),
-      VisitedBasicBlocks(0) {}
+      VisitedBasicBlocks(0),
+      TimesInlined(0) {}
   };
 
   typedef llvm::DenseMap<const Decl*, FunctionSummary*> MapTy;
@@ -84,11 +88,23 @@ public:
 
   unsigned getNumVisitedBasicBlocks(const Decl* D) {
     MapTy::const_iterator I = Map.find(D);
-      if (I != Map.end())
-        return I->second->VisitedBasicBlocks.count();
+    if (I != Map.end())
+      return I->second->VisitedBasicBlocks.count();
     return 0;
   }
 
+  unsigned getNumTimesInlined(const Decl* D) {
+    MapTy::const_iterator I = Map.find(D);
+    if (I != Map.end())
+      return I->second->TimesInlined;
+    return 0;
+  }
+
+  void bumpNumTimesInlined(const Decl* D) {
+    MapTy::iterator I = findOrInsertSummary(D);
+    I->second->TimesInlined++;
+  }
+
   /// Get the percentage of the reachable blocks.
   unsigned getPercentBlocksReachable(const Decl *D) {
     MapTy::const_iterator I = Map.find(D);
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 8ecbac009d3e8eafdd14285c21f4f39e25ce2594..b993804afeadb358b08b9288574e171b8b58ec24 100644
--- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -133,6 +133,12 @@ unsigned AnalyzerOptions::getGraphTrimInterval() {
   return GraphTrimInterval.getValue();
 }
 
+unsigned AnalyzerOptions::getMaxTimesInlineLarge() {
+  if (!MaxTimesInlineLarge.hasValue())
+    MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
+  return MaxTimesInlineLarge.getValue();
+}
+
 bool AnalyzerOptions::shouldSynthesizeBodies() {
   return getBooleanOption("faux-bodies", true);
 }
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index d654bb5f7073d34c0df9166f81cd387a9c6706ce..7c1c26e8f77f87face662a2f340f43714ddf235a 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -33,6 +33,9 @@ STATISTIC(NumOfDynamicDispatchPathSplits,
 STATISTIC(NumInlinedCalls,
   "The # of times we inlined a call");
 
+STATISTIC(NumReachedInlineCountMax,
+  "The # of times we reached inline count maximum");
+
 void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
   // Get the entry block in the CFG of the callee.
   const StackFrameContext *calleeCtx = CE.getCalleeContext();
@@ -415,12 +418,12 @@ bool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) {
   if (getContext().getLangOpts().CPlusPlus) {
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
       // Conditionally allow the inlining of template functions.
-      if (!getAnalysisManager().options.mayInlineTemplateFunctions())
+      if (!AMgr.options.mayInlineTemplateFunctions())
         if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
           return false;
 
       // Conditionally allow the inlining of C++ standard library functions.
-      if (!getAnalysisManager().options.mayInlineCXXStandardLibrary())
+      if (!AMgr.options.mayInlineCXXStandardLibrary())
         if (getContext().getSourceManager().isInSystemHeader(FD->getLocation()))
           if (IsInStdNamespace(FD))
             return false;
@@ -432,6 +435,14 @@ bool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) {
   if (!CalleeADC->getAnalysis<RelaxedLiveVariables>())
     return false;
 
+  if (Engine.FunctionSummaries->getNumTimesInlined(D) >
+        AMgr.options.getMaxTimesInlineLarge() &&
+      CalleeCFG->getNumBlockIDs() > 13) {
+    NumReachedInlineCountMax++;
+    return false;
+  }
+  Engine.FunctionSummaries->bumpNumTimesInlined(D);
+
   return true;
 }
 
diff --git a/test/Analysis/analyzer-config.c b/test/Analysis/analyzer-config.c
index 990f5784b42bed538613ef7e716d6deaa887a583..d156a6ec3b5305ddfd101ad8ec78f232b4c584bb 100644
--- a/test/Analysis/analyzer-config.c
+++ b/test/Analysis/analyzer-config.c
@@ -9,5 +9,6 @@ void foo() { bar(); }
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: graph-trim-interval = 1000
 // CHECK-NEXT: ipa-always-inline-size = 3
+// CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 4
+// CHECK-NEXT: num-entries = 5
diff --git a/test/Analysis/analyzer-config.cpp b/test/Analysis/analyzer-config.cpp
index fb142669b428e05856877496f25d5b687b85c9b8..b3a8b34d49528f87565699c4087487f614edab1a 100644
--- a/test/Analysis/analyzer-config.cpp
+++ b/test/Analysis/analyzer-config.cpp
@@ -18,5 +18,6 @@ public:
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: graph-trim-interval = 1000
 // CHECK-NEXT: ipa-always-inline-size = 3
+// CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 7
+// CHECK-NEXT: num-entries = 8