@@ -711,7 +711,7 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,
711
711
}
712
712
713
713
bool DataAggregator::doBranch (uint64_t From, uint64_t To, uint64_t Count,
714
- uint64_t Mispreds, bool IsPreagg ) {
714
+ uint64_t Mispreds) {
715
715
// Returns whether \p Offset in \p Func contains a return instruction.
716
716
auto checkReturn = [&](const BinaryFunction &Func, const uint64_t Offset) {
717
717
auto isReturn = [&](auto MI) { return MI && BC->MIB ->isReturn (*MI); };
@@ -772,7 +772,8 @@ bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
772
772
return false ;
773
773
774
774
// Record call to continuation trace.
775
- if (IsPreagg && FromFunc != ToFunc && (IsReturn || IsCallCont)) {
775
+ if (NeedsConvertRetProfileToCallCont && FromFunc != ToFunc &&
776
+ (IsReturn || IsCallCont)) {
776
777
LBREntry First{ToOrig - 1 , ToOrig - 1 , false };
777
778
LBREntry Second{ToOrig, ToOrig, false };
778
779
return doTrace (First, Second, Count);
@@ -1216,23 +1217,30 @@ ErrorOr<Location> DataAggregator::parseLocationOrOffset() {
1216
1217
return Location (true , BuildID.get (), Offset.get ());
1217
1218
}
1218
1219
1219
- ErrorOr<DataAggregator::AggregatedLBREntry>
1220
- DataAggregator::parseAggregatedLBREntry () {
1220
+ std::error_code DataAggregator::parseAggregatedLBREntry () {
1221
1221
while (checkAndConsumeFS ()) {
1222
1222
}
1223
1223
1224
1224
ErrorOr<StringRef> TypeOrErr = parseString (FieldSeparator);
1225
1225
if (std::error_code EC = TypeOrErr.getError ())
1226
1226
return EC;
1227
+ // Pre-aggregated profile with branches and fallthroughs needs to convert
1228
+ // return profile into call to continuation fall-through.
1227
1229
auto Type = AggregatedLBREntry::BRANCH;
1228
1230
if (TypeOrErr.get () == " B" ) {
1231
+ NeedsConvertRetProfileToCallCont = true ;
1229
1232
Type = AggregatedLBREntry::BRANCH;
1230
1233
} else if (TypeOrErr.get () == " F" ) {
1234
+ NeedsConvertRetProfileToCallCont = true ;
1231
1235
Type = AggregatedLBREntry::FT;
1232
1236
} else if (TypeOrErr.get () == " f" ) {
1237
+ NeedsConvertRetProfileToCallCont = true ;
1233
1238
Type = AggregatedLBREntry::FT_EXTERNAL_ORIGIN;
1239
+ } else if (TypeOrErr.get () == " T" ) {
1240
+ // Trace is expanded into B and [Ff]
1241
+ Type = AggregatedLBREntry::TRACE;
1234
1242
} else {
1235
- reportError (" expected B, F or f" );
1243
+ reportError (" expected T, B, F or f" );
1236
1244
return make_error_code (llvm::errc::io_error);
1237
1245
}
1238
1246
@@ -1248,6 +1256,15 @@ DataAggregator::parseAggregatedLBREntry() {
1248
1256
if (std::error_code EC = To.getError ())
1249
1257
return EC;
1250
1258
1259
+ ErrorOr<Location> TraceFtEnd = std::error_code ();
1260
+ if (Type == AggregatedLBREntry::TRACE) {
1261
+ while (checkAndConsumeFS ()) {
1262
+ }
1263
+ TraceFtEnd = parseLocationOrOffset ();
1264
+ if (std::error_code EC = TraceFtEnd.getError ())
1265
+ return EC;
1266
+ }
1267
+
1251
1268
while (checkAndConsumeFS ()) {
1252
1269
}
1253
1270
ErrorOr<int64_t > Frequency =
@@ -1270,9 +1287,24 @@ DataAggregator::parseAggregatedLBREntry() {
1270
1287
return make_error_code (llvm::errc::io_error);
1271
1288
}
1272
1289
1273
- return AggregatedLBREntry{From.get (), To.get (),
1274
- static_cast <uint64_t >(Frequency.get ()), Mispreds,
1275
- Type};
1290
+ BinaryFunction *FromFunc = getBinaryFunctionContainingAddress (From->Offset );
1291
+ BinaryFunction *ToFunc = getBinaryFunctionContainingAddress (To->Offset );
1292
+
1293
+ for (BinaryFunction *BF : {FromFunc, ToFunc})
1294
+ if (BF)
1295
+ BF->setHasProfileAvailable ();
1296
+
1297
+ uint64_t Count = static_cast <uint64_t >(Frequency.get ());
1298
+ AggregatedLBREntry Entry{From.get (), To.get (), Count, Mispreds, Type};
1299
+ AggregatedLBRs.emplace_back (Entry);
1300
+ if (Type == AggregatedLBREntry::TRACE) {
1301
+ auto FtType = (FromFunc == ToFunc) ? AggregatedLBREntry::FT
1302
+ : AggregatedLBREntry::FT_EXTERNAL_ORIGIN;
1303
+ AggregatedLBREntry TraceFt{To.get (), TraceFtEnd.get (), Count, 0 , FtType};
1304
+ AggregatedLBRs.emplace_back (TraceFt);
1305
+ }
1306
+
1307
+ return std::error_code ();
1276
1308
}
1277
1309
1278
1310
bool DataAggregator::ignoreKernelInterrupt (LBREntry &LBR) const {
@@ -1585,8 +1617,7 @@ void DataAggregator::processBranchEvents() {
1585
1617
for (const auto &AggrLBR : BranchLBRs) {
1586
1618
const Trace &Loc = AggrLBR.first ;
1587
1619
const TakenBranchInfo &Info = AggrLBR.second ;
1588
- doBranch (Loc.From , Loc.To , Info.TakenCount , Info.MispredCount ,
1589
- /* IsPreagg*/ false );
1620
+ doBranch (Loc.From , Loc.To , Info.TakenCount , Info.MispredCount );
1590
1621
}
1591
1622
}
1592
1623
@@ -1722,18 +1753,10 @@ std::error_code DataAggregator::parsePreAggregatedLBRSamples() {
1722
1753
outs () << " PERF2BOLT: parsing pre-aggregated profile...\n " ;
1723
1754
NamedRegionTimer T (" parseAggregated" , " Parsing aggregated branch events" ,
1724
1755
TimerGroupName, TimerGroupDesc, opts::TimeAggregator);
1725
- while (hasData ()) {
1726
- ErrorOr<AggregatedLBREntry> AggrEntry = parseAggregatedLBREntry ();
1727
- if (std::error_code EC = AggrEntry.getError ())
1756
+ while (hasData ())
1757
+ if (std::error_code EC = parseAggregatedLBREntry ())
1728
1758
return EC;
1729
1759
1730
- for (const uint64_t Addr : {AggrEntry->From .Offset , AggrEntry->To .Offset })
1731
- if (BinaryFunction *BF = getBinaryFunctionContainingAddress (Addr))
1732
- BF->setHasProfileAvailable ();
1733
-
1734
- AggregatedLBRs.emplace_back (std::move (AggrEntry.get ()));
1735
- }
1736
-
1737
1760
return std::error_code ();
1738
1761
}
1739
1762
@@ -1746,8 +1769,9 @@ void DataAggregator::processPreAggregated() {
1746
1769
for (const AggregatedLBREntry &AggrEntry : AggregatedLBRs) {
1747
1770
switch (AggrEntry.EntryType ) {
1748
1771
case AggregatedLBREntry::BRANCH:
1772
+ case AggregatedLBREntry::TRACE:
1749
1773
doBranch (AggrEntry.From .Offset , AggrEntry.To .Offset , AggrEntry.Count ,
1750
- AggrEntry.Mispreds , /* IsPreagg */ true );
1774
+ AggrEntry.Mispreds );
1751
1775
break ;
1752
1776
case AggregatedLBREntry::FT:
1753
1777
case AggregatedLBREntry::FT_EXTERNAL_ORIGIN: {
0 commit comments