bool run() { ASSERT(m_graph.m_form != SSA); BlockSet blocksThatNeedInvalidationPoints; for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { BasicBlock* block = m_graph.block(blockIndex); if (!block) continue; for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) handle(nodeIndex, block->at(nodeIndex)); // Note: this assumes that control flow occurs at bytecode instruction boundaries. if (m_originThatHadFire.isSet()) { for (unsigned i = block->numSuccessors(); i--;) blocksThatNeedInvalidationPoints.add(block->successor(i)); } m_insertionSet.execute(block); } for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { BasicBlock* block = m_graph.block(blockIndex); if (!blocksThatNeedInvalidationPoints.contains(block)) continue; insertInvalidationCheck(0, block->at(0)); m_insertionSet.execute(block); } return true; }
void ReplayAudioIngest::emit_frame(channel_entry &ch) { BlockSet bset; size_t i; if (ch.fifo->fill_samples( ) < fft_size) { throw std::runtime_error("cannot emit frame, not enough samples"); } /* take FFT of ch.fifo->data( ) into ch.current_frame */ fft->compute(ch.current_frame, ch.fifo->data( )); /* subtract phase of last_frame from phase of current_frame to get output_frame */ for (i = 0; i < fft_size; i++) { output_frame[i] = std::polar( std::abs(ch.current_frame[i]), std::arg(ch.current_frame[i]) - std::arg(ch.last_frame[i]) ); } /* * swap last_frame and current_frame pointers * (this makes current_frame the next last_frame) */ std::swap(ch.last_frame, ch.current_frame); /* write output_frame to buffer */ bset.add_block(REPLAY_PVOC_BLOCK, output_frame, fft_size); bset.add_block("Debug001", ch.fifo->data( ), fft_size); ch.buffer->write_blockset(bset); ch.fifo->pop_samples(fft_hop); }
timecode_t ReplayBuffer::write_frame(const ReplayFrameData &data) { BlockSet blkset; if (data.video_size == 0) { throw std::runtime_error("Tried to write empty frame"); } if (data.video_size > 0) { blkset.add_block( REPLAY_VIDEO_BLOCK, data.video_data, data.video_size ); } if (data.thumbnail_size > 0) { blkset.add_block( REPLAY_THUMBNAIL_BLOCK, data.thumbnail_data, data.thumbnail_size ); } if (data.audio != NULL) { blkset.add_object(REPLAY_AUDIO_BLOCK, *(data.audio)); } return write_blockset(blkset); }
static BlockSet getBlocksWithCallsToFuctionsThatObserveSideEffects( ir::IRKernel& k) { BlockSet blocks; report(" Getting functions that can observe side-effects"); for(auto block = k.cfg()->begin(); block != k.cfg()->end(); ++block) { for(auto instruction : block->instructions) { auto ptxInstruction = static_cast<ir::PTXInstruction*>(instruction); // TODO: Check that the target can observe side effects if(ptxInstruction->isCall()) { report(" " << ptxInstruction->toString()); blocks.insert(block); break; } } } return blocks; }
static BlockSet getBlocksWithBranchesThatDependOn( const BlockSet& blocksWithBackwardsBranches, const InstructionSet& instructionsThatCanObserveSideEffects, DependenceAnalysis* dependenceAnalysis, ControlDependenceAnalysis* controlDependenceAnalysis) { BlockSet blocksWithDependentBranches; report(" Getting blocks with branches that can observe side-effects"); for(auto blockWithBranch : blocksWithBackwardsBranches) { auto branch = getBranch(blockWithBranch); if(branch == nullptr) continue; auto controlDependentInstructions = getControlDependentInstructions( branch, instructionsThatCanObserveSideEffects, controlDependenceAnalysis); for(auto instruction : controlDependentInstructions) { if(dependenceAnalysis->dependsOn(instruction, branch)) { report(" " << blockWithBranch->label()); blocksWithDependentBranches.insert(blockWithBranch); break; } } } return blocksWithDependentBranches; }
Layer Layer::getSubgraphConnectedToTheseOutputs( const NeuronSet& outputs) const { typedef std::set<size_t> BlockSet; BlockSet blocks; // TODO: eliminate the reundant inserts for(auto& output : outputs) { size_t block = (output / getOutputBlockingFactor()) % this->blocks(); blocks.insert(block); } Layer layer(blocks.size(), getInputBlockingFactor(), getOutputBlockingFactor(), blockStep()); for(auto& block : blocks) { size_t blockIndex = block - *blocks.begin(); layer[blockIndex] = (*this)[block]; layer.at_bias(blockIndex) = at_bias(block); } return layer; }
Udm::Object MatLabUdmChart::distinguish( Udm::Object udmParent ) { SLSF::State state; static boost::regex stateflowRegex( "stateflow", boost::regex_constants::perl | boost::regex_constants::icase ); boost::match_results<std::string::const_iterator> results; SLSF::Subsystem subsystemParent = SLSF::Subsystem::Cast( udmParent ); BlockSet blockSet = subsystemParent.Block_kind_children(); Udm::Object chartParent = udmParent; for( BlockSet::iterator blsItr = blockSet.begin() ; blsItr != blockSet.end() ; ++blsItr ) { Block block = *blsItr; std::string tag( block.Tag() ); if ( regex_search( tag, results, stateflowRegex ) ) { chartParent = block; break; } } #if PARADIGM == CyberComposition_PARADIGM state = SLSF::State::Create( chartParent ); #else state = SLSF::State::Create( UdmEngine::get_singleton().getTopLevelState() ); SLSF::ConnectorRef connectorRef = SLSF::ConnectorRef::Create( chartParent ); connectorRef.ref() = state; #endif return state; }
BlockSet Drainer::GetBestBlocks() const { BlockSet set; set.reserve(m_RootMacro->m_BestBlocks.size()); for (auto blk : m_RootMacro->m_BestBlocks) set.push_back(m_Blocks[blk]); return set; }
ControlFlowGraph::BlockPointerVector ControlFlowGraph::reverse_topological_sequence() { typedef std::set<iterator, BlockSetCompare> BlockSet; typedef std::queue<iterator> Queue; report("Creating reverse topological order traversal"); BlockSet visited; BlockPointerVector sequence; Queue queue; queue.push(get_exit_block()); while (sequence.size() != size()) { if(queue.empty()) { for (pointer_iterator block = sequence.begin(); block != sequence.end(); ++block) { for (pointer_iterator pred = (*block)->predecessors.begin(); pred != (*block)->predecessors.end(); ++pred) { if (visited.count(*pred) == 0) { queue.push(*pred); break; } } if(!queue.empty()) { break; } } if(queue.empty()) break; // The remaining blocks are unreachable } iterator current = queue.front(); queue.pop(); if(!visited.insert(current).second) continue; sequence.push_back(current); report(" Adding block " << current->label()); for (pointer_iterator block = current->predecessors.begin(); block != current->predecessors.end(); ++block) { bool noDependencies = true; for (pointer_iterator successor = (*block)->successors.begin(); successor != (*block)->successors.end(); ++successor) { if (visited.count(*successor) == 0) { noDependencies = false; break; } } if(noDependencies) { queue.push(*block); } } } return sequence; }
void TotalGenerator::Fill(BlockSet &data) { std::vector<int_fast8_t> set(data.FullSize(), false); for (auto i = 0; i < m_Total; i++) set[i] = true; std::shuffle(set.begin(), set.end(), m_Random); for (auto i = 0; i < data.FullSize(); i++) if (set[i]) data += i; }
void FindLive(Block *Root) { BlockList ToInvestigate; ToInvestigate.push_back(Root); while (ToInvestigate.size() > 0) { Block *Curr = ToInvestigate.front(); ToInvestigate.pop_front(); if (Live.find(Curr) != Live.end()) continue; Live.insert(Curr); for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { ToInvestigate.push_back(iter->first); } } }
void TextAutosizer::FingerprintMapper::assertMapsAreConsistent() { // For each fingerprint -> block mapping in m_blocksForFingerprint we should have an associated // map from block -> fingerprint in m_fingerprints. ReverseFingerprintMap::iterator end = m_blocksForFingerprint.end(); for (ReverseFingerprintMap::iterator fingerprintIt = m_blocksForFingerprint.begin(); fingerprintIt != end; ++fingerprintIt) { Fingerprint fingerprint = fingerprintIt->key; BlockSet* blocks = fingerprintIt->value.get(); for (BlockSet::iterator blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt) { const LayoutBlock* block = (*blockIt); ASSERT(m_fingerprints.get(block) == fingerprint); } } }
/** * Generate side walks */ void VBOPmBlocks::generateSideWalk(VBORenderManager* renderManager, BlockSet& blocks) { for (int i = 0; i < blocks.size(); ++i) { if (!blocks[i].valid) continue; BBox3D bbox; blocks[i].sidewalkContour.getBBox3D(bbox.minPt, bbox.maxPt); // If the block is too narrow, make it invalid. if (blocks[i].sidewalkContour.isTooNarrow(8.0f, 18.0f) || blocks[i].sidewalkContour.isTooNarrow(1.0f, 3.0f)) { blocks[i].valid = false; continue; } // If the block is close or under waterlevel, or on a steep terain, make it invalid. float min_z = std::numeric_limits<float>::max(); float max_z = 0.0f; for (int pi = 0; pi < blocks[i].sidewalkContour.contour.size(); ++pi) { int next_pi = (pi + 1) % blocks[i].sidewalkContour.contour.size(); for (int k = 0; k <= 20; ++k) { QVector3D pt = blocks[i].sidewalkContour.contour[pi] * (float)(20 - k) * 0.05 + blocks[i].sidewalkContour.contour[next_pi] * (float)k * 0.05; float z = renderManager->getTerrainHeight(pt.x(), pt.y()); min_z = std::min(min_z, z); max_z = std::max(max_z, z); } //float z = renderManager->getTerrainHeight(blocks[i].sidewalkContour.contour[pi].x(), blocks[i].sidewalkContour.contour[pi].y()); //min_z = std::min(min_z, z); //max_z = std::max(max_z, z); } if (min_z < 40.0f) { blocks[i].valid = false; continue; } else if (max_z - min_z > 20.0f) { blocks[i].isPark = true; continue; } } // Compute the block contour (the outer part becomes sidewalks) for (int i = 0; i < blocks.size(); ++i) { if (!blocks[i].valid) continue; //if (blocks[i].isPark) continue; Loop3D blockContourInset; float sidewalk_width = G::getFloat("sidewalk_width"); blocks[i].sidewalkContour.computeInset(sidewalk_width, blockContourInset, false); blocks[i].blockContour.contour = blockContourInset; //blocks[i].blockContour.getBBox3D(blocks[i].bbox.minPt, blocks[i].bbox.maxPt); } }
SILValue StackAllocationPromoter::getLiveOutValue(BlockSet &PhiBlocks, SILBasicBlock *StartBB) { DEBUG(llvm::dbgs() << "*** Searching for a value definition.\n"); // Walk the Dom tree in search of a defining value: for (DomTreeNode *Node = DT->getNode(StartBB); Node; Node = Node->getIDom()) { SILBasicBlock *BB = Node->getBlock(); // If there is a store (that must come after the phi), use its value. BlockToInstMap::iterator it = LastStoreInBlock.find(BB); if (it != LastStoreInBlock.end()) if (auto *St = dyn_cast_or_null<StoreInst>(it->second)) { DEBUG(llvm::dbgs() << "*** Found Store def " << *St->getSrc()); return St->getSrc(); } // If there is a Phi definition in this block: if (PhiBlocks.count(BB)) { // Return the dummy instruction that represents the new value that we will // add to the basic block. SILValue Phi = BB->getArgument(BB->getNumArguments() - 1); DEBUG(llvm::dbgs() << "*** Found a dummy Phi def " << *Phi); return Phi; } // Move to the next dominating block. DEBUG(llvm::dbgs() << "*** Walking up the iDOM.\n"); } DEBUG(llvm::dbgs() << "*** Could not find a Def. Using Undef.\n"); return SILUndef::get(ASI->getElementType(), ASI->getModule()); }
static bool allPreviousDefinitionsDominateMove(instruction_iterator move, block_iterator block, BlockSet& visited) { if(!visited.insert(block->id()).second) return true; assert(move->d.size() == 1); auto destination = *move->d.front().pointer; // If the value is defined by a phi with multiple sources, then the // previous definition does not dominate the move for(auto phi = block->phis().begin(); phi != block->phis().end(); ++phi) { if(phi->d == destination) { return false; } } // Check all predecessors with the value live out for(auto predecessor = block->predecessors().begin(); predecessor != block->predecessors().end(); ++predecessor) { if((*predecessor)->aliveOut().count(destination) == 0) continue; if(!allPreviousDefinitionsDominateMove(move, *predecessor, visited)) { return false; } } return true; }
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); } }
// Create a list of entries from a block. If LimitTo is provided, only results in that set // will appear void GetBlocksOut(Block *Source, BlockSet& Entries, BlockSet *LimitTo=NULL) { for (BlockBranchMap::iterator iter = Source->BranchesOut.begin(); iter != Source->BranchesOut.end(); iter++) { if (!LimitTo || LimitTo->find(iter->first) != LimitTo->end()) { Entries.insert(iter->first); } } }
bool isValidFlushLocation(BasicBlock* startingBlock, unsigned index, VirtualRegister operand) { // This code is not meant to be fast. We just use it for assertions. If we got liveness wrong, // this function would return false for a Flush that we insert. Vector<BasicBlock*, 4> worklist; BlockSet seen; auto addPredecessors = [&] (BasicBlock* block) { for (BasicBlock* predecessor : block->predecessors) { bool isNewEntry = seen.add(predecessor); if (isNewEntry) worklist.append(predecessor); } }; auto flushIsDefinitelyInvalid = [&] (BasicBlock* block, unsigned index) { bool allGood = false; for (unsigned i = index; i--; ) { if (block->at(i)->accessesStack(m_graph) && block->at(i)->local() == operand) { allGood = true; break; } } if (allGood) return false; if (block->predecessors.isEmpty()) { // This is a root block. We proved we reached here, therefore we can't Flush, as // it'll make this local live at the start of a root block, which is invalid IR. return true; } addPredecessors(block); return false; }; if (flushIsDefinitelyInvalid(startingBlock, index)) return false; while (!worklist.isEmpty()) { BasicBlock* block = worklist.takeLast(); if (flushIsDefinitelyInvalid(block, block->size())) return false; } return true; }
Shape *MakeMultiple(BlockSet &Blocks, BlockSet& Entries, BlockBlockSetMap& IndependentGroups, Shape *Prev, BlockSet &NextEntries) { PrintDebug("creating multiple block with %d inner groups\n", IndependentGroups.size()); bool Fused = !!(Shape::IsSimple(Prev)); MultipleShape *Multiple = new MultipleShape(); Notice(Multiple); BlockSet CurrEntries; for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) { Block *CurrEntry = iter->first; BlockSet &CurrBlocks = iter->second; PrintDebug(" multiple group with entry %d:\n", CurrEntry->Id); DebugDump(CurrBlocks, " "); // Create inner block CurrEntries.clear(); CurrEntries.insert(CurrEntry); for (BlockSet::iterator iter = CurrBlocks.begin(); iter != CurrBlocks.end(); iter++) { Block *CurrInner = *iter; // Remove the block from the remaining blocks Blocks.erase(CurrInner); // Find new next entries and fix branches to them for (BlockBranchMap::iterator iter = CurrInner->BranchesOut.begin(); iter != CurrInner->BranchesOut.end();) { Block *CurrTarget = iter->first; BlockBranchMap::iterator Next = iter; Next++; if (!contains(CurrBlocks, CurrTarget)) { NextEntries.insert(CurrTarget); Solipsize(CurrTarget, Branch::Break, Multiple, CurrBlocks); } iter = Next; // increment carefully because Solipsize can remove us } } Multiple->InnerMap[CurrEntry] = Process(CurrBlocks, CurrEntries, NULL); // If we are not fused, then our entries will actually be checked if (!Fused) { CurrEntry->IsCheckedMultipleEntry = true; } } DebugDump(Blocks, " remaining blocks after multiple:"); // Add entries not handled as next entries, they are deferred for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) { Block *Entry = *iter; if (!contains(IndependentGroups, Entry)) { NextEntries.insert(Entry); } } return Multiple; }
Shape *MakeSimple(BlockSet &Blocks, Block *Inner, BlockSet &NextEntries) { PrintDebug("creating simple block with block #%d\n", Inner->Id); SimpleShape *Simple = new SimpleShape; Notice(Simple); Simple->Inner = Inner; Inner->Parent = Simple; if (Blocks.size() > 1) { Blocks.erase(Inner); GetBlocksOut(Inner, NextEntries, &Blocks); BlockSet JustInner; JustInner.insert(Inner); for (BlockSet::iterator iter = NextEntries.begin(); iter != NextEntries.end(); iter++) { Solipsize(*iter, Branch::Direct, Simple, JustInner); } } return Simple; }
ControlFlowGraph::BlockPointerVector ControlFlowGraph::pre_order_sequence() { typedef std::unordered_set<iterator> BlockSet; typedef std::stack<iterator> Stack; BlockSet visited; BlockPointerVector sequence; Stack stack; if (!empty()) { stack.push(get_entry_block()); visited.insert(get_entry_block()); } while (!stack.empty()) { iterator current = stack.top(); stack.pop(); sequence.push_back(current); // favor the fallthrough iterator fallthrough = end(); if (current->has_fallthrough_edge()) { edge_iterator fallthroughEdge = sequence.back()->get_fallthrough_edge(); if (visited.insert(fallthroughEdge->tail).second) { fallthrough = fallthroughEdge->tail; } } for (pointer_iterator block = current->successors.begin(); block != current->successors.end(); ++block) { if (visited.insert(*block).second) { stack.push(*block); } } if (fallthrough != end()) { stack.push(fallthrough); } } return sequence; }
TextAutosizer::Supercluster* TextAutosizer::getSupercluster(const LayoutBlock* block) { Fingerprint fingerprint = m_fingerprintMapper.get(block); if (!fingerprint) return nullptr; BlockSet* roots = m_fingerprintMapper.getTentativeClusterRoots(fingerprint); if (!roots || roots->size() < 2 || !roots->contains(block)) return nullptr; SuperclusterMap::AddResult addResult = m_superclusters.add(fingerprint, PassOwnPtr<Supercluster>()); if (!addResult.isNewEntry) return addResult.storedValue->value.get(); Supercluster* supercluster = new Supercluster(roots); addResult.storedValue->value = adoptPtr(supercluster); return supercluster; }
void StackAllocationPromoter::pruneAllocStackUsage() { DEBUG(llvm::dbgs() << "*** Pruning : " << *ASI); BlockSet Blocks; // Insert all of the blocks that ASI is live in. for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI) Blocks.insert(UI->getUser()->getParent()); // Clear AllocStack state. LastStoreInBlock.clear(); for (auto Block : Blocks) { StoreInst *SI = promoteAllocationInBlock(Block); LastStoreInBlock[Block] = SI; } DEBUG(llvm::dbgs() << "*** Finished pruning : " << *ASI); }
ControlFlowGraph::BlockPointerVector ControlFlowGraph::post_order_sequence() { typedef std::unordered_set<iterator> BlockSet; typedef std::stack<iterator> Stack; report("Creating post order traversal"); BlockSet visited; BlockPointerVector sequence; Stack stack; if (!empty()) { for (pointer_iterator block = get_entry_block()->successors.begin(); block != get_entry_block()->successors.end(); ++block) { if (visited.insert(*block).second) { stack.push(*block); } } } while (!stack.empty()) { iterator current = stack.top(); bool one = false; for (pointer_iterator block = current->successors.begin(); block != current->successors.end(); ++block) { if (visited.insert(*block).second) { stack.push(*block); one = true; } } if(!one) { stack.pop(); sequence.push_back(current); report(" Adding block " << current->label()); } } report(" Adding block " << get_entry_block()->label()); sequence.push_back(get_entry_block()); return sequence; }
void DeadCodeEliminationPass::runOnKernel(ir::IRKernel& k) { report("Running dead code elimination on kernel " << k.name); reportE(REPORT_PTX, k); Analysis* dfgAnalysis = getAnalysis(Analysis::DataflowGraphAnalysis); assert(dfgAnalysis != 0); analysis::DataflowGraph& dfg = *static_cast<analysis::DataflowGraph*>(dfgAnalysis); assert(dfg.ssa() != analysis::DataflowGraph::SsaType::None); BlockSet blocks; report(" Starting by scanning all basic blocks"); for(iterator block = dfg.begin(); block != dfg.end(); ++block) { report(" Queueing up BB_" << block->id()); blocks.insert(block); } while(!blocks.empty()) { iterator block = *blocks.begin(); blocks.erase(blocks.begin()); eliminateDeadInstructions(dfg, blocks, block); } report("Finished running dead code elimination on kernel " << k.name); reportE(REPORT_PTX, k); }
// If a block has multiple entries but no exits, and it is small enough, it is useful to split it. // A common example is a C++ function where everything ends up at a final exit block and does some // RAII cleanup. Without splitting, we will be forced to introduce labelled loops to allow // reaching the final block void SplitDeadEnds() { int TotalCodeSize = 0; for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) { Block *Curr = *iter; TotalCodeSize += strlen(Curr->Code); } for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) { Block *Original = *iter; if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue; if (strlen(Original->Code)*(Original->BranchesIn.size()-1) > TotalCodeSize/5) continue; // if splitting increases raw code size by a significant amount, abort // Split the node (for simplicity, we replace all the blocks, even though we could have reused the original) for (BlockBranchMap::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) { Block *Prior = iter->first; Block *Split = new Block(Original->Code); Split->BranchesIn[Prior] = new Branch(NULL); Prior->BranchesOut[Split] = new Branch(Prior->BranchesOut[Original]->Condition, Prior->BranchesOut[Original]->Code); Prior->BranchesOut.erase(Original); Parent->AddBlock(Split); Live.insert(Split); } } }
static BlockSet getBlocksWithBackwardsBranches(CycleAnalysis* cycleAnalysis) { auto edges = cycleAnalysis->getAllBackEdges(); report(" Getting blocks with backwards branches"); BlockSet backwardsBranchBlocks; for(auto& edge : edges) { if(edge->type != ir::Edge::Branch) continue; auto block = edge->head; if(getBranch(block) == nullptr) continue; backwardsBranchBlocks.insert(block); report(" " << block->label()); } return backwardsBranchBlocks; }
// Converts/processes all branchings to a specific target void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor, BlockSet &From) { PrintDebug("Solipsizing branches into %d\n", Target->Id); DebugDump(From, " relevant to solipsize: "); for (BlockSet::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) { Block *Prior = *iter; if (From.find(Prior) == From.end()) { iter++; continue; } Branch *PriorOut = Prior->BranchesOut[Target]; PriorOut->Ancestor = Ancestor; PriorOut->Type = Type; if (MultipleShape *Multiple = Shape::IsMultiple(Ancestor)) { Multiple->NeedLoop++; // We are breaking out of this Multiple, so need a loop } iter++; // carefully increment iter before erasing Target->BranchesIn.erase(Prior); Target->ProcessedBranchesIn.insert(Prior); Prior->BranchesOut.erase(Target); Prior->ProcessedBranchesOut[Target] = PriorOut; PrintDebug(" eliminated branch from %d\n", Prior->Id); } }
static bool flagHammocksWithSideEffects(SafeRegion& region, const BlockSet& blocksWithSideEffects) { if(region.isLeaf()) { region.doesNotDependOnSideEffects = blocksWithSideEffects.count(region.block) == 0; } else { region.doesNotDependOnSideEffects = true; for(auto& child : region.children) { region.doesNotDependOnSideEffects &= flagHammocksWithSideEffects(child, blocksWithSideEffects); } } return region.doesNotDependOnSideEffects; }
static void propagateMoveSourceToUsersInBlock(instruction_iterator move, instruction_iterator position, block_iterator block, BlockSet& visited) { // early exit for visited blocks if(!visited.insert(block->id()).second) return; assert(move->d.size() == 1); assert(move->s.size() == 1); auto destination = *move->d.front().pointer; auto moveSource = *move->s.front().pointer; // We can skip PHIs because the use of a PHI would make the removal illegal // replace uses in the block for(; position != block->instructions().end(); ++position) { for(auto source = position->s.begin(); source != position->s.end(); ++source) { if(*source->pointer == destination) { *source->pointer = moveSource; } } } // replace in successors for(auto successor = block->successors().begin(); successor != block->successors().end(); ++successor) { if((*successor)->aliveIn().count(destination) == 0) continue; propagateMoveSourceToUsersInBlock(move, (*successor)->instructions().begin(), *successor, visited); } }