GP-4582 Make sure newBlockMultiGoto preserves any self edge

This commit is contained in:
caheckman 2024-06-11 19:09:46 +00:00
parent e6112ce481
commit 464e33cf08
3 changed files with 38 additions and 16 deletions

View file

@ -84,12 +84,14 @@ void LoopBody::extendToContainer(const LoopBody &container,vector<FlowBlock *> &
}
}
/// This updates the \b head and \b tail nodes to FlowBlock in the current collapsed graph.
/// This returns the first \b tail and passes back the head.
/// \param top is where \b head is passed back
/// This updates the \b head node to the FlowBlock in the current collapsed graph.
/// The \b tail nodes are also updated until one is found that has not collapsed into \b head.
/// This first updated \b tail is returned. The loop may still exist as a \b head node with an
/// out edge back into itself, in which case \b head is returned as the active \b tail.
/// If the loop has been completely collapsed, null is returned.
/// \param graph is the containing control-flow structure
/// \return the current loop \b head
FlowBlock *LoopBody::getCurrentBounds(FlowBlock **top,FlowBlock *graph)
/// \return the current loop \b tail or null
FlowBlock *LoopBody::update(FlowBlock *graph)
{
while(head->getParent() != graph)
@ -101,10 +103,13 @@ FlowBlock *LoopBody::getCurrentBounds(FlowBlock **top,FlowBlock *graph)
bottom = bottom->getParent();
tails[i] = bottom;
if (bottom != head) { // If the loop hasn't been fully collapsed yet
*top = head;
return bottom;
}
}
for(int4 i=head->sizeOut()-1;i>=0;--i) {
if (head->getOut(i) == head) // Check for head looping with itself
return head;
}
return (FlowBlock *)0;
}
@ -391,17 +396,17 @@ void LoopBody::emitLikelyEdges(list<FloatingEdge> &likely,FlowBlock *graph)
break;
}
}
likely.push_back(FloatingEdge(inbl,outbl));
likely.emplace_back(inbl,outbl);
}
for(int4 i=tails.size()-1;i>=0;--i) { // Go in reverse order, to put out less preferred back-edges first
if ((holdin!=(FlowBlock *)0)&&(i==0))
likely.push_back(FloatingEdge(holdin,holdout)); // Put in delayed exit, right before final backedge
likely.emplace_back(holdin,holdout); // Put in delayed exit, right before final backedge
FlowBlock *tail = tails[i];
int4 sizeout = tail->sizeOut();
for(int4 j=0;j<sizeout;++j) {
FlowBlock *bl = tail->getOut(j);
if (bl == head) // If out edge to head (back-edge for this loop)
likely.push_back(FloatingEdge(tail,head)); // emit it
likely.emplace_back(tail,head); // emit it
}
}
}
@ -652,7 +657,7 @@ void TraceDAG::removeTrace(BlockTrace *trace)
{
// Record that we should now treat this edge like goto
likelygoto.push_back(FloatingEdge(trace->bottom,trace->destnode)); // Create goto record
likelygoto.emplace_back(trace->bottom,trace->destnode); // Create goto record
trace->destnode->setVisitCount( trace->destnode->getVisitCount() + trace->edgelump ); // Ignore edge(s)
BranchPoint *parentbp = trace->top;
@ -1194,11 +1199,21 @@ bool CollapseStructure::updateLoopBody(void)
FlowBlock *loopbottom = (FlowBlock *)0;
FlowBlock *looptop = (FlowBlock *)0;
while (loopbodyiter != loopbody.end()) { // Last innermost loop
loopbottom = (*loopbodyiter).getCurrentBounds(&looptop,&graph);
LoopBody &curBody( *loopbodyiter );
loopbottom = curBody.update(&graph);
if (loopbottom != (FlowBlock *)0) {
if ((!likelylistfull) ||
(likelyiter != likelygoto.end())) // Reaching here means, we removed edges but loop still didn't collapse
looptop = curBody.getHead();
if (loopbottom == looptop) { // Check for single node looping back to itself
// If sizeout is 1 or 2, the loop would have collapsed, so the node is likely a switch.
likelygoto.clear();
likelygoto.emplace_back(looptop,looptop); // Mark the loop edge as a goto
likelyiter = likelygoto.begin();
likelylistfull = true;
return true;
}
if (!likelylistfull || likelyiter != likelygoto.end()) {
break; // Loop still exists
}
}
++loopbodyiter;
likelylistfull = false; // Need to generate likely list for new loopbody (or no loopbody)