Example #1
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;
}
Example #2
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));
    }
  }
}
Example #3
0
GlobalValueNumbering::GlobalValueNumbering(IR* ir)
  : _current_map(NULL)
  , _value_maps(ir->linear_scan_order()->length(), NULL)
  , _compilation(ir->compilation())
{
  TRACE_VALUE_NUMBERING(tty->print_cr("****** start of global value numbering"));

  ShortLoopOptimizer short_loop_optimizer(this);

  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");

  // method parameters are not linked in instructions list, so process them separateley
  for_each_state_value(start_block->state(), value,
     assert(value->as_Local() != NULL, "only method parameters allowed");
     set_processed(value);
  );
Example #4
0
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());
}