2222#include " llvm/Support/Signals.h"
2323#include " llvm/Support/ThreadPool.h"
2424#include < algorithm>
25+ #include < fstream>
2526#include < mutex>
2627#include < unordered_map>
2728
@@ -267,69 +268,68 @@ void mergeLegacyProfiles(const SmallVectorImpl<std::string> &Filenames) {
267268 std::optional<bool > BoltedCollection;
268269 std::optional<bool > NoLBRCollection;
269270 std::mutex BoltedCollectionMutex;
270- typedef StringMap<uint64_t > ProfileTy;
271+ struct CounterTy {
272+ uint64_t Exec{0 };
273+ uint64_t Mispred{0 };
274+ CounterTy &operator +=(const CounterTy &O) {
275+ Exec += O.Exec ;
276+ Mispred += O.Mispred ;
277+ return *this ;
278+ }
279+ CounterTy operator +(const CounterTy &O) { return *this += O; }
280+ };
281+ typedef StringMap<CounterTy> ProfileTy;
271282
272283 auto ParseProfile = [&](const std::string &Filename, auto &Profiles) {
273284 const llvm::thread::id tid = llvm::this_thread::get_id ();
274285
275286 if (isYAML (Filename))
276287 report_error (Filename, " cannot mix YAML and legacy formats" );
277- ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
278- MemoryBuffer::getFileOrSTDIN (Filename);
279- if (std::error_code EC = MB.getError ())
280- report_error (Filename, EC);
281288
282- StringRef Buf = MB.get ()->getBuffer ();
289+ std::ifstream FdataFile (Filename, std::ios::in);
290+ std::string FdataLine;
291+ std::getline (FdataFile, FdataLine);
292+
293+ auto checkMode = [&](const std::string &Key, std::optional<bool > &Flag) {
294+ const bool KeyIsSet = FdataLine.rfind (Key, 0 ) == 0 ;
295+
296+ if (!Flag.has_value ())
297+ Flag = KeyIsSet;
298+ else if (*Flag != KeyIsSet)
299+ report_error (Filename, " cannot mix profile with and without " + Key);
300+ if (KeyIsSet)
301+ // Advance line
302+ std::getline (FdataFile, FdataLine);
303+ };
304+
283305 ProfileTy *Profile;
284306 {
285307 std::lock_guard<std::mutex> Lock (BoltedCollectionMutex);
286308 // Check if the string "boltedcollection" is in the first line
287- if (Buf.starts_with (" boltedcollection\n " )) {
288- if (!BoltedCollection.value_or (true ))
289- report_error (
290- Filename,
291- " cannot mix profile collected in BOLT and non-BOLT deployments" );
292- BoltedCollection = true ;
293- Buf = Buf.drop_front (17 );
294- } else {
295- if (BoltedCollection.value_or (false ))
296- report_error (
297- Filename,
298- " cannot mix profile collected in BOLT and non-BOLT deployments" );
299- BoltedCollection = false ;
300- }
309+ checkMode (" boltedcollection" , BoltedCollection);
301310 // Check if the string "no_lbr" is in the first line
302311 // (or second line if BoltedCollection is true)
303- size_t CheckNoLBRPos = Buf.find (' \n ' );
304- if (CheckNoLBRPos != StringRef::npos) {
305- StringRef FirstLine = Buf.substr (0 , CheckNoLBRPos);
306- if (FirstLine.contains (" no_lbr" )) {
307- if (!NoLBRCollection.value_or (true ))
308- report_error (Filename, " cannot mix 'no_lbr' and 'lbr' profiles" );
309- NoLBRCollection = true ;
310- Buf = Buf.drop_front (CheckNoLBRPos + 1 );
311- } else {
312- if (NoLBRCollection.value_or (false ))
313- report_error (Filename, " cannot mix 'no_lbr' and 'lbr' profiles" );
314- NoLBRCollection = false ;
315- }
316- }
312+ checkMode (" no_lbr" , NoLBRCollection);
317313 Profile = &Profiles[tid];
318314 }
319315
320- SmallVector<StringRef> Lines;
321- SplitString (Buf, Lines, " \n " );
322- for (StringRef Line : Lines) {
323- size_t Pos = Line.rfind (" " );
324- if (Pos == StringRef::npos)
325- report_error (Filename, " Malformed / corrupted profile" );
326- StringRef Signature = Line.substr (0 , Pos);
327- uint64_t Count;
328- if (Line.substr (Pos + 1 , Line.size () - Pos).getAsInteger (10 , Count))
329- report_error (Filename, " Malformed / corrupted profile counter" );
316+ do {
317+ StringRef Line (FdataLine);
318+ CounterTy Count;
319+ auto [Signature, ExecCount] = Line.rsplit (' ' );
320+ if (ExecCount.getAsInteger (10 , Count.Exec ))
321+ report_error (Filename, " Malformed / corrupted execution count" );
322+ // Only LBR profile has misprediction field
323+ if (!NoLBRCollection.value_or (false )) {
324+ auto [SignatureLBR, MispredCount] = Signature.rsplit (' ' );
325+ Signature = SignatureLBR;
326+ if (MispredCount.getAsInteger (10 , Count.Mispred ))
327+ report_error (Filename, " Malformed / corrupted misprediction count" );
328+ }
329+
330330 Count += Profile->lookup (Signature);
331331 Profile->insert_or_assign (Signature, Count);
332- }
332+ } while ( std::getline (FdataFile, FdataLine));
333333 };
334334
335335 // The final reduction has non-trivial cost, make sure each thread has at
@@ -346,16 +346,20 @@ void mergeLegacyProfiles(const SmallVectorImpl<std::string> &Filenames) {
346346 ProfileTy MergedProfile;
347347 for (const auto &[Thread, Profile] : ParsedProfiles)
348348 for (const auto &[Key, Value] : Profile) {
349- uint64_t Count = MergedProfile.lookup (Key) + Value;
349+ CounterTy Count = MergedProfile.lookup (Key) + Value;
350350 MergedProfile.insert_or_assign (Key, Count);
351351 }
352352
353353 if (BoltedCollection.value_or (false ))
354354 output () << " boltedcollection\n " ;
355355 if (NoLBRCollection.value_or (false ))
356356 output () << " no_lbr\n " ;
357- for (const auto &[Key, Value] : MergedProfile)
358- output () << Key << " " << Value << " \n " ;
357+ for (const auto &[Key, Value] : MergedProfile) {
358+ output () << Key << " " ;
359+ if (!NoLBRCollection.value_or (false ))
360+ output () << Value.Mispred << " " ;
361+ output () << Value.Exec << " \n " ;
362+ }
359363
360364 errs () << " Profile from " << Filenames.size () << " files merged.\n " ;
361365}
0 commit comments