diff --git a/llvm/include/llvm/IR/ProfileSummary.h b/llvm/include/llvm/IR/ProfileSummary.h
--- a/llvm/include/llvm/IR/ProfileSummary.h
+++ b/llvm/include/llvm/IR/ProfileSummary.h
@@ -14,6 +14,7 @@
 #define LLVM_IR_PROFILESUMMARY_H
 
 #include <algorithm>
+#include <cassert>
 #include <cstdint>
 #include <vector>
 
@@ -56,6 +57,10 @@
   /// code. The common profile is usually merged from profiles collected
   /// from running other targets.
   bool Partial = false;
+  /// This approximately represents the ratio of the number of profile counters
+  /// of the program being built to the number of profile counters in the
+  /// partial sample profile. When 'Partial' is false, it is undefined.
+  double PartialProfileRatio = 0;
   /// Return detailed summary as metadata.
   Metadata *getDetailedSummaryMD(LLVMContext &Context);
 
@@ -66,15 +71,17 @@
                  uint64_t TotalCount, uint64_t MaxCount,
                  uint64_t MaxInternalCount, uint64_t MaxFunctionCount,
                  uint32_t NumCounts, uint32_t NumFunctions,
-                 bool Partial = false)
+                 bool Partial = false, double PartialProfileRatio = 0)
       : PSK(K), DetailedSummary(std::move(DetailedSummary)),
         TotalCount(TotalCount), MaxCount(MaxCount),
         MaxInternalCount(MaxInternalCount), MaxFunctionCount(MaxFunctionCount),
-        NumCounts(NumCounts), NumFunctions(NumFunctions), Partial(Partial) {}
+        NumCounts(NumCounts), NumFunctions(NumFunctions), Partial(Partial),
+        PartialProfileRatio(PartialProfileRatio) {}
 
   Kind getKind() const { return PSK; }
   /// Return summary information as metadata.
-  Metadata *getMD(LLVMContext &Context, bool AddPartialField = true);
+  Metadata *getMD(LLVMContext &Context, bool AddPartialField = true,
+                  bool AddPartialProfileRatioField = true);
   /// Construct profile summary from metdata.
   static ProfileSummary *getFromMD(Metadata *MD);
   SummaryEntryVector &getDetailedSummary() { return DetailedSummary; }
@@ -86,6 +93,11 @@
   uint64_t getMaxInternalCount() { return MaxInternalCount; }
   void setPartialProfile(bool PP) { Partial = PP; }
   bool isPartialProfile() { return Partial; }
+  double getPartialProfileRatio() { return PartialProfileRatio; }
+  void setPartialProfileRatio(double R) {
+    assert(isPartialProfile());
+    PartialProfileRatio = R;
+  }
   void printSummary(raw_ostream &OS);
   void printDetailedSummary(raw_ostream &OS);
 };
diff --git a/llvm/lib/IR/ProfileSummary.cpp b/llvm/lib/IR/ProfileSummary.cpp
--- a/llvm/lib/IR/ProfileSummary.cpp
+++ b/llvm/lib/IR/ProfileSummary.cpp
@@ -31,6 +31,14 @@
   return MDTuple::get(Context, Ops);
 }
 
