Какую оптимизацию на уровне инструкций может применять JIT? - PullRequest
1 голос
/ 13 сентября 2011

В какой степени JIT может заменить независимый от платформы код машинными инструкциями для конкретного процессора?

Например, набор команд x86 включает в себя инструкцию BSWAP, чтобы изменить порядок следования байтов 32-разрядного целого числа. В Java метод Integer.reverseBytes() реализован с использованием нескольких побитовых масок и сдвигов, хотя в собственном коде x86 он может быть реализован в одной инструкции с использованием BSWAP. Могут ли JIT (или статические компиляторы) автоматически вносить изменения, или они слишком сложны или не стоят этого из-за плохого соотношения скорости и времени?

(я знаю, что в большинстве случаев это микрооптимизация, но тем не менее мне это интересно.)

1 Ответ

1 голос
/ 17 сентября 2011

В этом случае, да, компилятор сервера hotspot может выполнить эту оптимизацию. Методы reverseBytes () регистрируются как vmIntrinsics в горячей точке. Когда jit-компилятор компилирует эти методы, он генерирует специальный IR-узел, а не компилирует весь метод. И этот узел будет переведен в 'bswap' в x86. см. src / share / vm / opto / library_call.cpp

//----------------------------   inline_reverseBytes_int/long/char/short-------------------
// inline Integer.reverseBytes(int)
// inline Long.reverseBytes(long)
// inline Character.reverseBytes(char)
// inline Short.reverseBytes(short)
bool LibraryCallKit::inline_reverseBytes(vmIntrinsics::ID id) {
  assert(id == vmIntrinsics::_reverseBytes_i || id == vmIntrinsics::_reverseBytes_l ||
         id == vmIntrinsics::_reverseBytes_c || id == vmIntrinsics::_reverseBytes_s,
         "not reverse Bytes");
  if (id == vmIntrinsics::_reverseBytes_i && !Matcher::has_match_rule(Op_ReverseBytesI))  return false;
  if (id == vmIntrinsics::_reverseBytes_l && !Matcher::has_match_rule(Op_ReverseBytesL))  return false;
  if (id == vmIntrinsics::_reverseBytes_c && !Matcher::has_match_rule(Op_ReverseBytesUS)) return false;
  if (id == vmIntrinsics::_reverseBytes_s && !Matcher::has_match_rule(Op_ReverseBytesS))  return false;
  _sp += arg_size();        // restore stack pointer
  switch (id) {
  case vmIntrinsics::_reverseBytes_i:
    push(_gvn.transform(new (C, 2) ReverseBytesINode(0, pop())));
    break;
  case vmIntrinsics::_reverseBytes_l:
    push_pair(_gvn.transform(new (C, 2) ReverseBytesLNode(0,pop_pair())));
    break;
  case vmIntrinsics::_reverseBytes_c:
    push(_gvn.transform(new (C, 2) ReverseBytesUSNode(0, pop())));
    break;
  case vmIntrinsics::_reverseBytes_s:
    push(_gvn.transform(new (C, 2) ReverseBytesSNode(0, pop())));
    break;
  default:
;
  }
  return true;
}

и src / cpu / x86 / vm / x86_64.ad

instruct bytes_reverse_int(rRegI dst) %{
  match(Set dst (ReverseBytesI dst));

  format %{ "bswapl  $dst" %}
  opcode(0x0F, 0xC8);  /*Opcode 0F /C8 */
  ins_incode( REX_reg(dst), OpcP, opc2_reg(dst) );
  ins_pipe( ialu_reg );
%}
...