void processBlock(AstNode* nodep) { if (!nodep) return; // Empty lists are ignorable // Pass the first node in a list of block items, we'll process them // Check there's >= 2 sub statements, else nothing to analyze // Save recursion state AstNode* firstp = nodep; // We may reorder, and nodep is no longer first. void* oldBlockUser3 = nodep->user3p(); // May be overloaded in below loop, save it nodep->user3p(NULL); if (!nodep->firstAbovep()) nodep->v3fatalSrc("Node passed is in next list; should have processed all list at once"); // Process it if (!nodep->nextp()) { // Just one, so can't reorder. Just look for more blocks/statements. iterate(nodep); } else { UINFO(9," processBlock "<<nodep<<endl); // Process block and followers scanBlock(nodep); if (m_noReorderWhy != "") { // Jump or something nasty UINFO(9," NoReorderBlock because "<<m_noReorderWhy<<endl); } else { // Reorder statements in this block cleanupBlockGraph(nodep); reorderBlock(nodep); // Delete old vertexes and edges only applying to this block while (firstp->backp()->nextp()==firstp) firstp = firstp->backp(); // Walk back to first in list for (AstNode* nextp=firstp; nextp; nextp=nextp->nextp()) { SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p(); vvertexp->unlinkDelete(&m_graph); } } } // Again, nodep may no longer be first. firstp->user3p(oldBlockUser3); }
virtual void visit(AstNode* nodep) { if (nodep->user3p()) { SplitLogicVertex* vertexp = (SplitLogicVertex*)(nodep->user3p()); uint32_t color = vertexp->color(); m_colors.insert(color); UINFO(8, " SVL " << vertexp << " has color " << color << "\n"); // Record that all containing ifs have this color. for (IfStack::const_iterator it = m_ifStack.begin(); it != m_ifStack.end(); ++it) { m_ifColors[*it].insert(color); } } iterateChildren(nodep); }
virtual void visit(AstNode* nodep) { // Anything that's not an if/else we assume is a leaf // (that is, something we won't split.) Don't visit further // into the leaf. // // A leaf might contain another if, for example a WHILE loop // could contain an if. We can't split WHILE loops, so we // won't split its nested if either. Just treat it as part // of the leaf; do not visit further; do not reach visit(AstNodeIf*) // for such an embedded if. // Each leaf must have a user3p if (!nodep->user3p()) nodep->v3fatalSrc("null user3p in V3Split leaf"); // Clone the leaf into its new always block SplitLogicVertex* vxp = (SplitLogicVertex*)(nodep->user3p()); uint32_t color = vxp->color(); AstNode* clonedp = nodep->cloneTree(false); m_addAfter[color]->addNextHere(clonedp); m_addAfter[color] = clonedp; }
void reorderBlock(AstNode* nodep) { // Reorder statements in the completed graph // Map the rank numbers into nodes they associate with typedef std::multimap<uint32_t,AstNode*> RankNodeMap; RankNodeMap rankMap; int currOrder = 0; // Existing sequence number of assignment for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) { SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p(); rankMap.insert(make_pair(vvertexp->rank(), nextp)); nextp->user4(++currOrder); // Record current ordering } // Is the current ordering OK? bool leaveAlone=true; int newOrder = 0; // New sequence number of assignment for (RankNodeMap::const_iterator it = rankMap.begin(); it != rankMap.end(); ++it) { AstNode* nextp = it->second; if (++newOrder != nextp->user4()) leaveAlone=false; } if (leaveAlone) { UINFO(6," No changes\n"); } else { AstNRelinker replaceHandle; // Where to add the list AstNode* newListp = NULL; for (RankNodeMap::const_iterator it = rankMap.begin(); it != rankMap.end(); ++it) { AstNode* nextp = it->second; UINFO(6, " New order: "<<nextp<<endl); if (nextp == nodep) nodep->unlinkFrBack(&replaceHandle); else nextp->unlinkFrBack(); if (newListp) newListp = newListp->addNext(nextp); else newListp = nextp; } replaceHandle.relink(newListp); } // leaveAlone }
void colorAlwaysGraph() { // Color the graph to indicate subsets, each of which // we can split into its own always block. m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // Some vars are primary inputs to the always block; prune // edges on those vars. Reasoning: if two statements both depend // on primary input A, it's ok to split these statements. Whereas // if they both depend on locally-generated variable B, the statements // must be kept together. SplitEdge::incrementStep(); pruneDepsOnInputs(); // For any 'if' node whose deps have all been pruned // (meaning, its conditional expression only looks at primary // inputs) prune all edges that depend on the 'if'. for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { SplitLogicVertex* logicp = dynamic_cast<SplitLogicVertex*>(vertexp); if (!logicp) continue; AstNodeIf* ifNodep = VN_CAST(logicp->nodep(), NodeIf); if (!ifNodep) continue; bool pruneMe = true; for (V3GraphEdge* edgep = logicp->outBeginp(); edgep; edgep = edgep->outNextp()) { SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep); if (!oedgep->ignoreThisStep()) { // This if conditional depends on something we can't // prune -- a variable generated in the current block. pruneMe = false; // When we can't prune dependencies on the conditional, // give a hint about why... if (debug() >= 9) { V3GraphVertex* vxp = oedgep->top(); SplitNodeVertex* nvxp = dynamic_cast<SplitNodeVertex*>(vxp); UINFO(0, "Cannot prune if-node due to edge "<<oedgep<< " pointing to node "<<nvxp->nodep()<<endl); nvxp->nodep()->dumpTree(cout, "- "); } break; } } if (!pruneMe) continue; // This if can be split; prune dependencies on it. for (V3GraphEdge* edgep = logicp->inBeginp(); edgep; edgep = edgep->inNextp()) { SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep); oedgep->setIgnoreThisStep(); } } if (debug()>=9) { m_graph.dumpDotFilePrefixed("splitg_nodup", false); } // Weak coloring to determine what needs to remain grouped // in a single always. This follows all edges excluding: // - those we pruned above // - PostEdges, which are done later m_graph.weaklyConnected(&SplitEdge::followScoreboard); }
void cleanupBlockGraph(AstNode* nodep) { // Transform the graph into what we need UINFO(5, "ReorderBlock "<<nodep<<endl); m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); if (debug()>=9) { m_graph.dumpDotFilePrefixed("reorderg_nodup", false); //m_graph.dump(); cout<<endl; } // Mark all the logic for this step // Vertex::m_user begin: true indicates logic for this step m_graph.userClearVertices(); for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) { SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p(); vvertexp->user(true); } // If a var vertex has only inputs, it's a input-only node, // and can be ignored for coloring **this block only** SplitEdge::incrementStep(); pruneDepsOnInputs(); // For reordering this single block only, mark all logic // vertexes not involved with this step as unimportant for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { if (SplitLogicVertex* vvertexp = dynamic_cast<SplitLogicVertex*>(vertexp)) { if (!vvertexp->user()) { for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) { SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep); oedgep->setIgnoreThisStep(); } for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep); oedgep->setIgnoreThisStep(); } } } } // Weak coloring to determine what needs to remain in order // This follows all step-relevant edges excluding PostEdges, which are done later m_graph.weaklyConnected(&SplitEdge::followScoreboard); // Add hard orderings between all nodes of same color, in the order they appeared vl_unordered_map<uint32_t, SplitLogicVertex*> lastOfColor; for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) { SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p(); uint32_t color = vvertexp->color(); if (!color) nextp->v3fatalSrc("No node color assigned"); if (lastOfColor[color]) { new SplitStrictEdge(&m_graph, lastOfColor[color], vvertexp); } lastOfColor[color] = vvertexp; } // And a real ordering to get the statements into something reasonable // We don't care if there's cutable violations here... // Non-cutable violations should be impossible; as those edges are program-order if (debug()>=9) m_graph.dumpDotFilePrefixed((string)"splitg_preo", false); m_graph.acyclic(&SplitEdge::followCyclic); m_graph.rank(&SplitEdge::followCyclic); // Or order(), but that's more expensive if (debug()>=9) m_graph.dumpDotFilePrefixed((string)"splitg_opt", false); }
void reorderBlock(AstNode* nodep) { // Reorder statements in the completed graph AstAlways* splitAlwaysp = nodep->backp()->castAlways(); // Map the rank numbers into nodes they associate with typedef multimap<uint32_t,AstNode*> RankNodeMap; typedef map<uint32_t,RankNodeMap> ColorRankMap; ColorRankMap colorRankMap; uint32_t firstColor = 0; bool multiColors = false; int currOrder = 0; // Existing sequence number of assignment for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) { SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p(); if (!splitAlwaysp) vvertexp->splitColor(1); // All blocks remain as-is RankNodeMap& rankMap = colorRankMap[vvertexp->splitColor()]; rankMap.insert(make_pair(vvertexp->rank(), nextp)); if (firstColor && firstColor != vvertexp->splitColor()) multiColors = true; firstColor = vvertexp->splitColor(); nextp->user4(++currOrder); // Record current ordering } // If there was only one color, we don't need multiple always blocks if (!multiColors) splitAlwaysp = NULL; // Is the current ordering OK? bool leaveAlone=true; if (splitAlwaysp) leaveAlone=false; int newOrder = 0; // New sequence number of assignment for (ColorRankMap::iterator colorIt = colorRankMap.begin(); colorIt != colorRankMap.end(); ++colorIt) { RankNodeMap& rankMap = colorIt->second; for (RankNodeMap::iterator it = rankMap.begin(); it != rankMap.end(); ++it) { AstNode* nextp = it->second; if (++newOrder != nextp->user4()) leaveAlone=false; } } if (leaveAlone) { UINFO(6," No changes\n"); } else { AstNRelinker replaceHandle; // Where to add the list AstNode* addAfterp = splitAlwaysp; for (ColorRankMap::iterator colorIt = colorRankMap.begin(); colorIt != colorRankMap.end(); ++colorIt) { uint32_t color = colorIt->first; RankNodeMap& rankMap = colorIt->second; AstNode* newListp = NULL; for (RankNodeMap::iterator it = rankMap.begin(); it != rankMap.end(); ++it) { AstNode* nextp = it->second; UINFO(6, " Color="<<color<<" New order: "<<nextp<<endl); if (nextp == nodep && !splitAlwaysp) nodep->unlinkFrBack(&replaceHandle); else nextp->unlinkFrBack(); newListp = newListp->addNext(nextp); } if (splitAlwaysp) { ++m_statSplits; AstAlways* alwaysp = new AstAlways(newListp->fileline(), VAlwaysKwd::ALWAYS, NULL, NULL); addAfterp->addNextHere(alwaysp); addAfterp=alwaysp; alwaysp->addStmtp(newListp); } else { // Just reordering replaceHandle.relink(newListp); } } if (splitAlwaysp) { pushDeletep(splitAlwaysp->unlinkFrBack()); } } // leaveAlone }