BlockBegin* LoopFinder::insert_caching_block(LoopList* loops, BlockBegin* from, BlockBegin* to) {
  if (from->next() && from->next()->as_CachingChange() != NULL &&
      from->end()->default_sux() == to) {
    // we already have a caching change block
    // check that the precision flags are the same
#ifdef ASSERT
    CachingChange* cc = from->next()->as_CachingChange();
    assert(cc->pred_block()->is_set(BlockBegin::single_precision_flag) == from->is_set(BlockBegin::single_precision_flag), "consistency check");
    assert(cc->sux_block()->is_set(BlockBegin::single_precision_flag) == to->is_set(BlockBegin::single_precision_flag), "consistency check");
#endif
    return NULL;
  } else {
    // insert a caching change block, making it close to any single successor
    int bci = -1;
    BlockLoopInfo* bli = get_block_info(to);
    if (bli->nof_preds() == 1) {
      bci = to->bci();
    } else {
      bci = from->end()->bci();
    }
    BlockBegin* cc = new_block(to->scope(), bci);
    BlockEnd* e = new Goto(to, false);
    cc->set_end(e);
    cc->set_next(new CachingChange(from, to), bci)->set_next(e, bci);
    if (PrintLoops && Verbose) {
      tty->print_cr("Added caching block B%d (dest B%d)", cc->block_id(), to->block_id());
    }
    BlockEnd* from_end = from->end();
    from_end->substitute_sux(to, cc);
    cc->join(from_end->state());
    assert(cc->state() != NULL, "illegal operation");

    ValueStack* end_state = cc->state()->copy();
    cc->end()->set_state(end_state);
    to->join(end_state);

    assert(cc->end()->state() != NULL, "should have state");

    loops->update_loops(from, to, cc);
    return cc;
  }
}
// Gather backedges of natural loops: an edge a -> b where b dominates a
LoopList* LoopFinder::find_backedges(boolArray* visited) {
  int i;
  LoopList* backedges = new LoopList();
  for (i = 0; i < max_blocks(); i++) {
    if (visited->at(i)) {
      BlockLoopInfo* bli = _info->at(i);
      BlockBegin*    bb  = bli->block();
      BlockEnd*      be  = bb->end();
      int n = be->number_of_sux();
      for (int i = 0; i < n; i++) {
        BlockBegin* sux = be->sux_at(i);
        if (bli->is_dom_block(sux->block_id())) {
          bli->mark_backedge_start();
          backedges->push(new Loop(sux, bb));
        }
      }
    }
  }

  // backedges contains single pairs of blocks which are a backedge.
  // some of these loops may share entry points, so walk over the backedges
  // and merge loops which have the same entry point
  if (backedges->length() > 1) {
    backedges->sort(sort_by_start_block);
    Loop* current_loop = backedges->at(0);
    for (i = 1; i < backedges->length();) {
      Loop* this_loop = backedges->at(i);
      if (current_loop->start() == this_loop->start()) {
        // same entry point
        assert(this_loop->ends()->length() == 1, "should only have one end at this point");
#ifndef PRODUCT
        if (PrintLoops && Verbose) {
          tty->print_cr("Merging loops with same start");
          current_loop->print();
          this_loop->print();
        }
#endif
        BlockBegin* e = this_loop->ends()->at(0);
        current_loop->add_end(e);
        backedges->remove(this_loop);
      } else {
        // start processing the next loop entry point
        i++;
      }
    }
  }

  return backedges;
}
 BlockListScanInfo(BlockList* blocks) : _info(new RegisterManager()), _had_call(false) {
   for (int n = 0; n < blocks->length(); n++) {
     BlockBegin* b = blocks->at(n);
     if (b->lir() != NULL) {
       traverse(b, b->lir()->instructions_list());
     }
     // Registers may be used to hold the value
     // on the top of stack so check for that.
     check_stack(b->state());
     check_stack(b->end()->state());
   }
   if (_had_call) {
     for (int i = 0; i < FrameMap::nof_caller_save_cpu_regs; i++) {
       _info->lock(FrameMap::caller_save_cpu_reg_at(i)->as_rinfo());
     }
   }
 }
Exemple #4
0
void FpuStackAllocator::allocate() {
  int num_blocks = allocator()->block_count();
  for (int i = 0; i < num_blocks; i++) {
    // Set up to process block
    BlockBegin* block = allocator()->block_at(i);
    intArray* fpu_stack_state = block->fpu_stack_state();

#ifndef PRODUCT
    if (TraceFPUStack) {
      tty->cr();
      tty->print_cr("------- Begin of new Block %d -------", block->block_id());
    }
#endif

    assert(fpu_stack_state != NULL ||
           block->end()->as_Base() != NULL ||
           block->is_set(BlockBegin::exception_entry_flag),
           "FPU stack state must be present due to linear-scan order for FPU stack allocation");
    // note: exception handler entries always start with an empty fpu stack
    //       because stack merging would be too complicated

    if (fpu_stack_state != NULL) {
      sim()->read_state(fpu_stack_state);
    } else {
      sim()->clear();
    }

#ifndef PRODUCT
    if (TraceFPUStack) {
      tty->print("Reading FPU state for block %d:", block->block_id());
      sim()->print();
      tty->cr();
    }
#endif

    allocate_block(block);
    CHECK_BAILOUT();
  }
}