NodeList Element::getElementsByTagName (const DOMString& name) { NodeList elements; for (size_t i = 0; i < _children.length(); i++) { Node* node = _children.item(i); if (node->nodeType() == Node::ELEMENT_NODE) { if (((Element*)node)->tagName() == Utils::toUpper(name)) { elements.insert(node); } } } for (size_t i = 0; i < _children.length(); i++) { Node* node = _children.item(i); if (node->nodeType() == Node::ELEMENT_NODE) { NodeList subElements = ((Element*)node)->getElementsByTagName(name); for (size_t h = 0; h < subElements.length(); h++) { elements.insert(subElements.item(h)); } } } return elements; }
static void chaseDownPredecessors(iterator node, Register value, DataflowGraph* dfg, dataflow_iterator block, NodeList& nodes, InstructionToNodeMap& instructionToNodes, BlockSet& visited) { if(!visited.insert(block).second) return; assert(block->aliveIn().count(value) != 0); for(auto predecessor : block->predecessors()) { if(predecessor->aliveOut().count(value) == 0) continue; bool foundAnyDefinitions = false; // check the body for a definition for(auto instruction = predecessor->instructions().rbegin(); instruction != predecessor->instructions().rend(); ++instruction) { for(auto destination : instruction->d) { if(*destination.pointer == value) { auto producer = nodes.end(); auto ptx = static_cast<PTXInstruction*>(instruction->i); auto existingNode = instructionToNodes.find(ptx); if(existingNode == instructionToNodes.end()) { producer = nodes.insert(nodes.end(), Node(ptx)); instructionToNodes.insert( std::make_pair(ptx, producer)); } else { producer = existingNode->second; } report(" " << producer->instruction->toString() << " -> " << node->instruction->toString()); node->predecessors.push_back(producer); producer->successors.push_back(node); foundAnyDefinitions = true; break; } } } if(foundAnyDefinitions) continue; // if no definitions were found, recurse through predecessors chaseDownPredecessors(node, value, dfg, predecessor, nodes, instructionToNodes, visited); } }
void push(int v) { Edge* now = net[v][cur[v]]; double flow = min(now->cap(v), e[v]); int w = now->other(v); if ( zr(e[w]) && w != t) lst.insert(w, h[w]); now->addFlow(v, flow); e[v] -= flow; e[w] += flow; }
static void analyzeBlock(dataflow_iterator block, DataflowGraph* dfg, NodeList& nodes, InstructionToNodeMap& instructionToNodes) { typedef std::unordered_map<Register, iterator> RegisterToProducerMap; RegisterToProducerMap lastProducers; for(auto& instruction : block->instructions()) { // Create a node auto node = nodes.end(); auto ptx = static_cast<PTXInstruction*>(instruction.i); auto existingNode = instructionToNodes.find(ptx); if(existingNode == instructionToNodes.end()) { node = nodes.insert(nodes.end(), Node(ptx)); instructionToNodes.insert(std::make_pair(ptx, node)); } else { node = existingNode->second; } // Add predecessors for(auto source : instruction.s) { auto producer = lastProducers.find(*source.pointer); if(producer == lastProducers.end()) { BlockSet visited; chaseDownPredecessors(node, *source.pointer, dfg, block, nodes, instructionToNodes, visited); continue; } report(" " << producer->second->instruction->toString() << " -> " << node->instruction->toString()); node->predecessors.push_back(producer->second); producer->second->successors.push_back(node); } // Update last producers for(auto destination : instruction.d) { lastProducers[*destination.pointer] = node; } } }
/** return a list of pointer to the objects of specified class type */ NodeList* NodeList::selectClass (QString classname) { NodeList* nl = new NodeList; Node* node; for ( QStringList::Iterator it = list_.begin(); it != list_.end(); ++it ) { node = find(*it); if (!node) { qDebug("NodeList::selectClass: %s Warning: %s not found in nodelist", classname.latin1(),(*it).latin1()); continue; } if (classname.compare(node->classname()) == 0) { nl->insert (node->key(), node );//insert node } } return nl; }
static bool Graph_divide(Graph& graph, size_t loops, PositionList* position_tbl) { typedef std::set< size_t > NodeList; NodeList nodes; // nodes for (Graph::const_iterator i = graph.begin(); i != graph.end(); ++i) { nodes.insert(i->first); } while (!nodes.empty()) { // BFS Graph component; std::deque< size_t > Q = boost::assign::list_of(*nodes.begin()); while (!Q.empty()) { size_t xi = Q.front(); Q.pop_front(); if (nodes.find(xi) == nodes.end()) { continue; } nodes.erase(xi); Graph::const_iterator i = graph.find(xi); if (i != graph.end()) { for (Children::const_iterator j = i->second.children.begin(); j != i->second.children.end(); ++j) { Graph_addEdge(component, xi, j->first, j->second); Q.push_back(j->first); } for (Parents::const_iterator j = i->second.parents.begin(); j != i->second.parents.end(); ++j) { Q.push_back(*j); } } } LOG4CXX_TRACE(logger, boost::format("component:%d/%d") % component.size() % graph.size()); if (!Graph_solve(component, loops, position_tbl)) { LOG4CXX_ERROR(logger, "solve component failed"); return false; } } return true; }
NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, NodeAddr<RefNode*> RefA, bool FullChain, const RegisterSet &DefRRs) { SetVector<NodeId> DefQ; SetVector<NodeId> Owners; // The initial queue should not have reaching defs for shadows. The // whole point of a shadow is that it will have a reaching def that // is not aliased to the reaching defs of the related shadows. NodeId Start = RefA.Id; auto SNA = DFG.addr<RefNode*>(Start); if (NodeId RD = SNA.Addr->getReachingDef()) DefQ.insert(RD); // Collect all the reaching defs, going up until a phi node is encountered, // or there are no more reaching defs. From this set, the actual set of // reaching defs will be selected. // The traversal upwards must go on until a covering def is encountered. // It is possible that a collection of non-covering (individually) defs // will be sufficient, but keep going until a covering one is found. for (unsigned i = 0; i < DefQ.size(); ++i) { auto TA = DFG.addr<DefNode*>(DefQ[i]); if (TA.Addr->getFlags() & NodeAttrs::PhiRef) continue; // Stop at the covering/overwriting def of the initial register reference. RegisterRef RR = TA.Addr->getRegRef(); if (RAI.covers(RR, RefRR)) { uint16_t Flags = TA.Addr->getFlags(); if (!(Flags & NodeAttrs::Preserving)) continue; } // Get the next level of reaching defs. This will include multiple // reaching defs for shadows. for (auto S : DFG.getRelatedRefs(TA.Addr->getOwner(DFG), TA)) if (auto RD = NodeAddr<RefNode*>(S).Addr->getReachingDef()) DefQ.insert(RD); } // Remove all non-phi defs that are not aliased to RefRR, and collect // the owners of the remaining defs. SetVector<NodeId> Defs; for (auto N : DefQ) { auto TA = DFG.addr<DefNode*>(N); bool IsPhi = TA.Addr->getFlags() & NodeAttrs::PhiRef; if (!IsPhi && !RAI.alias(RefRR, TA.Addr->getRegRef())) continue; Defs.insert(TA.Id); Owners.insert(TA.Addr->getOwner(DFG).Id); } // Return the MachineBasicBlock containing a given instruction. auto Block = [this] (NodeAddr<InstrNode*> IA) -> MachineBasicBlock* { if (IA.Addr->getKind() == NodeAttrs::Stmt) return NodeAddr<StmtNode*>(IA).Addr->getCode()->getParent(); assert(IA.Addr->getKind() == NodeAttrs::Phi); NodeAddr<PhiNode*> PA = IA; NodeAddr<BlockNode*> BA = PA.Addr->getOwner(DFG); return BA.Addr->getCode(); }; // Less(A,B) iff instruction A is further down in the dominator tree than B. auto Less = [&Block,this] (NodeId A, NodeId B) -> bool { if (A == B) return false; auto OA = DFG.addr<InstrNode*>(A), OB = DFG.addr<InstrNode*>(B); MachineBasicBlock *BA = Block(OA), *BB = Block(OB); if (BA != BB) return MDT.dominates(BB, BA); // They are in the same block. bool StmtA = OA.Addr->getKind() == NodeAttrs::Stmt; bool StmtB = OB.Addr->getKind() == NodeAttrs::Stmt; if (StmtA) { if (!StmtB) // OB is a phi and phis dominate statements. return true; auto CA = NodeAddr<StmtNode*>(OA).Addr->getCode(); auto CB = NodeAddr<StmtNode*>(OB).Addr->getCode(); // The order must be linear, so tie-break such equalities. if (CA == CB) return A < B; return MDT.dominates(CB, CA); } else { // OA is a phi. if (StmtB) return false; // Both are phis. There is no ordering between phis (in terms of // the data-flow), so tie-break this via node id comparison. return A < B; } }; std::vector<NodeId> Tmp(Owners.begin(), Owners.end()); std::sort(Tmp.begin(), Tmp.end(), Less); // The vector is a list of instructions, so that defs coming from // the same instruction don't need to be artificially ordered. // Then, when computing the initial segment, and iterating over an // instruction, pick the defs that contribute to the covering (i.e. is // not covered by previously added defs). Check the defs individually, // i.e. first check each def if is covered or not (without adding them // to the tracking set), and then add all the selected ones. // The reason for this is this example: // *d1<A>, *d2<B>, ... Assume A and B are aliased (can happen in phi nodes). // *d3<C> If A \incl BuC, and B \incl AuC, then *d2 would be // covered if we added A first, and A would be covered // if we added B first. NodeList RDefs; RegisterSet RRs = DefRRs; auto DefInSet = [&Defs] (NodeAddr<RefNode*> TA) -> bool { return TA.Addr->getKind() == NodeAttrs::Def && Defs.count(TA.Id); }; for (auto T : Tmp) { if (!FullChain && RAI.covers(RRs, RefRR)) break; auto TA = DFG.addr<InstrNode*>(T); bool IsPhi = DFG.IsCode<NodeAttrs::Phi>(TA); NodeList Ds; for (NodeAddr<DefNode*> DA : TA.Addr->members_if(DefInSet, DFG)) { auto QR = DA.Addr->getRegRef(); // Add phi defs even if they are covered by subsequent defs. This is // for cases where the reached use is not covered by any of the defs // encountered so far: the phi def is needed to expose the liveness // of that use to the entry of the block. // Example: // phi d1<R3>(,d2,), ... Phi def d1 is covered by d2. // d2<R3>(d1,,u3), ... // ..., u3<D1>(d2) This use needs to be live on entry. if (FullChain || IsPhi || !RAI.covers(RRs, QR)) Ds.push_back(DA); } RDefs.insert(RDefs.end(), Ds.begin(), Ds.end()); for (NodeAddr<DefNode*> DA : Ds) { // When collecting a full chain of definitions, do not consider phi // defs to actually define a register. uint16_t Flags = DA.Addr->getFlags(); if (!FullChain || !(Flags & NodeAttrs::PhiRef)) if (!(Flags & NodeAttrs::Preserving)) RRs.insert(DA.Addr->getRegRef()); } } return RDefs; }
void Liveness::computePhiInfo() { RealUseMap.clear(); NodeList Phis; NodeAddr<FuncNode*> FA = DFG.getFunc(); auto Blocks = FA.Addr->members(DFG); for (NodeAddr<BlockNode*> BA : Blocks) { auto Ps = BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG); Phis.insert(Phis.end(), Ps.begin(), Ps.end()); } // phi use -> (map: reaching phi -> set of registers defined in between) std::map<NodeId,std::map<NodeId,RegisterSet>> PhiUp; std::vector<NodeId> PhiUQ; // Work list of phis for upward propagation. // Go over all phis. for (NodeAddr<PhiNode*> PhiA : Phis) { // Go over all defs and collect the reached uses that are non-phi uses // (i.e. the "real uses"). auto &RealUses = RealUseMap[PhiA.Id]; auto PhiRefs = PhiA.Addr->members(DFG); // Have a work queue of defs whose reached uses need to be found. // For each def, add to the queue all reached (non-phi) defs. SetVector<NodeId> DefQ; NodeSet PhiDefs; for (auto R : PhiRefs) { if (!DFG.IsRef<NodeAttrs::Def>(R)) continue; DefQ.insert(R.Id); PhiDefs.insert(R.Id); } for (unsigned i = 0; i < DefQ.size(); ++i) { NodeAddr<DefNode*> DA = DFG.addr<DefNode*>(DefQ[i]); NodeId UN = DA.Addr->getReachedUse(); while (UN != 0) { NodeAddr<UseNode*> A = DFG.addr<UseNode*>(UN); if (!(A.Addr->getFlags() & NodeAttrs::PhiRef)) RealUses[getRestrictedRegRef(A)].insert(A.Id); UN = A.Addr->getSibling(); } NodeId DN = DA.Addr->getReachedDef(); while (DN != 0) { NodeAddr<DefNode*> A = DFG.addr<DefNode*>(DN); for (auto T : DFG.getRelatedRefs(A.Addr->getOwner(DFG), A)) { uint16_t Flags = NodeAddr<DefNode*>(T).Addr->getFlags(); // Must traverse the reached-def chain. Consider: // def(D0) -> def(R0) -> def(R0) -> use(D0) // The reachable use of D0 passes through a def of R0. if (!(Flags & NodeAttrs::PhiRef)) DefQ.insert(T.Id); } DN = A.Addr->getSibling(); } } // Filter out these uses that appear to be reachable, but really // are not. For example: // // R1:0 = d1 // = R1:0 u2 Reached by d1. // R0 = d3 // = R1:0 u4 Still reached by d1: indirectly through // the def d3. // R1 = d5 // = R1:0 u6 Not reached by d1 (covered collectively // by d3 and d5), but following reached // defs and uses from d1 will lead here. auto HasDef = [&PhiDefs] (NodeAddr<DefNode*> DA) -> bool { return PhiDefs.count(DA.Id); }; for (auto UI = RealUses.begin(), UE = RealUses.end(); UI != UE; ) { // For each reached register UI->first, there is a set UI->second, of // uses of it. For each such use, check if it is reached by this phi, // i.e. check if the set of its reaching uses intersects the set of // this phi's defs. auto &Uses = UI->second; for (auto I = Uses.begin(), E = Uses.end(); I != E; ) { auto UA = DFG.addr<UseNode*>(*I); NodeList RDs = getAllReachingDefs(UI->first, UA); if (std::any_of(RDs.begin(), RDs.end(), HasDef)) ++I; else I = Uses.erase(I); } if (Uses.empty()) UI = RealUses.erase(UI); else ++UI; } // If this phi reaches some "real" uses, add it to the queue for upward // propagation. if (!RealUses.empty()) PhiUQ.push_back(PhiA.Id); // Go over all phi uses and check if the reaching def is another phi. // Collect the phis that are among the reaching defs of these uses. // While traversing the list of reaching defs for each phi use, collect // the set of registers defined between this phi (Phi) and the owner phi // of the reaching def. for (auto I : PhiRefs) { if (!DFG.IsRef<NodeAttrs::Use>(I)) continue; NodeAddr<UseNode*> UA = I; auto &UpMap = PhiUp[UA.Id]; RegisterSet DefRRs; for (NodeAddr<DefNode*> DA : getAllReachingDefs(UA)) { if (DA.Addr->getFlags() & NodeAttrs::PhiRef) UpMap[DA.Addr->getOwner(DFG).Id] = DefRRs; else DefRRs.insert(DA.Addr->getRegRef()); } } } if (Trace) { dbgs() << "Phi-up-to-phi map:\n"; for (auto I : PhiUp) { dbgs() << "phi " << Print<NodeId>(I.first, DFG) << " -> {"; for (auto R : I.second) dbgs() << ' ' << Print<NodeId>(R.first, DFG) << Print<RegisterSet>(R.second, DFG); dbgs() << " }\n"; } } // Propagate the reached registers up in the phi chain. // // The following type of situation needs careful handling: // // phi d1<R1:0> (1) // | // ... d2<R1> // | // phi u3<R1:0> (2) // | // ... u4<R1> // // The phi node (2) defines a register pair R1:0, and reaches a "real" // use u4 of just R1. The same phi node is also known to reach (upwards) // the phi node (1). However, the use u4 is not reached by phi (1), // because of the intervening definition d2 of R1. The data flow between // phis (1) and (2) is restricted to R1:0 minus R1, i.e. R0. // // When propagating uses up the phi chains, get the all reaching defs // for a given phi use, and traverse the list until the propagated ref // is covered, or until or until reaching the final phi. Only assume // that the reference reaches the phi in the latter case. for (unsigned i = 0; i < PhiUQ.size(); ++i) { auto PA = DFG.addr<PhiNode*>(PhiUQ[i]); auto &RealUses = RealUseMap[PA.Id]; for (auto U : PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG)) { NodeAddr<UseNode*> UA = U; auto &UpPhis = PhiUp[UA.Id]; for (auto UP : UpPhis) { bool Changed = false; auto &MidDefs = UP.second; // Collect the set UpReached of uses that are reached by the current // phi PA, and are not covered by any intervening def between PA and // the upward phi UP. RegisterSet UpReached; for (auto T : RealUses) { if (!isRestricted(PA, UA, T.first)) continue; if (!RAI.covers(MidDefs, T.first)) UpReached.insert(T.first); } if (UpReached.empty()) continue; // Update the set PRUs of real uses reached by the upward phi UP with // the actual set of uses (UpReached) that the UP phi reaches. auto &PRUs = RealUseMap[UP.first]; for (auto R : UpReached) { unsigned Z = PRUs[R].size(); PRUs[R].insert(RealUses[R].begin(), RealUses[R].end()); Changed |= (PRUs[R].size() != Z); } if (Changed) PhiUQ.push_back(UP.first); } } } if (Trace) { dbgs() << "Real use map:\n"; for (auto I : RealUseMap) { dbgs() << "phi " << Print<NodeId>(I.first, DFG); NodeAddr<PhiNode*> PA = DFG.addr<PhiNode*>(I.first); NodeList Ds = PA.Addr->members_if(DFG.IsRef<NodeAttrs::Def>, DFG); if (!Ds.empty()) { RegisterRef RR = NodeAddr<DefNode*>(Ds[0]).Addr->getRegRef(); dbgs() << '<' << Print<RegisterRef>(RR, DFG) << '>'; } else { dbgs() << "<noreg>"; } dbgs() << " -> " << Print<RefMap>(I.second, DFG) << '\n'; } } }
int main(int argc, char** argv) { NodeList<int> llista; OrderedList<int> llistaOrd; cout << "Vols introduir les dades per consola o per fitxer (C/F)?" << endl; if(cin.get() == 'F') { FILE * pFile; pFile = fopen("fitxer.txt" , "r"); int n; ifstream fe("fitxer.txt"); while (scanf("%d", &n) == 1) { llista.insert(n); llistaOrd.insert(n); } } else { cout << "Introdueix una seqüència de nombres acabada per 99:" << endl; int aux; cin >> aux; while(aux != 99) { llista.insert(aux); llistaOrd.insert(aux); cin >> aux; } } cout << "Llista: "; llista.show(); cout << "Llista Ordenada: "; llistaOrd.show(); cout << endl << "Introdueix un nombre a cercar:" << endl; cin >> aux; cout << "Nombres posteriors a " << aux << " a la llista:" << endl; llista.begin(); bool trobat = false; while(!llista.end()) { if(trobat) { cout << llista.get() << " " ; } else { if(llista.get() == aux) trobat = true; } llista.next(); } cout << endl << "Nombres posteriors a " << aux << " a la llista ordenada:" <<endl; trobat = false; llistaOrd.begin(); while(!llistaOrd.end()) { if(trobat) { cout << llistaOrd.get() << " " ; } else { if(llistaOrd.get() == aux) trobat = true; } llistaOrd.next(); } cout << endl << "Llista esborrada i recursos alliberats" << endl; llista.begin(); while(!llista.end()) { llista.remove(); } cout << "Llista ordenada esborrada i recursos alliberats:" << endl; llistaOrd.begin(); while(!llistaOrd.end()) { llistaOrd.remove(); } cout << "Llista:" << endl; llista.show(); cout << "Llista ordenada:" << endl; llistaOrd.show(); return 0; }
void Liveness::computePhiInfo() { RealUseMap.clear(); NodeList Phis; NodeAddr<FuncNode*> FA = DFG.getFunc(); NodeList Blocks = FA.Addr->members(DFG); for (NodeAddr<BlockNode*> BA : Blocks) { auto Ps = BA.Addr->members_if(DFG.IsCode<NodeAttrs::Phi>, DFG); Phis.insert(Phis.end(), Ps.begin(), Ps.end()); } // phi use -> (map: reaching phi -> set of registers defined in between) std::map<NodeId,std::map<NodeId,RegisterAggr>> PhiUp; std::vector<NodeId> PhiUQ; // Work list of phis for upward propagation. // Go over all phis. for (NodeAddr<PhiNode*> PhiA : Phis) { // Go over all defs and collect the reached uses that are non-phi uses // (i.e. the "real uses"). RefMap &RealUses = RealUseMap[PhiA.Id]; NodeList PhiRefs = PhiA.Addr->members(DFG); // Have a work queue of defs whose reached uses need to be found. // For each def, add to the queue all reached (non-phi) defs. SetVector<NodeId> DefQ; NodeSet PhiDefs; for (NodeAddr<RefNode*> R : PhiRefs) { if (!DFG.IsRef<NodeAttrs::Def>(R)) continue; DefQ.insert(R.Id); PhiDefs.insert(R.Id); } // Collect the super-set of all possible reached uses. This set will // contain all uses reached from this phi, either directly from the // phi defs, or (recursively) via non-phi defs reached by the phi defs. // This set of uses will later be trimmed to only contain these uses that // are actually reached by the phi defs. for (unsigned i = 0; i < DefQ.size(); ++i) { NodeAddr<DefNode*> DA = DFG.addr<DefNode*>(DefQ[i]); // Visit all reached uses. Phi defs should not really have the "dead" // flag set, but check it anyway for consistency. bool IsDead = DA.Addr->getFlags() & NodeAttrs::Dead; NodeId UN = !IsDead ? DA.Addr->getReachedUse() : 0; while (UN != 0) { NodeAddr<UseNode*> A = DFG.addr<UseNode*>(UN); uint16_t F = A.Addr->getFlags(); if ((F & (NodeAttrs::Undef | NodeAttrs::PhiRef)) == 0) { RegisterRef R = PRI.normalize(A.Addr->getRegRef(DFG)); RealUses[R.Reg].insert({A.Id,R.Mask}); } UN = A.Addr->getSibling(); } // Visit all reached defs, and add them to the queue. These defs may // override some of the uses collected here, but that will be handled // later. NodeId DN = DA.Addr->getReachedDef(); while (DN != 0) { NodeAddr<DefNode*> A = DFG.addr<DefNode*>(DN); for (auto T : DFG.getRelatedRefs(A.Addr->getOwner(DFG), A)) { uint16_t Flags = NodeAddr<DefNode*>(T).Addr->getFlags(); // Must traverse the reached-def chain. Consider: // def(D0) -> def(R0) -> def(R0) -> use(D0) // The reachable use of D0 passes through a def of R0. if (!(Flags & NodeAttrs::PhiRef)) DefQ.insert(T.Id); } DN = A.Addr->getSibling(); } } // Filter out these uses that appear to be reachable, but really // are not. For example: // // R1:0 = d1 // = R1:0 u2 Reached by d1. // R0 = d3 // = R1:0 u4 Still reached by d1: indirectly through // the def d3. // R1 = d5 // = R1:0 u6 Not reached by d1 (covered collectively // by d3 and d5), but following reached // defs and uses from d1 will lead here. auto InPhiDefs = [&PhiDefs] (NodeAddr<DefNode*> DA) -> bool { return PhiDefs.count(DA.Id); }; for (auto UI = RealUses.begin(), UE = RealUses.end(); UI != UE; ) { // For each reached register UI->first, there is a set UI->second, of // uses of it. For each such use, check if it is reached by this phi, // i.e. check if the set of its reaching uses intersects the set of // this phi's defs. NodeRefSet &Uses = UI->second; for (auto I = Uses.begin(), E = Uses.end(); I != E; ) { auto UA = DFG.addr<UseNode*>(I->first); // Undef flag is checked above. assert((UA.Addr->getFlags() & NodeAttrs::Undef) == 0); RegisterRef R(UI->first, I->second); NodeList RDs = getAllReachingDefs(R, UA); // If none of the reaching defs of R are from this phi, remove this // use of R. I = any_of(RDs, InPhiDefs) ? std::next(I) : Uses.erase(I); } UI = Uses.empty() ? RealUses.erase(UI) : std::next(UI); } // If this phi reaches some "real" uses, add it to the queue for upward // propagation. if (!RealUses.empty()) PhiUQ.push_back(PhiA.Id); // Go over all phi uses and check if the reaching def is another phi. // Collect the phis that are among the reaching defs of these uses. // While traversing the list of reaching defs for each phi use, accumulate // the set of registers defined between this phi (PhiA) and the owner phi // of the reaching def. NodeSet SeenUses; for (auto I : PhiRefs) { if (!DFG.IsRef<NodeAttrs::Use>(I) || SeenUses.count(I.Id)) continue; NodeAddr<PhiUseNode*> PUA = I; if (PUA.Addr->getReachingDef() == 0) continue; RegisterRef UR = PUA.Addr->getRegRef(DFG); NodeList Ds = getAllReachingDefs(UR, PUA, true, false, NoRegs); RegisterAggr DefRRs(PRI); for (NodeAddr<DefNode*> D : Ds) { if (D.Addr->getFlags() & NodeAttrs::PhiRef) { NodeId RP = D.Addr->getOwner(DFG).Id; std::map<NodeId,RegisterAggr> &M = PhiUp[PUA.Id]; auto F = M.find(RP); if (F == M.end()) M.insert(std::make_pair(RP, DefRRs)); else F->second.insert(DefRRs); } DefRRs.insert(D.Addr->getRegRef(DFG)); } for (NodeAddr<PhiUseNode*> T : DFG.getRelatedRefs(PhiA, PUA)) SeenUses.insert(T.Id); } } if (Trace) { dbgs() << "Phi-up-to-phi map with intervening defs:\n"; for (auto I : PhiUp) { dbgs() << "phi " << Print<NodeId>(I.first, DFG) << " -> {"; for (auto R : I.second) dbgs() << ' ' << Print<NodeId>(R.first, DFG) << Print<RegisterAggr>(R.second, DFG); dbgs() << " }\n"; } } // Propagate the reached registers up in the phi chain. // // The following type of situation needs careful handling: // // phi d1<R1:0> (1) // | // ... d2<R1> // | // phi u3<R1:0> (2) // | // ... u4<R1> // // The phi node (2) defines a register pair R1:0, and reaches a "real" // use u4 of just R1. The same phi node is also known to reach (upwards) // the phi node (1). However, the use u4 is not reached by phi (1), // because of the intervening definition d2 of R1. The data flow between // phis (1) and (2) is restricted to R1:0 minus R1, i.e. R0. // // When propagating uses up the phi chains, get the all reaching defs // for a given phi use, and traverse the list until the propagated ref // is covered, or until reaching the final phi. Only assume that the // reference reaches the phi in the latter case. for (unsigned i = 0; i < PhiUQ.size(); ++i) { auto PA = DFG.addr<PhiNode*>(PhiUQ[i]); NodeList PUs = PA.Addr->members_if(DFG.IsRef<NodeAttrs::Use>, DFG); RefMap &RUM = RealUseMap[PA.Id]; for (NodeAddr<UseNode*> UA : PUs) { std::map<NodeId,RegisterAggr> &PUM = PhiUp[UA.Id]; RegisterRef UR = PRI.normalize(UA.Addr->getRegRef(DFG)); for (const std::pair<NodeId,RegisterAggr> &P : PUM) { bool Changed = false; const RegisterAggr &MidDefs = P.second; // Collect the set PropUp of uses that are reached by the current // phi PA, and are not covered by any intervening def between the // currently visited use UA and the the upward phi P. if (MidDefs.hasCoverOf(UR)) continue; // General algorithm: // for each (R,U) : U is use node of R, U is reached by PA // if MidDefs does not cover (R,U) // then add (R-MidDefs,U) to RealUseMap[P] // for (const std::pair<RegisterId,NodeRefSet> &T : RUM) { RegisterRef R = DFG.restrictRef(RegisterRef(T.first), UR); if (!R) continue; for (std::pair<NodeId,LaneBitmask> V : T.second) { RegisterRef S = DFG.restrictRef(RegisterRef(R.Reg, V.second), R); if (!S) continue; if (RegisterRef SS = MidDefs.clearIn(S)) { NodeRefSet &RS = RealUseMap[P.first][SS.Reg]; Changed |= RS.insert({V.first,SS.Mask}).second; } } } if (Changed) PhiUQ.push_back(P.first); } } } if (Trace) { dbgs() << "Real use map:\n"; for (auto I : RealUseMap) { dbgs() << "phi " << Print<NodeId>(I.first, DFG); NodeAddr<PhiNode*> PA = DFG.addr<PhiNode*>(I.first); NodeList Ds = PA.Addr->members_if(DFG.IsRef<NodeAttrs::Def>, DFG); if (!Ds.empty()) { RegisterRef RR = NodeAddr<DefNode*>(Ds[0]).Addr->getRegRef(DFG); dbgs() << '<' << Print<RegisterRef>(RR, DFG) << '>'; } else { dbgs() << "<noreg>"; } dbgs() << " -> " << Print<RefMap>(I.second, DFG) << '\n'; } } }
bool BottomUpLib::neighbour(Stack& stack){ StackElement *el1=0; StackElement *el2=0; StackElement *el3=0; StackElement *el4=0; try { if (stack.count()<4) throw Stack::CleanUp(false); // sind noch genug Werte auf dem stack? el1=stack.pop(); //Abstandswert vom stack holen el2=stack.pop(); //Richtung vom stack holen el3=stack.pop(); //nodelist Schatten vom stack holen el4=stack.pop(); //nodelist Dach vom stack holen // Typen testen if (el1->type()!=StackElement::NUMBER || el2->type()!=StackElement::STRING || el3->type()!=StackElement::NODELIST || el4->type()!=StackElement::NODELIST) throw Stack::CleanUp(false); // Werte holen float maxdist=((StackElementNumber*)el1)->data(); // max eudist QString dir=((StackElementString*)el2)->data(); // Sonnenrichtung NodeList& nl2=((StackElementNodeList*)el3)->data(); // Schatten NodeList& nl1=((StackElementNodeList*)el4)->data(); // Daecher #ifdef DEBUGMESSAGES cout<<"in function neighbour"<<endl; #endif { RegionSensor *rs1 = new RegionSensor(); nl1.calcForSelect("ALL", "llx", rs1); nl1.calcForSelect("ALL", "lly", rs1); nl1.calcForSelect("ALL", "urx", rs1); nl1.calcForSelect("ALL", "ury", rs1); nl1.calcForSelect("ALL", "area", rs1); delete rs1; RegionSensor *rs2 = new RegionSensor(); nl2.calcForSelect("ALL", "llx", rs2); nl2.calcForSelect("ALL", "lly", rs2); nl2.calcForSelect("ALL", "urx", rs2); nl2.calcForSelect("ALL", "ury", rs2); nl2.calcForSelect("ALL", "area", rs2); delete rs2; } Stack* st= new Stack; // Ergebnis stack anlegen QHash<QString,Node*>::iterator it1=nl1.begin(); // nodelist1 durchlaufen Daecher while ( it1!=nl1.end() ) { Node *node1 = it1.value(); NodeList *nlist = new NodeList; GeoPosition gp(node1, node1->getValue("llx").toInt(), node1->getValue("lly").toInt(), node1->getValue("urx").toInt(), node1->getValue("ury").toInt(), node1->getValue("area").toFloat() ); gp.key(it1.key()); int shade=0; QHash<QString,Node*>::iterator it2=nl2.begin(); // nodelist2 durchlaufen Schattenbereiche while ( it2!=nl2.end() ) { Node *node2 = it2.value(); if (gp.bbOverlap(GeoPosition (node2, node2->getValue("llx").toInt(), node2->getValue("lly").toInt(), node2->getValue("urx").toInt(), node2->getValue("ury").toInt(), node2->getValue("area").toFloat() ), dir, maxdist)){ if (!shade){ #ifdef DEBUGMESSAGES cout<<"Haus in nodelist eingehaengt"<<endl; #endif //DEBUGMESSAGES // insert node1 Haus nlist->insert(node1->value("addr"), node1 ); shade=1; } // insert node2 Schatten nlist->insert(node2->value("addr"), node2 ); #ifdef DEBUGMESSAGES cout<<"Schatten in nodelist eingehaengt"<<endl; #endif //DEBUGMESSAGES } ++it2; } if (shade){ st->push(new StackElementNodeList(*nlist)); #ifdef DEBUGMESSAGES cout<<"nodelist auf lokalen stack gepusht"<<endl; #endif //DEBUGMESSAGES } delete nlist; ++it1; } stack.push(new StackElementStack(*st)); #ifdef DEBUGMESSAGES cout<<"gefundene Haeuser mit Schatten:"<<st->count()<<" auf globalen Stack gepusht"<<endl; #endif //DEBUGMESSAGES delete st; throw Stack::CleanUp(true); } catch(Stack::CleanUp e) { if (el1) delete el1; if (el2) delete el2; if (el3) delete el3; if (el4) delete el4; return e.status_; } }
void DataFlow::mergeFlow(Graph<NodeDesc>* f,const Graph<NodeDesc>* g, std::map<Node*,Node*>& mapping) { // mapping is g -> f NodeList queue = g->rootNodes(); while (!queue.empty()) { Node* n = queue.back(); queue.pop_back(); // check predecessors bool allSourcesMapped = true; for (LinkListCIt sIt=n->sources().begin();sIt!=n->sources().end();sIt++) { Link* sLink = *sIt; map<Node*,Node*>::iterator findIt=mapping.find(sLink->source); if (findIt==mapping.end()) { allSourcesMapped = false; break; } } if (!allSourcesMapped) { // some sources miss. Ignore current node for now continue; } if (mapping.find(n)==mapping.end()) { // merge node // all sources are merged, merge current node Node* mergedNode(NULL); // first check if identical node already exists in f NodeList candidates; if (n->sources().size()>0) { candidates = mapping.find(n->sources()[0]->source)->second->targetNodes(); } else { candidates = f->rootNodes(); } for (NodeListIt cIt=candidates.begin();cIt!=candidates.end();cIt++) { if ((**cIt==*n) && sources_match(n->sources(),(*cIt)->sources(),mapping)) { // found identical node mergedNode = *cIt; break; } } if (mergedNode==NULL) { // no identical node found. Create node mergedNode = f->createNode(n->v); for (LinkListCIt sIt=n->sources().begin();sIt!=n->sources().end();sIt++) { f->link(mapping.find((*sIt)->source)->second,(*sIt)->sourceOutputPort, mergedNode, (*sIt)->targetInputPort); } } // register mapping mapping[n] = mergedNode; } // add target nodes to queue NodeList targets = n->targetNodes(); queue.insert(queue.end(),targets.begin(),targets.end()); } // merge names for (NameMapCIt gnIt=g->getNames().begin();gnIt!=g->getNames().end();gnIt++) { NameMapCIt fnIt = f->getNames().find(gnIt->first); if (fnIt!=f->getNames().end()) { // check nodes are merged if (mapping[gnIt->second]!=fnIt->second) { cerr << "ERROR: '" << gnIt->first << "' node exists in the two graphs and cannot be merged !" << endl; } } else { // add named node to f f->setNodeName(mapping[gnIt->second], gnIt->first); } } }