Esempio n. 1
0
void LoopInvariantCodeMotion::process_block(BlockBegin* block) {
  TRACE_VALUE_NUMBERING(tty->print_cr("processing block B%d", block->block_id()));

  Instruction* prev = block;
  Instruction* cur = block->next();

  while (cur != NULL) {

    // determine if cur instruction is loop invariant
    // only selected instruction types are processed here
    bool cur_invariant = false;

    if (cur->as_Constant() != NULL) {
      cur_invariant = !cur->can_trap();
    } else if (cur->as_ArithmeticOp() != NULL || cur->as_LogicOp() != NULL || cur->as_ShiftOp() != NULL) {
      assert(cur->as_Op2() != NULL, "must be Op2");
      Op2* op2 = (Op2*)cur;
      cur_invariant = !op2->can_trap() && is_invariant(op2->x()) && is_invariant(op2->y());
    } else if (cur->as_LoadField() != NULL) {
      LoadField* lf = (LoadField*)cur;
      // deoptimizes on NullPointerException
      cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()) && _insert_is_pred;
    } else if (cur->as_ArrayLength() != NULL) {
      ArrayLength *length = cur->as_ArrayLength();
      cur_invariant = is_invariant(length->array());
    } else if (cur->as_LoadIndexed() != NULL) {
      LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed();
      cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()) && _insert_is_pred;
    }

    if (cur_invariant) {
      // perform value numbering and mark instruction as loop-invariant
      _gvn->substitute(cur);

      if (cur->as_Constant() == NULL) {
        // ensure that code for non-constant instructions is always generated
        cur->pin();
      }

      // remove cur instruction from loop block and append it to block before loop
      Instruction* next = cur->next();
      Instruction* in = _insertion_point->next();
      _insertion_point = _insertion_point->set_next(cur);
      cur->set_next(in);

      //  Deoptimize on exception
      cur->set_flag(Instruction::DeoptimizeOnException, true);

      //  Clear exception handlers
      cur->set_exception_handlers(NULL);

      TRACE_VALUE_NUMBERING(tty->print_cr("Instruction %c%d is loop invariant", cur->type()->tchar(), cur->id()));

      if (cur->state_before() != NULL) {
        cur->set_state_before(_state->copy());
      }
      if (cur->exception_state() != NULL) {
        cur->set_exception_state(_state->copy());
      }

      cur = prev->set_next(next);

    } else {
      prev = cur;
      cur = cur->next();
    }
  }
}