static bool match(UnsafeRawOp* x,
                  Instruction** base,
                  Instruction** index,
                  int*          log2_scale) {
  Instruction* instr_to_unpin = NULL;
  ArithmeticOp* root = x->base()->as_ArithmeticOp();
  if (root == NULL) return false;
  // Limit ourselves to addition for now
  if (root->op() != Bytecodes::_ladd) return false;
  // Try to find shift or scale op
  if (match_index_and_scale(root->y(), index, log2_scale, &instr_to_unpin)) {
    *base = root->x();
  } else if (match_index_and_scale(root->x(), index, log2_scale, &instr_to_unpin)) {
    *base = root->y();
  } else if (root->y()->as_Convert() != NULL) {
    Convert* convert = root->y()->as_Convert();
    if (convert->op() == Bytecodes::_i2l && convert->value()->type() == intType) {
      // pick base and index, setting scale at 1
      *base  = root->x();
      *index = convert->value();
      *log2_scale = 0;
    } else {
      return false;
    }
  } else {
    // doesn't match any expected sequences
    return false;
  }
  // Typically the addition is pinned, as it is the result of an
  // inlined routine. We want to unpin it so as to avoid the long
  // addition, but in order to do so we must still ensure that the
  // operands are pinned, as they may be computed arbitrarily before
  // the Unsafe op completes (even if the Unsafe op is pinned). At
  // this point we do not really need to pin Unsafe raw or object
  // gets.
  if (root->is_pinned()) {
    if (root->pin_state() == Instruction::PinInlineReturnValue) {
      assert(x->is_pinned(), "All unsafe raw ops should be pinned");
      root->unpin(Instruction::PinInlineReturnValue);
      (*base)->pin();
      (*index)->pin();
    } else {
      // can't safely unpin this instruction
      return false;
    }
  }

  if (PrintUnsafeOptimization && instr_to_unpin != NULL) {
    tty->print_cr("pin_state = 0x%x", instr_to_unpin->pin_state());
    instr_to_unpin->print();
  }
  return true;
}