BlockBegin* LIR_OopMapGenerator::work_list_dequeue() {
  if (_work_list.is_empty()) {
    return NULL;
  }
  BlockBegin* b = _work_list.pop();
  b->set_enqueued_for_oop_map_gen(false);
  return b;
}
BlockBegin* LoopFinder::new_block(IRScope* scope, int bci) {
  BlockBegin* b = new BlockBegin(bci);
  _valid_doms = false;
  assert(b->block_id() == max_blocks(), "illegal block_id");
  _max_blocks++;
  BlockLoopInfo* bli = new BlockLoopInfo(b, max_blocks());
  _info->append(bli);
  assert(_info->length() == max_blocks(), "operation failed");
  return b;
}
 void block_do(BlockBegin* from) {
   int n = from->end()->number_of_sux();
   int tag = _tags->at(from->block_id());
   for (int i = 0; i < n; i++) {
     BlockBegin* to = from->end()->sux_at(i);
     if (tag != _tags->at(to->block_id())) {
       // this edge is a transition between two different
       // caching regions, so we need to insert a CachingChange
       _pairs->append(new BlockPair(from, to));
     }
   }
 }
void LoopFinder::find_loop_exits(BlockBegin* bb, Loop* loop) {
  BlockLoopInfo* bli = get_block_info(bb);
  int loop_index = bb->loop_index();
  // search all successors and locate the ones that do not have the same loop_index
  BlockEnd* be = bb->end();
  int n = be->number_of_sux() - 1;
  for(; n >= 0; n--) {
    BlockBegin* sux = be->sux_at(n);
    BlockLoopInfo* sux_bli = get_block_info(sux);
    if (sux->loop_index() != loop_index) {
      loop->append_loop_exit(bb, sux);
    }
  }
}
// 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;
}
Exemple #6
0
  void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) {
    int e = sux->number_of_exception_handlers();
    for (int i = 0; i < e; i++) {
      BlockBegin* xhandler = sux->exception_handler_at(i);
      block->add_exception_handler(xhandler);

      assert(xhandler->is_predecessor(sux), "missing predecessor");
      if (sux->number_of_preds() == 0) {
        // sux is disconnected from graph so disconnect from exception handlers
        xhandler->remove_predecessor(sux);
      }
      if (!xhandler->is_predecessor(block)) {
        xhandler->add_predecessor(block);
      }
    }
  }
 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 #8