+static Metadata *getKeyFPValMD(LLVMContext &Context, const char *Key,
+                               double Val) {
+  Type *DoubleTy = Type::getDoubleTy(Context);
+  Metadata *Ops[2] = {MDString::get(Context, Key),
+                      ConstantAsMetadata::get(ConstantFP::get(DoubleTy, Val))};
+  return MDTuple::get(Context, Ops);
+}
+
 // Return an MDTuple with two elements. The first element is a string Key and
 // the second is a string Value.
 static Metadata *getKeyValMD(LLVMContext &Context, const char *Key,
@@ -67,7 +75,10 @@
 // to the kind of profile summary as returned by getFormatSpecificMD.
 // IsPartialProfile is an optional field and \p AddPartialField will decide
 // whether to add a field for it.
-Metadata *ProfileSummary::getMD(LLVMContext &Context, bool AddPartialField) {
+// PartialProfileRatio is an optional field and \p AddPartialProfileRatioField
+// will decide whether to add a field for it.
+Metadata *ProfileSummary::getMD(LLVMContext &Context, bool AddPartialField,
+                                bool AddPartialProfileRatioField) {
   const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"};
   SmallVector<Metadata *, 16> Components;
   Components.push_back(getKeyValMD(Context, "ProfileFormat", KindStr[PSK]));
@@ -82,24 +93,43 @@
   if (AddPartialField)
     Components.push_back(
         getKeyValMD(Context, "IsPartialProfile", isPartialProfile()));
+  if (AddPartialProfileRatioField)
+    Components.push_back(getKeyFPValMD(Context, "PartialProfileRatio",
+                                       getPartialProfileRatio()));
   Components.push_back(getDetailedSummaryMD(Context));
   return MDTuple::get(Context, Components);
 }
 
-// Parse an MDTuple representing (Key, Val) pair.
-static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) {
+// Get the value metadata for the input MD/Key.
+static ConstantAsMetadata *getValMD(MDTuple *MD, const char *Key) {
   if (!MD)
-    return false;
+    return nullptr;
   if (MD->getNumOperands() != 2)
-    return false;
+    return nullptr;
   MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
   ConstantAsMetadata *ValMD = dyn_cast<ConstantAsMetadata>(MD->getOperand(1));
   if (!KeyMD || !ValMD)
-    return false;
+    return nullptr;
   if (!KeyMD->getString().equals(Key))
-    return false;
-  Val = cast<ConstantInt>(ValMD->getValue())->getZExtValue();
-  return true;
+    return nullptr;
+  return ValMD;
+}
+
+// Parse an MDTuple representing (Key, Val) pair.
+static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) {
+  if (auto *ValMD = getValMD(MD, Key)) {
+    Val = cast<ConstantInt>(ValMD->getValue())->getZExtValue();
+    return true;
+  }
+  return false;
+}
+
+static bool getVal(MDTuple *MD, const char *Key, double &Val) {
+  if (auto *ValMD = getValMD(MD, Key)) {
+    Val = cast<ConstantFP>(ValMD->getValue())->getValueAPF().convertToDouble();
+    return true;
+  }
+  return false;
 }
 
 // Check if an MDTuple represents a (Key, Val) pair.
@@ -163,7 +193,7 @@
 
 ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) {
   MDTuple *Tuple = dyn_cast_or_null<MDTuple>(MD);
-  if (!Tuple || Tuple->getNumOperands() < 8 || Tuple->getNumOperands() > 9)
+  if (!Tuple || Tuple->getNumOperands() < 8 || Tuple->getNumOperands() > 10)
     return nullptr;
 
   unsigned I = 0;
@@ -205,13 +235,17 @@
   uint64_t IsPartialProfile = 0;
   if (!getOptionalVal(Tuple, I, "IsPartialProfile", IsPartialProfile))
     return nullptr;
+  double PartialProfileRatio = 0;
+  if (!getOptionalVal(Tuple, I, "PartialProfileRatio", PartialProfileRatio))
+    return nullptr;
 
   SummaryEntryVector Summary;
   if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(I++)), Summary))
     return nullptr;
   return new ProfileSummary(SummaryKind, std::move(Summary), TotalCount,
                             MaxCount, MaxInternalCount, MaxFunctionCount,
-                            NumCounts, NumFunctions, IsPartialProfile);
+                            NumCounts, NumFunctions, IsPartialProfile,
+                            PartialProfileRatio);
 }
 
 void ProfileSummary::printSummary(raw_ostream &OS) {
diff --git a/llvm/test/Transforms/PGOProfile/unreachable_bb.ll b/llvm/test/Transforms/PGOProfile/unreachable_bb.ll
--- a/llvm/test/Transforms/PGOProfile/unreachable_bb.ll
+++ b/llvm/test/Transforms/PGOProfile/unreachable_bb.ll
@@ -16,7 +16,7 @@
 declare void @bar()
 
 ;USE: !0 = !{i32 1, !"ProfileSummary", !1}
-;USE: !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10}
+;USE: !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10, !11}
 ;USE: !2 = !{!"ProfileFormat", !"InstrProf"}
 ;USE: !3 = !{!"TotalCount", i64 0}
 
diff --git a/llvm/unittests/ProfileData/SampleProfTest.cpp b/llvm/unittests/ProfileData/SampleProfTest.cpp
--- a/llvm/unittests/ProfileData/SampleProfTest.cpp
+++ b/llvm/unittests/ProfileData/SampleProfTest.cpp
@@ -81,10 +81,13 @@
   // Metadata. \p AddPartialField is to choose whether the Metadata
   // contains the IsPartialProfile field which is optional.
   void verifyProfileSummary(ProfileSummary &Summary, Module &M,
-                            const bool AddPartialField) {
+                            const bool AddPartialField,
+                            const bool AddPartialProfileRatioField) {
     LLVMContext &Context = M.getContext();
     const bool IsPartialProfile = Summary.isPartialProfile();
-    auto VerifySummary = [IsPartialProfile](ProfileSummary &Summary) mutable {
+    const double PartialProfileRatio = Summary.getPartialProfileRatio();
+    auto VerifySummary = [IsPartialProfile, PartialProfileRatio](
+                             ProfileSummary &Summary) mutable {
       ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind());
       ASSERT_EQ(137392u, Summary.getTotalCount());
       ASSERT_EQ(8u, Summary.getNumCounts());
@@ -92,6 +95,7 @@
       ASSERT_EQ(1437u, Summary.getMaxFunctionCount());
       ASSERT_EQ(60351u, Summary.getMaxCount());
       ASSERT_EQ(IsPartialProfile, Summary.isPartialProfile());
+      ASSERT_EQ(PartialProfileRatio, Summary.getPartialProfileRatio());
 
       uint32_t Cutoff = 800000;
       auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) {
@@ -113,7 +117,8 @@
     VerifySummary(Summary);
 
     // Test that conversion of summary to and from Metadata works.
-    Metadata *MD = Summary.getMD(Context, AddPartialField);
+    Metadata *MD =
+        Summary.getMD(Context, AddPartialField, AddPartialProfileRatioField);
     ASSERT_TRUE(MD);
     ProfileSummary *PS = ProfileSummary::getFromMD(MD);
     ASSERT_TRUE(PS);
@@ -271,13 +276,16 @@
 
     ProfileSummary &Summary = Reader->getSummary();
     Summary.setPartialProfile(true);
-    verifyProfileSummary(Summary, M, true);
+    verifyProfileSummary(Summary, M, true, false);
 
     Summary.setPartialProfile(false);
-    verifyProfileSummary(Summary, M, true);
+    verifyProfileSummary(Summary, M, true, false);
 
-    Summary.setPartialProfile(false);
-    verifyProfileSummary(Summary, M, false);
+    verifyProfileSummary(Summary, M, false, false);
+
+    Summary.setPartialProfile(true);
+    Summary.setPartialProfileRatio(0.5);
+    verifyProfileSummary(Summary, M, true, true);
   }
 
   void addFunctionSamples(StringMap<FunctionSamples> *Smap, const char *Fname,