//------------------------------getset----------------------------------------- // Get an IndexSet for a block. Return existing one, if any. Make a new // empty one if a prior one does not exist. IndexSet *PhaseLive::getset( Block *p ) { IndexSet *delta = _deltas[p->_pre_order-1]; if( !delta ) // Not on worklist? // Get a free set; flag as being on worklist delta = _deltas[p->_pre_order-1] = getfreeset(); return delta; // Return set of new live-out items }
//------------------------------add_liveout------------------------------------ // Add a vector of live-out values to a given blocks live-out set. void PhaseLive::add_liveout( Block *p, IndexSet *lo, VectorSet &first_pass ) { IndexSet *live = &_live[p->_pre_order-1]; IndexSet *defs = &_defs[p->_pre_order-1]; IndexSet *on_worklist = _deltas[p->_pre_order-1]; IndexSet *delta = on_worklist ? on_worklist : getfreeset(); IndexSetIterator elements(lo); uint r; while ((r = elements.next()) != 0) { if( live->insert(r) && // If actually inserted... !defs->member( r ) ) // and not defined locally delta->insert(r); // Then add to live-in set } if( delta->count() ) { // If actually added things _deltas[p->_pre_order-1] = delta; // Flag as on worklist now if( !on_worklist && // Not on worklist? first_pass.test(p->_pre_order) ) _worklist->push(p); // Actually go on worklist if already 1st pass } else { // Nothing there; just free it delta->set_next(_free_IndexSet); _free_IndexSet = delta; // Drop onto free list } }
void PhaseLive::compute(uint maxlrg) { _maxlrg = maxlrg; _worklist = new (_arena) Block_List(); // Init the sparse live arrays. This data is live on exit from here! // The _live info is the live-out info. _live = (IndexSet*)_arena->Amalloc(sizeof(IndexSet) * _cfg.number_of_blocks()); uint i; for (i = 0; i < _cfg.number_of_blocks(); i++) { _live[i].initialize(_maxlrg); } if (_keep_deltas) { _livein = (IndexSet*)_arena->Amalloc(sizeof(IndexSet) * _cfg.number_of_blocks()); for (i = 0; i < _cfg.number_of_blocks(); i++) { _livein[i].initialize(_maxlrg); } } // Init the sparse arrays for delta-sets. ResourceMark rm; // Nuke temp storage on exit // Does the memory used by _defs and _deltas get reclaimed? Does it matter? TT // Array of values defined locally in blocks _defs = NEW_RESOURCE_ARRAY(IndexSet,_cfg.number_of_blocks()); for (i = 0; i < _cfg.number_of_blocks(); i++) { _defs[i].initialize(_maxlrg); } // Array of delta-set pointers, indexed by block pre_order-1. _deltas = NEW_RESOURCE_ARRAY(IndexSet*,_cfg.number_of_blocks()); memset( _deltas, 0, sizeof(IndexSet*)* _cfg.number_of_blocks()); _free_IndexSet = NULL; // Blocks having done pass-1 VectorSet first_pass(Thread::current()->resource_area()); // Outer loop: must compute local live-in sets and push into predecessors. for (uint j = _cfg.number_of_blocks(); j > 0; j--) { Block* block = _cfg.get_block(j - 1); // Compute the local live-in set. Start with any new live-out bits. IndexSet* use = getset(block); IndexSet* def = &_defs[block->_pre_order-1]; DEBUG_ONLY(IndexSet *def_outside = getfreeset();) uint i; for (i = block->number_of_nodes(); i > 1; i--) { Node* n = block->get_node(i-1); if (n->is_Phi()) { break; } uint r = _names.at(n->_idx); assert(!def_outside->member(r), "Use of external LRG overlaps the same LRG defined in this block"); def->insert( r ); use->remove( r ); uint cnt = n->req(); for (uint k = 1; k < cnt; k++) { Node *nk = n->in(k); uint nkidx = nk->_idx; if (_cfg.get_block_for_node(nk) != block) { uint u = _names.at(nkidx); use->insert(u); DEBUG_ONLY(def_outside->insert(u);) } } }