@@ -1479,23 +1479,13 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
1479
1479
// of length, and within each length, lexicographically by stack id. The
1480
1480
// latter is so that we can specially handle calls that have identical stack
1481
1481
// id sequences (either due to cloning or artificially because of the MIB
1482
- // context pruning). Those with the same Ids are then sorted by function to
1483
- // facilitate efficiently mapping them to the same context node.
1484
- // Because the functions are pointers, to ensure a stable sort first assign
1485
- // each function pointer to its first index in the Calls array, and then use
1486
- // that to sort by.
1487
- DenseMap<const FuncTy *, unsigned > FuncToIndex;
1488
- for (const auto &[Idx, CallCtxInfo] : enumerate(Calls))
1489
- FuncToIndex.insert ({CallCtxInfo.Func , Idx});
1490
- std::stable_sort (
1491
- Calls.begin (), Calls.end (),
1492
- [&FuncToIndex](const CallContextInfo &A, const CallContextInfo &B) {
1493
- return A.StackIds .size () > B.StackIds .size () ||
1494
- (A.StackIds .size () == B.StackIds .size () &&
1495
- (A.StackIds < B.StackIds ||
1496
- (A.StackIds == B.StackIds &&
1497
- FuncToIndex[A.Func ] < FuncToIndex[B.Func ])));
1498
- });
1482
+ // context pruning).
1483
+ std::stable_sort (Calls.begin (), Calls.end (),
1484
+ [](const CallContextInfo &A, const CallContextInfo &B) {
1485
+ return A.StackIds .size () > B.StackIds .size () ||
1486
+ (A.StackIds .size () == B.StackIds .size () &&
1487
+ A.StackIds < B.StackIds );
1488
+ });
1499
1489
1500
1490
// Find the node for the last stack id, which should be the same
1501
1491
// across all calls recorded for this id, and is the id for this
@@ -1513,35 +1503,18 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
1513
1503
DenseSet<uint32_t > LastNodeContextIds = LastNode->getContextIds ();
1514
1504
assert (!LastNodeContextIds.empty ());
1515
1505
1516
- #ifndef NDEBUG
1517
- // Save the set of functions seen for a particular set of the same stack
1518
- // ids. This is used to ensure that they have been correctly sorted to be
1519
- // adjacent in the Calls list, since we rely on that to efficiently place
1520
- // all such matching calls onto the same context node.
1521
- DenseSet<const FuncTy *> MatchingIdsFuncSet;
1522
- #endif
1506
+ // Map from function to the first call from the below list (with matching
1507
+ // stack ids) found in that function. Note that calls from different
1508
+ // functions can have the same stack ids because this is the list of stack
1509
+ // ids that had (possibly pruned) nodes after building the graph from the
1510
+ // allocation MIBs.
1511
+ DenseMap<const FuncTy *, CallInfo> FuncToCallMap;
1523
1512
1524
1513
for (unsigned I = 0 ; I < Calls.size (); I++) {
1525
1514
auto &[Call, Ids, Func, SavedContextIds] = Calls[I];
1526
1515
assert (SavedContextIds.empty ());
1527
1516
assert (LastId == Ids.back ());
1528
1517
1529
- #ifndef NDEBUG
1530
- // If this call has a different set of ids than the last one, clear the
1531
- // set used to ensure they are sorted properly.
1532
- if (I > 0 && Ids != Calls[I - 1 ].StackIds )
1533
- MatchingIdsFuncSet.clear ();
1534
- else
1535
- // If the prior call had the same stack ids this set would not be empty.
1536
- // Check if we already have a call that "matches" because it is located
1537
- // in the same function. If the Calls list was sorted properly we should
1538
- // not encounter this situation as all such entries should be adjacent
1539
- // and processed in bulk further below.
1540
- assert (!MatchingIdsFuncSet.contains (Func));
1541
-
1542
- MatchingIdsFuncSet.insert (Func);
1543
- #endif
1544
-
1545
1518
// First compute the context ids for this stack id sequence (the
1546
1519
// intersection of the context ids of the corresponding nodes).
1547
1520
// Start with the remaining saved ids for the last node.
@@ -1610,27 +1583,23 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
1610
1583
continue ;
1611
1584
}
1612
1585
1586
+ // If the prior call had the same stack ids this map would not be empty.
1587
+ // Check if we already have a call that "matches" because it is located
1588
+ // in the same function.
1589
+ if (FuncToCallMap.contains (Func)) {
1590
+ // Record the matching call found for this call, and skip it. We
1591
+ // will subsequently combine it into the same node.
1592
+ CallToMatchingCall[Call] = FuncToCallMap[Func];
1593
+ continue ;
1594
+ }
1595
+
1613
1596
// Check if the next set of stack ids is the same (since the Calls vector
1614
1597
// of tuples is sorted by the stack ids we can just look at the next one).
1615
- // If so, save them in the CallToMatchingCall map so that they get
1616
- // assigned to the same context node, and skip them.
1617
1598
bool DuplicateContextIds = false ;
1618
- for ( unsigned J = I + 1 ; J < Calls.size (); J++ ) {
1619
- auto &CallCtxInfo = Calls[J ];
1599
+ if ( I + 1 < Calls.size ()) {
1600
+ auto &CallCtxInfo = Calls[I + 1 ];
1620
1601
auto &NextIds = CallCtxInfo.StackIds ;
1621
- if (NextIds != Ids)
1622
- break ;
1623
- auto *NextFunc = CallCtxInfo.Func ;
1624
- if (NextFunc != Func) {
1625
- // We have another Call with the same ids but that cannot share this
1626
- // node, must duplicate ids for it.
1627
- DuplicateContextIds = true ;
1628
- break ;
1629
- }
1630
- auto &NextCall = CallCtxInfo.Call ;
1631
- CallToMatchingCall[NextCall] = Call;
1632
- // Update I so that it gets incremented correctly to skip this call.
1633
- I = J;
1602
+ DuplicateContextIds = Ids == NextIds;
1634
1603
}
1635
1604
1636
1605
// If we don't have duplicate context ids, then we can assign all the
@@ -1654,7 +1623,14 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
1654
1623
set_subtract (LastNodeContextIds, StackSequenceContextIds);
1655
1624
if (LastNodeContextIds.empty ())
1656
1625
break ;
1657
- }
1626
+ // No longer possibly in a sequence of calls with duplicate stack ids,
1627
+ // clear the map.
1628
+ FuncToCallMap.clear ();
1629
+ } else
1630
+ // Record the call with its function, so we can locate it the next time
1631
+ // we find a call from this function when processing the calls with the
1632
+ // same stack ids.
1633
+ FuncToCallMap[Func] = Call;
1658
1634
}
1659
1635
}
1660
1636
0 commit comments