void LIR_OpVisitState::visit()

in src/hotspot/share/c1/c1_LIR.cpp [399:899]


void LIR_OpVisitState::visit(LIR_Op* op) {
  // copy information from the LIR_Op
  reset();
  set_op(op);

  switch (op->code()) {

// LIR_Op0
    case lir_breakpoint:               // result and info always invalid
    case lir_membar:                   // result and info always invalid
    case lir_membar_acquire:           // result and info always invalid
    case lir_membar_release:           // result and info always invalid
    case lir_membar_loadload:          // result and info always invalid
    case lir_membar_storestore:        // result and info always invalid
    case lir_membar_loadstore:         // result and info always invalid
    case lir_membar_storeload:         // result and info always invalid
    case lir_on_spin_wait:
    {
      assert(op->as_Op0() != nullptr, "must be");
      assert(op->_info == nullptr, "info not used by this instruction");
      assert(op->_result->is_illegal(), "not used");
      break;
    }

    case lir_nop:                      // may have info, result always invalid
    case lir_std_entry:                // may have result, info always invalid
    case lir_osr_entry:                // may have result, info always invalid
    case lir_get_thread:               // may have result, info always invalid
    {
      assert(op->as_Op0() != nullptr, "must be");
      if (op->_info != nullptr)           do_info(op->_info);
      if (op->_result->is_valid())     do_output(op->_result);
      break;
    }


// LIR_OpLabel
    case lir_label:                    // result and info always invalid
    {
      assert(op->as_OpLabel() != nullptr, "must be");
      assert(op->_info == nullptr, "info not used by this instruction");
      assert(op->_result->is_illegal(), "not used");
      break;
    }


// LIR_Op1
    case lir_push:           // input always valid, result and info always invalid
    case lir_pop:            // input always valid, result and info always invalid
    case lir_leal:           // input and result always valid, info always invalid
    case lir_monaddr:        // input and result always valid, info always invalid
    case lir_null_check:     // input and info always valid, result always invalid
    case lir_move:           // input and result always valid, may have info
    case lir_sqrt:           // FP Ops have no info, but input and result
    case lir_abs:
    case lir_neg:
    case lir_f2hf:
    case lir_hf2f:
    {
      assert(op->as_Op1() != nullptr, "must be");
      LIR_Op1* op1 = (LIR_Op1*)op;

      if (op1->_info)                  do_info(op1->_info);
      if (op1->_opr->is_valid())       do_input(op1->_opr);
      if (op1->_tmp->is_valid())       do_temp(op1->_tmp);
      if (op1->_result->is_valid())    do_output(op1->_result);

      break;
    }

    case lir_return:
    {
      assert(op->as_OpReturn() != nullptr, "must be");
      LIR_OpReturn* op_ret = (LIR_OpReturn*)op;

      if (op_ret->_info)               do_info(op_ret->_info);
      if (op_ret->_opr->is_valid())    do_input(op_ret->_opr);
      if (op_ret->_result->is_valid()) do_output(op_ret->_result);
      if (op_ret->stub() != nullptr)      do_stub(op_ret->stub());

      break;
    }

    case lir_safepoint:
    {
      assert(op->as_Op1() != nullptr, "must be");
      LIR_Op1* op1 = (LIR_Op1*)op;

      assert(op1->_info != nullptr, "");  do_info(op1->_info);
      if (op1->_opr->is_valid())       do_temp(op1->_opr); // safepoints on SPARC need temporary register
      assert(op1->_tmp->is_illegal(), "not used");
      assert(op1->_result->is_illegal(), "safepoint does not produce value");

      break;
    }

// LIR_OpConvert;
    case lir_convert:        // input and result always valid, info always invalid
    {
      assert(op->as_OpConvert() != nullptr, "must be");
      LIR_OpConvert* opConvert = (LIR_OpConvert*)op;

      assert(opConvert->_info == nullptr, "must be");
      if (opConvert->_opr->is_valid())       do_input(opConvert->_opr);
      if (opConvert->_result->is_valid())    do_output(opConvert->_result);

      break;
    }

// LIR_OpBranch;
    case lir_branch:                   // may have info, input and result register always invalid
    case lir_cond_float_branch:        // may have info, input and result register always invalid
    {
      assert(op->as_OpBranch() != nullptr, "must be");
      LIR_OpBranch* opBranch = (LIR_OpBranch*)op;

      assert(opBranch->_tmp1->is_illegal() && opBranch->_tmp2->is_illegal() &&
             opBranch->_tmp3->is_illegal() && opBranch->_tmp4->is_illegal() &&
             opBranch->_tmp5->is_illegal(), "not used");

      if (opBranch->_opr1->is_valid()) do_input(opBranch->_opr1);
      if (opBranch->_opr2->is_valid()) do_input(opBranch->_opr2);

      if (opBranch->_info != nullptr)  do_info(opBranch->_info);
      assert(opBranch->_result->is_illegal(), "not used");
      if (opBranch->_stub != nullptr)  opBranch->stub()->visit(this);

      break;
    }


// LIR_OpAllocObj
    case lir_alloc_object:
    {
      assert(op->as_OpAllocObj() != nullptr, "must be");
      LIR_OpAllocObj* opAllocObj = (LIR_OpAllocObj*)op;

      if (opAllocObj->_info)                     do_info(opAllocObj->_info);
      if (opAllocObj->_opr->is_valid()) {        do_input(opAllocObj->_opr);
                                                 do_temp(opAllocObj->_opr);
                                        }
      if (opAllocObj->_tmp1->is_valid())         do_temp(opAllocObj->_tmp1);
      if (opAllocObj->_tmp2->is_valid())         do_temp(opAllocObj->_tmp2);
      if (opAllocObj->_tmp3->is_valid())         do_temp(opAllocObj->_tmp3);
      if (opAllocObj->_tmp4->is_valid())         do_temp(opAllocObj->_tmp4);
      if (opAllocObj->_result->is_valid())       do_output(opAllocObj->_result);
      if (opAllocObj->_stub != nullptr)          do_stub(opAllocObj->_stub);
      break;
    }


// LIR_Op2
    case lir_cmp:
    case lir_cmp_l2i:
    case lir_ucmp_fd2i:
    case lir_cmp_fd2i:
    case lir_add:
    case lir_sub:
    case lir_rem:
    case lir_logic_and:
    case lir_logic_or:
    case lir_logic_xor:
    case lir_shl:
    case lir_shr:
    case lir_ushr:
    case lir_xadd:
    case lir_xchg:
    case lir_assert:
    {
      assert(op->as_Op2() != nullptr, "must be");
      LIR_Op2* op2 = (LIR_Op2*)op;
      assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
             op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");

      if (op2->_info)                     do_info(op2->_info);
      if (op2->_opr1->is_valid())         do_input(op2->_opr1);
      if (op2->_opr2->is_valid())         do_input(op2->_opr2);
      if (op2->_tmp1->is_valid())         do_temp(op2->_tmp1);
      if (op2->_result->is_valid())       do_output(op2->_result);
      if (op->code() == lir_xchg || op->code() == lir_xadd) {
        // on ARM and PPC, return value is loaded first so could
        // destroy inputs. On other platforms that implement those
        // (x86, sparc), the extra constrainsts are harmless.
        if (op2->_opr1->is_valid())       do_temp(op2->_opr1);
        if (op2->_opr2->is_valid())       do_temp(op2->_opr2);
      }

      break;
    }

    // special handling for cmove: right input operand must not be equal
    // to the result operand, otherwise the backend fails
    case lir_cmove:
    {
      assert(op->as_Op4() != nullptr, "must be");
      LIR_Op4* op4 = (LIR_Op4*)op;

      assert(op4->_info == nullptr && op4->_tmp1->is_illegal() && op4->_tmp2->is_illegal() &&
             op4->_tmp3->is_illegal() && op4->_tmp4->is_illegal() && op4->_tmp5->is_illegal(), "not used");
      assert(op4->_opr1->is_valid() && op4->_opr2->is_valid() && op4->_result->is_valid(), "used");

      do_input(op4->_opr1);
      do_input(op4->_opr2);
      if (op4->_opr3->is_valid()) do_input(op4->_opr3);
      if (op4->_opr4->is_valid()) do_input(op4->_opr4);
      do_temp(op4->_opr2);
      do_output(op4->_result);

      break;
    }

    // vspecial handling for strict operations: register input operands
    // as temp to guarantee that they do not overlap with other
    // registers
    case lir_mul:
    case lir_div:
    {
      assert(op->as_Op2() != nullptr, "must be");
      LIR_Op2* op2 = (LIR_Op2*)op;

      assert(op2->_info == nullptr, "not used");
      assert(op2->_opr1->is_valid(), "used");
      assert(op2->_opr2->is_valid(), "used");
      assert(op2->_result->is_valid(), "used");
      assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
             op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");

      do_input(op2->_opr1); do_temp(op2->_opr1);
      do_input(op2->_opr2); do_temp(op2->_opr2);
      if (op2->_tmp1->is_valid()) do_temp(op2->_tmp1);
      do_output(op2->_result);

      break;
    }

    case lir_throw: {
      assert(op->as_Op2() != nullptr, "must be");
      LIR_Op2* op2 = (LIR_Op2*)op;

      if (op2->_info)                     do_info(op2->_info);
      if (op2->_opr1->is_valid())         do_temp(op2->_opr1);
      if (op2->_opr2->is_valid())         do_input(op2->_opr2); // exception object is input parameter
      assert(op2->_result->is_illegal(), "no result");
      assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
             op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");

      break;
    }

    case lir_unwind: {
      assert(op->as_Op1() != nullptr, "must be");
      LIR_Op1* op1 = (LIR_Op1*)op;

      assert(op1->_info == nullptr, "no info");
      assert(op1->_opr->is_valid(), "exception oop");         do_input(op1->_opr);
      assert(op1->_tmp->is_illegal(), "not used");
      assert(op1->_result->is_illegal(), "no result");

      break;
    }

// LIR_Op3
    case lir_idiv:
    case lir_irem: {
      assert(op->as_Op3() != nullptr, "must be");
      LIR_Op3* op3= (LIR_Op3*)op;

      if (op3->_info)                     do_info(op3->_info);
      if (op3->_opr1->is_valid())         do_input(op3->_opr1);

      // second operand is input and temp, so ensure that second operand
      // and third operand get not the same register
      if (op3->_opr2->is_valid())         do_input(op3->_opr2);
      if (op3->_opr2->is_valid())         do_temp(op3->_opr2);
      if (op3->_opr3->is_valid())         do_temp(op3->_opr3);

      if (op3->_result->is_valid())       do_output(op3->_result);

      break;
    }

    case lir_fmad:
    case lir_fmaf: {
      assert(op->as_Op3() != nullptr, "must be");
      LIR_Op3* op3= (LIR_Op3*)op;
      assert(op3->_info == nullptr, "no info");
      do_input(op3->_opr1);
      do_input(op3->_opr2);
      do_input(op3->_opr3);
      do_output(op3->_result);
      break;
    }

// LIR_OpJavaCall
    case lir_static_call:
    case lir_optvirtual_call:
    case lir_icvirtual_call:
    case lir_dynamic_call: {
      LIR_OpJavaCall* opJavaCall = op->as_OpJavaCall();
      assert(opJavaCall != nullptr, "must be");

      if (opJavaCall->_receiver->is_valid())     do_input(opJavaCall->_receiver);

      // only visit register parameters
      int n = opJavaCall->_arguments->length();
      for (int i = opJavaCall->_receiver->is_valid() ? 1 : 0; i < n; i++) {
        if (!opJavaCall->_arguments->at(i)->is_pointer()) {
          do_input(*opJavaCall->_arguments->adr_at(i));
        }
      }

      if (opJavaCall->_info)                     do_info(opJavaCall->_info);
      do_call();
      if (opJavaCall->_result->is_valid())       do_output(opJavaCall->_result);

      break;
    }


// LIR_OpRTCall
    case lir_rtcall: {
      assert(op->as_OpRTCall() != nullptr, "must be");
      LIR_OpRTCall* opRTCall = (LIR_OpRTCall*)op;

      // only visit register parameters
      int n = opRTCall->_arguments->length();
      for (int i = 0; i < n; i++) {
        if (!opRTCall->_arguments->at(i)->is_pointer()) {
          do_input(*opRTCall->_arguments->adr_at(i));
        }
      }
      if (opRTCall->_info)                     do_info(opRTCall->_info);
      if (opRTCall->_tmp->is_valid())          do_temp(opRTCall->_tmp);
      do_call();
      if (opRTCall->_result->is_valid())       do_output(opRTCall->_result);

      break;
    }


// LIR_OpArrayCopy
    case lir_arraycopy: {
      assert(op->as_OpArrayCopy() != nullptr, "must be");
      LIR_OpArrayCopy* opArrayCopy = (LIR_OpArrayCopy*)op;

      assert(opArrayCopy->_result->is_illegal(), "unused");
      assert(opArrayCopy->_src->is_valid(), "used");          do_input(opArrayCopy->_src);     do_temp(opArrayCopy->_src);
      assert(opArrayCopy->_src_pos->is_valid(), "used");      do_input(opArrayCopy->_src_pos); do_temp(opArrayCopy->_src_pos);
      assert(opArrayCopy->_dst->is_valid(), "used");          do_input(opArrayCopy->_dst);     do_temp(opArrayCopy->_dst);
      assert(opArrayCopy->_dst_pos->is_valid(), "used");      do_input(opArrayCopy->_dst_pos); do_temp(opArrayCopy->_dst_pos);
      assert(opArrayCopy->_length->is_valid(), "used");       do_input(opArrayCopy->_length);  do_temp(opArrayCopy->_length);
      assert(opArrayCopy->_tmp->is_valid(), "used");          do_temp(opArrayCopy->_tmp);
      if (opArrayCopy->_info)                     do_info(opArrayCopy->_info);

      // the implementation of arraycopy always has a call into the runtime
      do_call();

      break;
    }


// LIR_OpUpdateCRC32
    case lir_updatecrc32: {
      assert(op->as_OpUpdateCRC32() != nullptr, "must be");
      LIR_OpUpdateCRC32* opUp = (LIR_OpUpdateCRC32*)op;

      assert(opUp->_crc->is_valid(), "used");          do_input(opUp->_crc);     do_temp(opUp->_crc);
      assert(opUp->_val->is_valid(), "used");          do_input(opUp->_val);     do_temp(opUp->_val);
      assert(opUp->_result->is_valid(), "used");       do_output(opUp->_result);
      assert(opUp->_info == nullptr, "no info for LIR_OpUpdateCRC32");

      break;
    }


// LIR_OpLock
    case lir_lock:
    case lir_unlock: {
      assert(op->as_OpLock() != nullptr, "must be");
      LIR_OpLock* opLock = (LIR_OpLock*)op;

      if (opLock->_info)                          do_info(opLock->_info);

      // TODO: check if these operands really have to be temp
      // (or if input is sufficient). This may have influence on the oop map!
      assert(opLock->_lock->is_valid(), "used");  do_temp(opLock->_lock);
      assert(opLock->_hdr->is_valid(),  "used");  do_temp(opLock->_hdr);
      assert(opLock->_obj->is_valid(),  "used");  do_temp(opLock->_obj);

      if (opLock->_scratch->is_valid())           do_temp(opLock->_scratch);
      assert(opLock->_result->is_illegal(), "unused");

      do_stub(opLock->_stub);

      break;
    }


// LIR_OpTypeCheck
    case lir_instanceof:
    case lir_checkcast:
    case lir_store_check: {
      assert(op->as_OpTypeCheck() != nullptr, "must be");
      LIR_OpTypeCheck* opTypeCheck = (LIR_OpTypeCheck*)op;

      if (opTypeCheck->_info_for_exception)       do_info(opTypeCheck->_info_for_exception);
      if (opTypeCheck->_info_for_patch)           do_info(opTypeCheck->_info_for_patch);
      if (opTypeCheck->_object->is_valid())       do_input(opTypeCheck->_object);
      if (op->code() == lir_store_check && opTypeCheck->_object->is_valid()) {
        do_temp(opTypeCheck->_object);
      }
      if (opTypeCheck->_array->is_valid())        do_input(opTypeCheck->_array);
      if (opTypeCheck->_tmp1->is_valid())         do_temp(opTypeCheck->_tmp1);
      if (opTypeCheck->_tmp2->is_valid())         do_temp(opTypeCheck->_tmp2);
      if (opTypeCheck->_tmp3->is_valid())         do_temp(opTypeCheck->_tmp3);
      if (opTypeCheck->_result->is_valid())       do_output(opTypeCheck->_result);
      if (opTypeCheck->_stub != nullptr)          do_stub(opTypeCheck->_stub);
      break;
    }

// LIR_OpCompareAndSwap
    case lir_cas_long:
    case lir_cas_obj:
    case lir_cas_int: {
      assert(op->as_OpCompareAndSwap() != nullptr, "must be");
      LIR_OpCompareAndSwap* opCmpAndSwap = (LIR_OpCompareAndSwap*)op;

      if (opCmpAndSwap->_info)                              do_info(opCmpAndSwap->_info);
      assert(opCmpAndSwap->_addr->is_valid(), "used");      do_input(opCmpAndSwap->_addr);
                                                            do_temp(opCmpAndSwap->_addr);
      assert(opCmpAndSwap->_cmp_value->is_valid(), "used"); do_input(opCmpAndSwap->_cmp_value);
                                                            do_temp(opCmpAndSwap->_cmp_value);
      assert(opCmpAndSwap->_new_value->is_valid(), "used"); do_input(opCmpAndSwap->_new_value);
                                                            do_temp(opCmpAndSwap->_new_value);
      if (opCmpAndSwap->_tmp1->is_valid())                  do_temp(opCmpAndSwap->_tmp1);
      if (opCmpAndSwap->_tmp2->is_valid())                  do_temp(opCmpAndSwap->_tmp2);
      if (opCmpAndSwap->_result->is_valid())                do_output(opCmpAndSwap->_result);

      break;
    }


// LIR_OpAllocArray;
    case lir_alloc_array: {
      assert(op->as_OpAllocArray() != nullptr, "must be");
      LIR_OpAllocArray* opAllocArray = (LIR_OpAllocArray*)op;

      if (opAllocArray->_info)                        do_info(opAllocArray->_info);
      if (opAllocArray->_klass->is_valid()) {         do_input(opAllocArray->_klass);
                                                      do_temp(opAllocArray->_klass);
                                            }
      if (opAllocArray->_len->is_valid())   {         do_input(opAllocArray->_len);
                                                      do_temp(opAllocArray->_len);
                                            }
      if (opAllocArray->_tmp1->is_valid())            do_temp(opAllocArray->_tmp1);
      if (opAllocArray->_tmp2->is_valid())            do_temp(opAllocArray->_tmp2);
      if (opAllocArray->_tmp3->is_valid())            do_temp(opAllocArray->_tmp3);
      if (opAllocArray->_tmp4->is_valid())            do_temp(opAllocArray->_tmp4);
      if (opAllocArray->_result->is_valid())          do_output(opAllocArray->_result);
      if (opAllocArray->_stub != nullptr)             do_stub(opAllocArray->_stub);
      break;
    }

// LIR_OpLoadKlass
    case lir_load_klass:
    {
      LIR_OpLoadKlass* opLoadKlass = op->as_OpLoadKlass();
      assert(opLoadKlass != nullptr, "must be");

      do_input(opLoadKlass->_obj);
      do_output(opLoadKlass->_result);
      if (opLoadKlass->_info) do_info(opLoadKlass->_info);
      break;
    }


// LIR_OpProfileCall:
    case lir_profile_call: {
      assert(op->as_OpProfileCall() != nullptr, "must be");
      LIR_OpProfileCall* opProfileCall = (LIR_OpProfileCall*)op;

      if (opProfileCall->_recv->is_valid())              do_temp(opProfileCall->_recv);
      assert(opProfileCall->_mdo->is_valid(), "used");   do_temp(opProfileCall->_mdo);
      assert(opProfileCall->_tmp1->is_valid(), "used");  do_temp(opProfileCall->_tmp1);
      break;
    }

// LIR_OpProfileType:
    case lir_profile_type: {
      assert(op->as_OpProfileType() != nullptr, "must be");
      LIR_OpProfileType* opProfileType = (LIR_OpProfileType*)op;

      do_input(opProfileType->_mdp); do_temp(opProfileType->_mdp);
      do_input(opProfileType->_obj);
      do_temp(opProfileType->_tmp);
      break;
    }
  default:
    op->visit(this);
  }
}