@@ -692,32 +692,28 @@ class CallsiteContextGraph {
692692
693693 // / Create a clone of Edge's callee and move Edge to that new callee node,
694694 // / performing the necessary context id and allocation type updates.
695- // / If callee's caller edge iterator is supplied, it is updated when removing
696- // / the edge from that list. If ContextIdsToMove is non-empty, only that
697- // / subset of Edge's ids are moved to an edge to the new callee.
695+ // / If ContextIdsToMove is non-empty, only that subset of Edge's ids are
696+ // / moved to an edge to the new callee.
698697 ContextNode *
699698 moveEdgeToNewCalleeClone (const std::shared_ptr<ContextEdge> &Edge,
700- EdgeIter *CallerEdgeI = nullptr ,
701699 DenseSet<uint32_t > ContextIdsToMove = {});
702700
703701 // / Change the callee of Edge to existing callee clone NewCallee, performing
704702 // / the necessary context id and allocation type updates.
705- // / If callee's caller edge iterator is supplied, it is updated when removing
706- // / the edge from that list. If ContextIdsToMove is non-empty, only that
707- // / subset of Edge's ids are moved to an edge to the new callee.
703+ // / If ContextIdsToMove is non-empty, only that subset of Edge's ids are
704+ // / moved to an edge to the new callee.
708705 void moveEdgeToExistingCalleeClone (const std::shared_ptr<ContextEdge> &Edge,
709706 ContextNode *NewCallee,
710- EdgeIter *CallerEdgeI = nullptr ,
711707 bool NewClone = false ,
712708 DenseSet<uint32_t > ContextIdsToMove = {});
713709
714710 // / Change the caller of the edge at the given callee edge iterator to be
715711 // / NewCaller, performing the necessary context id and allocation type
716- // / updates. The iterator is updated as the edge is removed from the list of
717- // / callee edges in the original caller. This is similar to the above
718- // / moveEdgeToExistingCalleeClone, but a simplified version of it as we always
719- // / move the given edge and all of its context ids.
720- void moveCalleeEdgeToNewCaller (EdgeIter &CalleeEdgeI, ContextNode *NewCaller);
712+ // / updates. This is similar to the above moveEdgeToExistingCalleeClone, but
713+ // / a simplified version of it as we always move the given edge and all of its
714+ // / context ids.
715+ void moveCalleeEdgeToNewCaller ( const std::shared_ptr<ContextEdge> &Edge,
716+ ContextNode *NewCaller);
721717
722718 // / Recursively perform cloning on the graph for the given Node and its
723719 // / callers, in order to uniquely identify the allocation behavior of an
@@ -2313,12 +2309,13 @@ bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::partitionCallsByCallee(
23132309 // Track whether we already assigned original node to a callee.
23142310 bool UsedOrigNode = false ;
23152311 assert (NodeToCallingFunc[Node]);
2316- for (auto EI = Node->CalleeEdges .begin (); EI != Node->CalleeEdges .end ();) {
2317- auto Edge = *EI;
2318- if (!Edge->Callee ->hasCall ()) {
2319- ++EI;
2312+ // Iterate over a copy of Node's callee edges, since we may need to remove
2313+ // edges in moveCalleeEdgeToNewCaller, and this simplifies the handling and
2314+ // makes it less error-prone.
2315+ auto CalleeEdges = Node->CalleeEdges ;
2316+ for (auto &Edge : CalleeEdges) {
2317+ if (!Edge->Callee ->hasCall ())
23202318 continue ;
2321- }
23222319
23232320 // Will be updated below to point to whatever (caller) node this callee edge
23242321 // should be moved to.
@@ -2361,12 +2358,10 @@ bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::partitionCallsByCallee(
23612358 }
23622359
23632360 // Don't need to move edge if we are using the original node;
2364- if (CallerNodeToUse == Node) {
2365- ++EI;
2361+ if (CallerNodeToUse == Node)
23662362 continue ;
2367- }
23682363
2369- moveCalleeEdgeToNewCaller (EI , CallerNodeToUse);
2364+ moveCalleeEdgeToNewCaller (Edge , CallerNodeToUse);
23702365 }
23712366 // Now that we are done moving edges, clean up any caller edges that ended
23722367 // up with no type or context ids. During moveCalleeEdgeToNewCaller all
@@ -3046,24 +3041,23 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::exportToDot(
30463041template <typename DerivedCCG, typename FuncTy, typename CallTy>
30473042typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode *
30483043CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::moveEdgeToNewCalleeClone(
3049- const std::shared_ptr<ContextEdge> &Edge, EdgeIter *CallerEdgeI,
3044+ const std::shared_ptr<ContextEdge> &Edge,
30503045 DenseSet<uint32_t > ContextIdsToMove) {
30513046 ContextNode *Node = Edge->Callee ;
30523047 assert (NodeToCallingFunc.count (Node));
30533048 ContextNode *Clone =
30543049 createNewNode (Node->IsAllocation , NodeToCallingFunc[Node], Node->Call );
30553050 Node->addClone (Clone);
30563051 Clone->MatchingCalls = Node->MatchingCalls ;
3057- moveEdgeToExistingCalleeClone (Edge, Clone, CallerEdgeI, /* NewClone=*/ true ,
3052+ moveEdgeToExistingCalleeClone (Edge, Clone, /* NewClone=*/ true ,
30583053 ContextIdsToMove);
30593054 return Clone;
30603055}
30613056
30623057template <typename DerivedCCG, typename FuncTy, typename CallTy>
30633058void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
30643059 moveEdgeToExistingCalleeClone (const std::shared_ptr<ContextEdge> &Edge,
3065- ContextNode *NewCallee, EdgeIter *CallerEdgeI,
3066- bool NewClone,
3060+ ContextNode *NewCallee, bool NewClone,
30673061 DenseSet<uint32_t > ContextIdsToMove) {
30683062 // NewCallee and Edge's current callee must be clones of the same original
30693063 // node (Edge's current callee may be the original node too).
@@ -3094,23 +3088,18 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
30943088 ContextIdsToMove.end ());
30953089 ExistingEdgeToNewCallee->AllocTypes |= Edge->AllocTypes ;
30963090 assert (Edge->ContextIds == ContextIdsToMove);
3097- removeEdgeFromGraph (Edge.get (), CallerEdgeI, /* CalleeIter= */ false );
3091+ removeEdgeFromGraph (Edge.get ());
30983092 } else {
30993093 // Otherwise just reconnect Edge to NewCallee.
31003094 Edge->Callee = NewCallee;
31013095 NewCallee->CallerEdges .push_back (Edge);
31023096 // Remove it from callee where it was previously connected.
3103- if (CallerEdgeI)
3104- *CallerEdgeI = OldCallee->CallerEdges .erase (*CallerEdgeI);
3105- else
3106- OldCallee->eraseCallerEdge (Edge.get ());
3097+ OldCallee->eraseCallerEdge (Edge.get ());
31073098 // Don't need to update Edge's context ids since we are simply
31083099 // reconnecting it.
31093100 }
31103101 } else {
31113102 // Only moving a subset of Edge's ids.
3112- if (CallerEdgeI)
3113- ++(*CallerEdgeI);
31143103 // Compute the alloc type of the subset of ids being moved.
31153104 auto CallerEdgeAllocType = computeAllocType (ContextIdsToMove);
31163105 if (ExistingEdgeToNewCallee) {
@@ -3183,16 +3172,16 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
31833172
31843173template <typename DerivedCCG, typename FuncTy, typename CallTy>
31853174void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
3186- moveCalleeEdgeToNewCaller (EdgeIter &CalleeEdgeI, ContextNode *NewCaller) {
3187- auto Edge = *CalleeEdgeI;
3175+ moveCalleeEdgeToNewCaller (const std::shared_ptr<ContextEdge> &Edge,
3176+ ContextNode *NewCaller) {
31883177
31893178 ContextNode *OldCaller = Edge->Caller ;
3179+ OldCaller->eraseCalleeEdge (Edge.get ());
31903180
31913181 // We might already have an edge to the new caller. If one exists we will
31923182 // reuse it.
31933183 auto ExistingEdgeToNewCaller = NewCaller->findEdgeFromCallee (Edge->Callee );
31943184
3195- CalleeEdgeI = OldCaller->CalleeEdges .erase (CalleeEdgeI);
31963185 if (ExistingEdgeToNewCaller) {
31973186 // Since we already have an edge to NewCaller, simply move the ids
31983187 // onto it, and remove the existing Edge.
@@ -3417,22 +3406,20 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones(
34173406 // Iterate until we find no more opportunities for disambiguating the alloc
34183407 // types via cloning. In most cases this loop will terminate once the Node
34193408 // has a single allocation type, in which case no more cloning is needed.
3420- // We need to be able to remove Edge from CallerEdges, so need to adjust
3421- // iterator inside the loop.
3422- for ( auto EI = Node-> CallerEdges . begin (); EI != Node-> CallerEdges . end ();) {
3423- auto CallerEdge = *EI ;
3424-
3409+ // Iterate over a copy of Node's caller edges, since we may need to remove
3410+ // edges in the moveEdgeTo* methods, and this simplifies the handling and
3411+ // makes it less error-prone.
3412+ auto CallerEdges = Node-> CallerEdges ;
3413+ for ( auto &CallerEdge : CallerEdges) {
34253414 // See if cloning the prior caller edge left this node with a single alloc
34263415 // type or a single caller. In that case no more cloning of Node is needed.
34273416 if (hasSingleAllocType (Node->AllocTypes ) || Node->CallerEdges .size () <= 1 )
34283417 break ;
34293418
34303419 // If the caller was not successfully matched to a call in the IR/summary,
34313420 // there is no point in trying to clone for it as we can't update that call.
3432- if (!CallerEdge->Caller ->hasCall ()) {
3433- ++EI;
3421+ if (!CallerEdge->Caller ->hasCall ())
34343422 continue ;
3435- }
34363423
34373424 // Only need to process the ids along this edge pertaining to the given
34383425 // allocation.
@@ -3441,10 +3428,9 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones(
34413428 if (!RecursiveContextIds.empty ())
34423429 CallerEdgeContextsForAlloc =
34433430 set_difference (CallerEdgeContextsForAlloc, RecursiveContextIds);
3444- if (CallerEdgeContextsForAlloc.empty ()) {
3445- ++EI;
3431+ if (CallerEdgeContextsForAlloc.empty ())
34463432 continue ;
3447- }
3433+
34483434 auto CallerAllocTypeForAlloc = computeAllocType (CallerEdgeContextsForAlloc);
34493435
34503436 // Compute the node callee edge alloc types corresponding to the context ids
@@ -3471,10 +3457,8 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones(
34713457 if (allocTypeToUse (CallerAllocTypeForAlloc) ==
34723458 allocTypeToUse (Node->AllocTypes ) &&
34733459 allocTypesMatch<DerivedCCG, FuncTy, CallTy>(
3474- CalleeEdgeAllocTypesForCallerEdge, Node->CalleeEdges )) {
3475- ++EI;
3460+ CalleeEdgeAllocTypesForCallerEdge, Node->CalleeEdges ))
34763461 continue ;
3477- }
34783462
34793463 // First see if we can use an existing clone. Check each clone and its
34803464 // callee edges for matching alloc types.
@@ -3504,14 +3488,11 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones(
35043488
35053489 // The edge iterator is adjusted when we move the CallerEdge to the clone.
35063490 if (Clone)
3507- moveEdgeToExistingCalleeClone (CallerEdge, Clone, &EI, /* NewClone=*/ false ,
3491+ moveEdgeToExistingCalleeClone (CallerEdge, Clone, /* NewClone=*/ false ,
35083492 CallerEdgeContextsForAlloc);
35093493 else
3510- Clone =
3511- moveEdgeToNewCalleeClone (CallerEdge, &EI, CallerEdgeContextsForAlloc);
3494+ Clone = moveEdgeToNewCalleeClone (CallerEdge, CallerEdgeContextsForAlloc);
35123495
3513- assert (EI == Node->CallerEdges .end () ||
3514- Node->AllocTypes != (uint8_t )AllocationType::None);
35153496 // Sanity check that no alloc types on clone or its edges are None.
35163497 assert (Clone->AllocTypes != (uint8_t )AllocationType::None);
35173498 }
@@ -3952,16 +3933,14 @@ bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::assignFunctions() {
39523933 // assign this clone to.
39533934 std::map<FuncInfo, ContextNode *> FuncCloneToNewCallsiteCloneMap;
39543935 FuncInfo FuncCloneAssignedToCurCallsiteClone;
3955- // We need to be able to remove Edge from CallerEdges, so need to adjust
3956- // iterator in the loop.
3957- for ( auto EI = Clone-> CallerEdges . begin ();
3958- EI ! = Clone->CallerEdges . end ();) {
3959- auto Edge = *EI;
3936+ // Iterate over a copy of Clone's caller edges, since we may need to
3937+ // remove edges in the moveEdgeTo* methods, and this simplifies the
3938+ // handling and makes it less error-prone.
3939+ auto CloneCallerEdges = Clone->CallerEdges ;
3940+ for ( auto & Edge : CloneCallerEdges) {
39603941 // Ignore any caller that does not have a recorded callsite Call.
3961- if (!Edge->Caller ->hasCall ()) {
3962- EI++;
3942+ if (!Edge->Caller ->hasCall ())
39633943 continue ;
3964- }
39653944 // If this caller already assigned to call a version of OrigFunc, need
39663945 // to ensure we can assign this callsite clone to that function clone.
39673946 if (CallsiteToCalleeFuncCloneMap.count (Edge->Caller )) {
@@ -4006,27 +3985,24 @@ bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::assignFunctions() {
40063985 FuncCloneCalledByCaller)) {
40073986 ContextNode *NewClone =
40083987 FuncCloneToNewCallsiteCloneMap[FuncCloneCalledByCaller];
4009- moveEdgeToExistingCalleeClone (Edge, NewClone, &EI );
3988+ moveEdgeToExistingCalleeClone (Edge, NewClone);
40103989 // Cleanup any none type edges cloned over.
40113990 removeNoneTypeCalleeEdges (NewClone);
40123991 } else {
40133992 // Create a new callsite clone.
4014- ContextNode *NewClone = moveEdgeToNewCalleeClone (Edge, &EI );
3993+ ContextNode *NewClone = moveEdgeToNewCalleeClone (Edge);
40153994 removeNoneTypeCalleeEdges (NewClone);
40163995 FuncCloneToNewCallsiteCloneMap[FuncCloneCalledByCaller] =
40173996 NewClone;
40183997 // Add to list of clones and process later.
40193998 ClonesWorklist.push_back (NewClone);
4020- assert (EI == Clone->CallerEdges .end () ||
4021- Clone->AllocTypes != (uint8_t )AllocationType::None);
40223999 assert (NewClone->AllocTypes != (uint8_t )AllocationType::None);
40234000 }
40244001 // Moving the caller edge may have resulted in some none type
40254002 // callee edges.
40264003 removeNoneTypeCalleeEdges (Clone);
40274004 // We will handle the newly created callsite clone in a subsequent
4028- // iteration over this Node's Clones. Continue here since we
4029- // already adjusted iterator EI while moving the edge.
4005+ // iteration over this Node's Clones.
40304006 continue ;
40314007 }
40324008
@@ -4074,8 +4050,6 @@ bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::assignFunctions() {
40744050 RecordCalleeFuncOfCallsite (Edge->Caller ,
40754051 FuncCloneAssignedToCurCallsiteClone);
40764052 }
4077-
4078- EI++;
40794053 }
40804054 }
40814055 if (VerifyCCG) {
0 commit comments