[llvm-profdata] Add support for weighted merge of profile data (2nd try)
[oota-llvm.git] / include / llvm / ProfileData / InstrProf.h
index 6d7a8716787060eb0b7af372c8739702d96cedc1..98cb5b8e25a7a492e3530796429bc6ae1c7c18dc 100644 (file)
@@ -219,7 +219,8 @@ struct InstrProfValueSiteRecord {
   }
 
   /// Merge data from another InstrProfValueSiteRecord
-  void mergeValueData(InstrProfValueSiteRecord &Input) {
+  /// Optionally scale merged counts by \p Weight.
+  void mergeValueData(InstrProfValueSiteRecord &Input, uint64_t Weight = 1) {
     this->sortByTargetValues();
     Input.sortByTargetValues();
     auto I = ValueData.begin();
@@ -229,7 +230,15 @@ struct InstrProfValueSiteRecord {
       while (I != IE && I->Value < J->Value)
         ++I;
       if (I != IE && I->Value == J->Value) {
-        I->Count = SaturatingAdd(I->Count, J->Count);
+        // FIXME: Improve handling of counter overflow.
+        uint64_t JCount = J->Count;
+        bool Overflowed;
+        if (Weight > 1) {
+          JCount = SaturatingMultiply(JCount, Weight, &Overflowed);
+          assert(!Overflowed && "Value data counter overflowed!");
+        }
+        I->Count = SaturatingAdd(I->Count, JCount, &Overflowed);
+        assert(!Overflowed && "Value data counter overflowed!");
         ++I;
         continue;
       }
@@ -275,7 +284,8 @@ struct InstrProfRecord {
                            ValueMapType *HashKeys);
 
   /// Merge the counts in \p Other into this one.
-  inline instrprof_error merge(InstrProfRecord &Other);
+  /// Optionally scale merged counts by \p Weight.
+  inline instrprof_error merge(InstrProfRecord &Other, uint64_t Weight = 1);
 
   /// Used by InstrProfWriter: update the value strings to commoned strings in
   /// the writer instance.
@@ -327,7 +337,9 @@ private:
   }
 
   // Merge Value Profile data from Src record to this record for ValueKind.
-  instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src) {
+  // Scale merged value counts by \p Weight.
+  instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
+                                     uint64_t Weight) {
     uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
     uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
     if (ThisNumValueSites != OtherNumValueSites)
@@ -337,7 +349,7 @@ private:
     std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =
         Src.getValueSitesForKind(ValueKind);
     for (uint32_t I = 0; I < ThisNumValueSites; I++)
-      ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I]);
+      ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I], Weight);
     return instrprof_error::success;
   }
 };
@@ -423,7 +435,8 @@ void InstrProfRecord::updateStrings(InstrProfStringTable *StrTab) {
       VData.Value = (uint64_t)StrTab->insertString((const char *)VData.Value);
 }
 
-instrprof_error InstrProfRecord::merge(InstrProfRecord &Other) {
+instrprof_error InstrProfRecord::merge(InstrProfRecord &Other,
+                                       uint64_t Weight) {
   // If the number of counters doesn't match we either have bad data
   // or a hash collision.
   if (Counts.size() != Other.Counts.size())
@@ -432,14 +445,20 @@ instrprof_error InstrProfRecord::merge(InstrProfRecord &Other) {
   instrprof_error Result = instrprof_error::success;
 
   for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
-    bool ResultOverflowed;
-    Counts[I] = SaturatingAdd(Counts[I], Other.Counts[I], &ResultOverflowed);
-    if (ResultOverflowed)
+    bool Overflowed;
+    uint64_t OtherCount = Other.Counts[I];
+    if (Weight > 1) {
+      OtherCount = SaturatingMultiply(OtherCount, Weight, &Overflowed);
+      if (Overflowed)
+        Result = instrprof_error::counter_overflow;
+    }
+    Counts[I] = SaturatingAdd(Counts[I], OtherCount, &Overflowed);
+    if (Overflowed)
       Result = instrprof_error::counter_overflow;
   }
 
   for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
-    instrprof_error MergeValueResult = mergeValueProfData(Kind, Other);
+    instrprof_error MergeValueResult = mergeValueProfData(Kind, Other, Weight);
     if (MergeValueResult != instrprof_error::success)
       Result = MergeValueResult;
   }