@@ -1479,23 +1479,13 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
14791479 // of length, and within each length, lexicographically by stack id. The
14801480 // latter is so that we can specially handle calls that have identical stack
14811481 // 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+ });
14991489
15001490 // Find the node for the last stack id, which should be the same
15011491 // across all calls recorded for this id, and is the id for this
@@ -1513,35 +1503,18 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
15131503 DenseSet<uint32_t > LastNodeContextIds = LastNode->getContextIds ();
15141504 assert (!LastNodeContextIds.empty ());
15151505
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;
15231512
15241513 for (unsigned I = 0 ; I < Calls.size (); I++) {
15251514 auto &[Call, Ids, Func, SavedContextIds] = Calls[I];
15261515 assert (SavedContextIds.empty ());
15271516 assert (LastId == Ids.back ());
15281517
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-
15451518 // First compute the context ids for this stack id sequence (the
15461519 // intersection of the context ids of the corresponding nodes).
15471520 // Start with the remaining saved ids for the last node.
@@ -1610,27 +1583,23 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
16101583 continue ;
16111584 }
16121585
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+
16131596 // Check if the next set of stack ids is the same (since the Calls vector
16141597 // 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.
16171598 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 ];
16201601 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;
16341603 }
16351604
16361605 // If we don't have duplicate context ids, then we can assign all the
@@ -1654,7 +1623,14 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
16541623 set_subtract (LastNodeContextIds, StackSequenceContextIds);
16551624 if (LastNodeContextIds.empty ())
16561625 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;
16581634 }
16591635 }
16601636
0 commit comments