0
bool ShortLoopOptimizer::process(BlockBegin* loop_header) {
  TRACE_VALUE_NUMBERING(tty->print_cr("** loop header block"));

  _too_complicated_loop = false;
  _loop_blocks.clear();
  _loop_blocks.append(loop_header);

  for (int i = 0; i < _loop_blocks.length(); i++) {
    BlockBegin* block = _loop_blocks.at(i);
    TRACE_VALUE_NUMBERING(tty->print_cr("processing loop block B%d", block->block_id()));

    if (block->is_set(BlockBegin::exception_entry_flag)) {
      // this would be too complicated
      return false;
    }

    // add predecessors to worklist
    for (int j = block->number_of_preds() - 1; j >= 0; j--) {
      BlockBegin* pred = block->pred_at(j);

      if (pred->is_set(BlockBegin::osr_entry_flag)) {
        return false;
      }

      ValueMap* pred_map = value_map_of(pred);
      if (pred_map != NULL) {
        current_map()->kill_map(pred_map);
      } else if (!_loop_blocks.contains(pred)) {
        if (_loop_blocks.length() >= ValueMapMaxLoopSize) {
          return false;
        }
        _loop_blocks.append(pred);
      }
    }

    // use the instruction visitor for killing values
    for (Value instr = block->next(); instr != NULL; instr = instr->next()) {
      instr->visit(this);
      if (_too_complicated_loop) {
        return false;
      }
    }
  }

  bool optimistic = this->_gvn->compilation()->is_optimistic();

  if (UseLoopInvariantCodeMotion && optimistic) {
    LoopInvariantCodeMotion code_motion(this, _gvn, loop_header, &_loop_blocks);
  }

  TRACE_VALUE_NUMBERING(tty->print_cr("** loop successfully optimized"));
  return true;
}
void LoopFinder::compute_loop_exits_and_entries(LoopList* loops) {
  // create loop exits for each loop
  int loop_index = loops->length() - 1;
  for (; loop_index >= 0; loop_index--) {
    Loop* loop = loops->at(loop_index);
    int n = loop->nof_blocks() - 1;
    // mark all nodes belonging to this loop 
    for (; n >= 0; n --) {
      BlockBegin* bb = loop->block_no(n);
      bb->set_loop_index(loop_index);
    }
    find_loop_entries(loop->start(), loop);
    // search for blocks that have successors outside the loop
    n = loop->nof_blocks() - 1;
    for (; n >= 0; n--) {
      BlockBegin* bb = loop->block_no(n);
      find_loop_exits(bb, loop);
    }
  }
}
Exemple #10
0
void LoopFinder::gather_loop_blocks(LoopList* loops) {
  int lng = loops->length();
  BitMap blocks_in_loop(max_blocks());
  for (int i = 0; i < lng; i++) {
    // for each loop do the following
    blocks_in_loop.clear();
    Loop* loop = loops->at(i);
    BlockList* ends = loop->ends();
    if (!loop->is_end(loop->start())) {
      GrowableArray<BlockBegin*>* stack = new GrowableArray<BlockBegin*>();
      blocks_in_loop.at_put(loop->start()->block_id(), true);
      
      // insert all the ends into the list
      for (int i = 0; i < ends->length(); i++) {
        blocks_in_loop.at_put(ends->at(i)->block_id()  , true);
        stack->push(ends->at(i));
      }
      
      while (!stack->is_empty()) {
        BlockBegin* bb = stack->pop();
        BlockLoopInfo* bli = get_block_info(bb);
        // push all predecessors that are not yet in loop
        int npreds = bli->nof_preds();
        for (int m = 0; m < npreds; m++) {
          BlockBegin* pred = bli->pred_no(m);
          if (!blocks_in_loop.at(pred->block_id())) {
            blocks_in_loop.at_put(pred->block_id(), true);
            loop->append_node(pred);
            stack->push(pred);
          }
        }
      }
      loop->append_node(loop->start());
    }
    // insert all the ends into the loop
    for (int i = 0; i < ends->length(); i++) {
      loop->append_node(ends->at(i));
    }
  }
}
void LIR_OopMapGenerator::generate() {
  // Initialize by iterating down the method's signature and marking
  // oop locals in the state

  assert((int) oop_map()->size() == frame_map()->num_local_names(), "just checking");
  oop_map()->clear();
  ciSignature* sig = ir()->method()->signature();
  int idx = 0;
  // Handle receiver for non-static methods
  if (!ir()->method()->is_static()) {
    mark(frame_map()->name_for_argument(idx));
    ++idx;
  }
  for (int i = 0; i < sig->count(); i++) {
    ciType* type = sig->type_at(i);
    if (!type->is_primitive_type()) {
      mark(frame_map()->name_for_argument(idx));
    }
    idx += type->size();
  }

  // The start block contains a Base instruction, which causes the LIR
  // for ref-uninit conflicts to be generated. We need to handle this
  // block specially so we don't traverse its "osr_entry" successor,
  // because we don't know how to set up the state appropriately for
  // that entry point.
  _base = ir()->start()->end()->as_Base();

  // Always start iterating at the start (even for OSR compiles)
  merge_state(ir()->start());
  
  BlockBegin* block = work_list_dequeue();
  while (block != NULL) {
    oop_map()->set_from(*block->lir_oop_map());
    iterate_one(block);
    block = work_list_dequeue();
  }
}
Exemple #12
0
// Compute dominators for bb and 
// walk the successors of bb in depth first order
void LoopFinder::dominator_walk_sux(BlockBegin* bb, boolArray* visited) {
  // we may not visit a block that is jsr-target
  if (bb->is_set(BlockBegin::subroutine_entry_flag)) set_not_ok();
  BlockEnd*      be  = bb->end();
  BlockLoopInfo* bli = get_block_info(bb);
  visited->at_put(bb->block_id(), true);

  // compute new dominators using predecessors
  BitMap map(max_blocks());
  map.set_from(*BlockLoopInfo::all_blocks_map());
  { // Compute dominators for myself (looking at predecessors)
    int nof_preds = bli->nof_preds();
    for (int i = 0; i < nof_preds; i++) {
      BlockBegin* pred     = bli->pred_no(i);
      BitMap      pred_map = get_block_info(pred)->doms_map();
      map.set_intersection(pred_map);
    }
    // add itself
    map.at_put(bb->block_id(), true);
    
    // if the computed dominators differ from the one stored,
    // then we need another iteration
    BitMap bb_map = bli->doms_map();
    if (!bb_map.is_same(map)) {
      set_changed(true);
      bb_map.set_from(map);
    }
  }
  { // Visit all successors
    int n = be->number_of_sux();
    for (int i = 0; i < n; i++) {
      BlockBegin* sux = be->sux_at(i);
      if (!visited->at(sux->block_id())) {
        dominator_walk_sux(sux, visited);
      }
    }
  }
}
Exemple #13
0
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;
  }
}
Exemple #14
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();
  }
}
void LIR_LocalCaching::cache_locals() {
  LoopList* loops = ir()->loops();
  BlockList* all_blocks = ir()->code();
  WordSizeList* local_name_to_offset_map = ir()->local_name_to_offset_map();

  if (loops == NULL) {
    // collect global scan information
    BlockListScanInfo gsi(ir()->code());
    RegisterManager* global_scan_info = gsi.info();

    // just cache registers globally.
    LocalMappingSetter setter(cache_locals_for_blocks(all_blocks, global_scan_info));
    all_blocks->iterate_forward(&setter);
  } else {
    assert(loops->length() != 0, "should be at least one loop");
    int i;

    // collect all the blocks that are outside of the loops
    BlockList* non_loop_blocks = new BlockList;
    for (i = 0; i < all_blocks->length(); i++) {
      BlockBegin* b = all_blocks->at(i);
      if (b->loop_index() == -1 && b->next()->as_CachingChange() == NULL) {
        non_loop_blocks->append(b);
      }
    }

    RegisterManager* global_scan_info = new RegisterManager();

    // scan each of the loops and the remaining blocks recording register usage
    // so we know what registers are free.
    RegisterManagerArray scan_infos(loops->length() + 1);
    for (i = 0; i < loops->length(); i++) {
      Loop* loop = loops->at(i);

      BlockListScanInfo lsi(loop->blocks());
      scan_infos.at_put(i, lsi.info());
      // accumulate the global state
      global_scan_info->merge(lsi.info());
    }

    BlockListScanInfo lsi(non_loop_blocks);
    scan_infos.at_put(loops->length(), lsi.info());
    // accumulate the global state
    global_scan_info->merge(lsi.info());
    
    // use the global mapping as a guide in the rest of the register selection process.
    LocalMapping* global = cache_locals_for_blocks(all_blocks, global_scan_info, true);
    LocalMapping* pref = new LocalMapping(local_name_to_offset_map);
    pref->merge(global);
    pref->merge(_preferred);
    _preferred = pref;

    for (i = 0; i < loops->length(); i++) {
      if (i < LIRCacheLoopStart || (uint)i >= (uint)LIRCacheLoopStop) {
        continue;
      }

      Loop* loop = loops->at(i);

      LocalMapping* mapping = cache_locals_for_blocks(loop->blocks(), scan_infos.at(i));
      LocalMappingSetter setter(mapping);
      loop->blocks()->iterate_forward(&setter);
      _preferred->merge(mapping);
      mapping->join(global);
    }

    LocalMapping* mapping = cache_locals_for_blocks(non_loop_blocks, scan_infos.at(loops->length()));
    mapping->join(global);
    LocalMappingSetter setter(mapping);
    non_loop_blocks->iterate_forward(&setter);
  }
}
GlobalValueNumbering::GlobalValueNumbering(IR* ir)
    : _current_map(NULL)
    , _value_maps(ir->linear_scan_order()->length(), NULL)
{
    TRACE_VALUE_NUMBERING(tty->print_cr("****** start of global value numbering"));

    ShortLoopOptimizer short_loop_optimizer(this);
    int subst_count = 0;

    BlockList* blocks = ir->linear_scan_order();
    int num_blocks = blocks->length();

    BlockBegin* start_block = blocks->at(0);
    assert(start_block == ir->start() && start_block->number_of_preds() == 0 && start_block->dominator() == NULL, "must be start block");
    assert(start_block->next()->as_Base() != NULL && start_block->next()->next() == NULL, "start block must not have instructions");

    // initial, empty value map with nesting 0
    set_value_map_of(start_block, new ValueMap());

    for (int i = 1; i < num_blocks; i++) {
        BlockBegin* block = blocks->at(i);
        TRACE_VALUE_NUMBERING(tty->print_cr("**** processing block B%d", block->block_id()));

        int num_preds = block->number_of_preds();
        assert(num_preds > 0, "block must have predecessors");

        BlockBegin* dominator = block->dominator();
        assert(dominator != NULL, "dominator must exist");
        assert(value_map_of(dominator) != NULL, "value map of dominator must exist");

        // create new value map with increased nesting
        _current_map = new ValueMap(value_map_of(dominator));

        if (num_preds == 1) {
            assert(dominator == block->pred_at(0), "dominator must be equal to predecessor");
            // nothing to do here

        } else if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
            // block has incoming backward branches -> try to optimize short loops
            if (!short_loop_optimizer.process(block)) {
                // loop is too complicated, so kill all memory loads because there might be
                // stores to them in the loop
                current_map()->kill_memory();
            }

        } else {
            // only incoming forward branches that are already processed
            for (int j = 0; j < num_preds; j++) {
                BlockBegin* pred = block->pred_at(j);
                ValueMap* pred_map = value_map_of(pred);

                if (pred_map != NULL) {
                    // propagate killed values of the predecessor to this block
                    current_map()->kill_map(value_map_of(pred));
                } else {
                    // kill all memory loads because predecessor not yet processed
                    // (this can happen with non-natural loops and OSR-compiles)
                    current_map()->kill_memory();
                }
            }
        }

        if (block->is_set(BlockBegin::exception_entry_flag)) {
            current_map()->kill_exception();
        }

        TRACE_VALUE_NUMBERING(tty->print("value map before processing block: "); current_map()->print());

        // visit all instructions of this block
        for (Value instr = block->next(); instr != NULL; instr = instr->next()) {
            assert(!instr->has_subst(), "substitution already set");

            // check if instruction kills any values
            instr->visit(this);

            if (instr->hash() != 0) {
                Value f = current_map()->find_insert(instr);
                if (f != instr) {
                    assert(!f->has_subst(), "can't have a substitution");
                    instr->set_subst(f);
                    subst_count++;
                }
            }
        }

        // remember value map for successors
        set_value_map_of(block, current_map());
    }

    if (subst_count != 0) {
        SubstitutionResolver resolver(ir);
    }

    TRACE_VALUE_NUMBERING(tty->print("****** end of global value numbering. "); ValueMap::print_statistics());
}
Exemple #17
0
void LinearScan::allocate_fpu_stack() {
  // First compute which FPU registers are live at the start of each basic block
  // (To minimize the amount of work we have to do if we have to merge FPU stacks)
  if (ComputeExactFPURegisterUsage) {
    Interval* intervals_in_register, *intervals_in_memory;
    create_unhandled_lists(&intervals_in_register, &intervals_in_memory, is_in_fpu_register, NULL);

    // ignore memory intervals by overwriting intervals_in_memory
    // the dummy interval is needed to enforce the walker to walk until the given id:
    // without it, the walker stops when the unhandled-list is empty -> live information
    // beyond this point would be incorrect.
    Interval* dummy_interval = new Interval(any_reg);
    dummy_interval->add_range(max_jint - 2, max_jint - 1);
    dummy_interval->set_next(Interval::end());
    intervals_in_memory = dummy_interval;

    IntervalWalker iw(this, intervals_in_register, intervals_in_memory);

    const int num_blocks = block_count();
    for (int i = 0; i < num_blocks; i++) {
      BlockBegin* b = block_at(i);

      // register usage is only needed for merging stacks -> compute only
      // when more than one predecessor.
      // the block must not have any spill moves at the beginning (checked by assertions)
      // spill moves would use intervals that are marked as handled and so the usage bit
      // would been set incorrectly

      // NOTE: the check for number_of_preds > 1 is necessary. A block with only one
      //       predecessor may have spill moves at the begin of the block.
      //       If an interval ends at the current instruction id, it is not possible
      //       to decide if the register is live or not at the block begin -> the
      //       register information would be incorrect.
      if (b->number_of_preds() > 1) {
        int id = b->first_lir_instruction_id();
        ResourceBitMap regs(FrameMap::nof_fpu_regs);

        iw.walk_to(id);   // walk after the first instruction (always a label) of the block
        assert(iw.current_position() == id, "did not walk completely to id");

        // Only consider FPU values in registers
        Interval* interval = iw.active_first(fixedKind);
        while (interval != Interval::end()) {
          int reg = interval->assigned_reg();
          assert(reg >= pd_first_fpu_reg && reg <= pd_last_fpu_reg, "no fpu register");
          assert(interval->assigned_regHi() == -1, "must not have hi register (doubles stored in one register)");
          assert(interval->from() <= id && id < interval->to(), "interval out of range");

#ifndef PRODUCT
          if (TraceFPURegisterUsage) {
            tty->print("fpu reg %d is live because of ", reg - pd_first_fpu_reg); interval->print();
          }
#endif

          regs.set_bit(reg - pd_first_fpu_reg);
          interval = interval->next();
        }

        b->set_fpu_register_usage(regs);

#ifndef PRODUCT
        if (TraceFPURegisterUsage) {
          tty->print("FPU regs for block %d, LIR instr %d): ", b->block_id(), id); regs.print_on(tty); tty->cr();
        }
#endif
      }
    }
  }

  FpuStackAllocator alloc(ir()->compilation(), this);
  _fpu_stack_allocator = &alloc;
  alloc.allocate();
  _fpu_stack_allocator = NULL;
}
Exemple #18
0
void LoopFinder::compute_dominators(boolArray* visited) {
  // set up a bitmap that contains all blocks
  BitMap all_map(max_blocks());
  all_map.clear();
  for (int i = 0; i < max_blocks(); i++) all_map.at_put(i, true);
  BlockLoopInfo::set_all_blocks_map(&all_map);
  { // initialize block loop info and set all predecessors
    CreateInfoClosure c(this);
    ir()->iterate_preorder(&c);
    SetPredsClosure s(this);
    ir()->iterate_preorder(&s);
  }
  { // compute dominators
    // init dominators
    // set entry block (only one exists) and its dominators
    BlockBegin* root_bb = ir()->start();
    assert(!root_bb->is_set(BlockBegin::subroutine_entry_flag), "root may not be jsr target");

    { // initialize root dominators (only itself)
      BitMap root_doms(max_blocks());
      root_doms.clear();
      root_doms.at_put(root_bb->block_id(), true);
      BlockLoopInfo* bli = get_block_info(root_bb);
      bli->doms_map().set_from(root_doms);
    }

    // iterate until either iter_count exceeds or dominators stable
    int iter_count = 0;
    do {
      iter_count++;
      visited->at_put(root_bb->block_id(), true);
      set_changed(false);
      BlockEnd* be = root_bb->end();
      int n = be->number_of_sux();
      for (int i = 0; i < n; i++) {
        BlockBegin* sux = be->sux_at(i);
        if (!visited->at(sux->block_id())) {
          dominator_walk_sux(sux, visited);
        }
      }
      if (changed()) {
        for (int i = visited->length() - 1; i >= 0; i--) {
          visited->at_put(i, false);
        }
      }
    } while (changed() && iter_count <= max_nof_dom_iterations);
    if (iter_count == max_nof_dom_iterations) {
      if (PrintLoops) {
        tty->print_cr("could not computer dominators");
      }
      set_not_ok();
    }

    // if (PrintLoops) {
    //   tty->print_cr("  Dominators: %d iterations", iter_count);
    //   PrintBlockDominators p(this);
    //   ir()->iterate_topological(&p);
    // }
  }  
  BlockLoopInfo::set_all_blocks_map(NULL);


  // go through all blocks; if a block has not been analyzed, then check its
  // predecessors and successors: all must be also un-analyzed;
  // Note: the block may not be JSR blocks
  if (ok()) {
    _valid_doms = true;
#ifdef ASSERT
    CheckDomClosure cc(visited);
    ir()->iterate_preorder(&cc);
#endif
  }

}
Exemple #19
0
void CE_Eliminator::block_do(BlockBegin* block) {
  // 1) find conditional expression
  // check if block ends with an If
  If* if_ = block->end()->as_If();
  if (if_ == NULL) return;

  // check if If works on int or object types
  // (we cannot handle If's working on long, float or doubles yet,
  // since IfOp doesn't support them - these If's show up if cmp
  // operations followed by If's are eliminated)
  ValueType* if_type = if_->x()->type();
  if (!if_type->is_int() && !if_type->is_object()) return;

  BlockBegin* t_block = if_->tsux();
  BlockBegin* f_block = if_->fsux();
  Instruction* t_cur = t_block->next();
  Instruction* f_cur = f_block->next();

  // one Constant may be present between BlockBegin and BlockEnd
  Value t_const = NULL;
  Value f_const = NULL;
  if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) {
    t_const = t_cur;
    t_cur = t_cur->next();
  }
  if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) {
    f_const = f_cur;
    f_cur = f_cur->next();
  }

  // check if both branches end with a goto
  Goto* t_goto = t_cur->as_Goto();
  if (t_goto == NULL) return;
  Goto* f_goto = f_cur->as_Goto();
  if (f_goto == NULL) return;

  // check if both gotos merge into the same block
  BlockBegin* sux = t_goto->default_sux();
  if (sux != f_goto->default_sux()) return;

  // check if at least one word was pushed on sux_state
  // inlining depths must match
  ValueStack* if_state = if_->state();
  ValueStack* sux_state = sux->state();
  if (if_state->scope()->level() > sux_state->scope()->level()) {
    while (sux_state->scope() != if_state->scope()) {
      if_state = if_state->caller_state();
      assert(if_state != NULL, "states do not match up");
    }
  } else if (if_state->scope()->level() < sux_state->scope()->level()) {
    while (sux_state->scope() != if_state->scope()) {
      sux_state = sux_state->caller_state();
      assert(sux_state != NULL, "states do not match up");
    }
  }

  if (sux_state->stack_size() <= if_state->stack_size()) return;

  // check if phi function is present at end of successor stack and that
  // only this phi was pushed on the stack
  Value sux_phi = sux_state->stack_at(if_state->stack_size());
  if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return;
  if (sux_phi->type()->size() != sux_state->stack_size() - if_state->stack_size()) return;

  // get the values that were pushed in the true- and false-branch
  Value t_value = t_goto->state()->stack_at(if_state->stack_size());
  Value f_value = f_goto->state()->stack_at(if_state->stack_size());

  // backend does not support floats
  assert(t_value->type()->base() == f_value->type()->base(), "incompatible types");
  if (t_value->type()->is_float_kind()) return;

  // check that successor has no other phi functions but sux_phi
  // this can happen when t_block or f_block contained additonal stores to local variables
  // that are no longer represented by explicit instructions
  for_each_phi_fun(sux, phi,
                   if (phi != sux_phi) return;
                   );
Exemple #20
0
bool FpuStackAllocator::merge_fpu_stack_with_successors(BlockBegin* block) {
#ifndef PRODUCT
  if (TraceFPUStack) {
    tty->print_cr("Propagating FPU stack state for B%d at LIR_Op position %d to successors:",
                  block->block_id(), pos());
    sim()->print();
    tty->cr();
  }
#endif

  bool changed = false;
  int number_of_sux = block->number_of_sux();

  if (number_of_sux == 1 && block->sux_at(0)->number_of_preds() > 1) {
    // The successor has at least two incoming edges, so a stack merge will be necessary
    // If this block is the first predecessor, cleanup the current stack and propagate it
    // If this block is not the first predecessor, a stack merge will be necessary

    BlockBegin* sux = block->sux_at(0);
    intArray* state = sux->fpu_stack_state();
    LIR_List* instrs = new LIR_List(_compilation);

    if (state != NULL) {
      // Merge with a successors that already has a FPU stack state
      // the block must only have one successor because critical edges must been split
      FpuStackSim* cur_sim = sim();
      FpuStackSim* sux_sim = temp_sim();
      sux_sim->read_state(state);

      merge_fpu_stack(instrs, cur_sim, sux_sim);

    } else {
      // propagate current FPU stack state to successor without state
      // clean up stack first so that there are no dead values on the stack
      if (ComputeExactFPURegisterUsage) {
        FpuStackSim* cur_sim = sim();
        ResourceBitMap live_fpu_regs = block->sux_at(0)->fpu_register_usage();
        assert(live_fpu_regs.size() == FrameMap::nof_fpu_regs, "missing register usage");

        merge_cleanup_fpu_stack(instrs, cur_sim, live_fpu_regs);
      }

      intArray* state = sim()->write_state();
      if (TraceFPUStack) {
        tty->print_cr("Setting FPU stack state of B%d (merge path)", sux->block_id());
        sim()->print(); tty->cr();
      }
      sux->set_fpu_stack_state(state);
    }

    if (instrs->instructions_list()->length() > 0) {
      lir()->insert_before(pos(), instrs);
      set_pos(instrs->instructions_list()->length() + pos());
      changed = true;
    }

  } else {
    // Propagate unmodified Stack to successors where a stack merge is not necessary
    intArray* state = sim()->write_state();
    for (int i = 0; i < number_of_sux; i++) {
      BlockBegin* sux = block->sux_at(i);

#ifdef ASSERT
      for (int j = 0; j < sux->number_of_preds(); j++) {
        assert(block == sux->pred_at(j), "all critical edges must be broken");
      }

      // check if new state is same
      if (sux->fpu_stack_state() != NULL) {
        intArray* sux_state = sux->fpu_stack_state();
        assert(state->length() == sux_state->length(), "overwriting existing stack state");
        for (int j = 0; j < state->length(); j++) {
          assert(state->at(j) == sux_state->at(j), "overwriting existing stack state");
        }
      }
#endif
#ifndef PRODUCT
      if (TraceFPUStack) {
        tty->print_cr("Setting FPU stack state of B%d", sux->block_id());
        sim()->print(); tty->cr();
      }
#endif

      sux->set_fpu_stack_state(state);
    }
  }

#ifndef PRODUCT
  // assertions that FPU stack state conforms to all successors' states
  intArray* cur_state = sim()->write_state();
  for (int i = 0; i < number_of_sux; i++) {
    BlockBegin* sux = block->sux_at(i);
    intArray* sux_state = sux->fpu_stack_state();

    assert(sux_state != NULL, "no fpu state");
    assert(cur_state->length() == sux_state->length(), "incorrect length");
    for (int i = 0; i < cur_state->length(); i++) {
      assert(cur_state->at(i) == sux_state->at(i), "element not equal");
    }
  }
#endif

  return changed;
}