JIT可以应用多少指令级优化?

时间:2011-09-13 14:30:07

标签: jit compiler-optimization

JIT在多大程度上可以用特定于处理器的机器指令替换平台无关代码?

例如,x86指令集包含用于反转32位整数字节顺序的BSWAP指令。在Java中,Integer.reverseBytes()方法是使用多个按位掩码和移位实现的,即使在x86本机代码中,它也可以使用BSWAP在单个指令中实现。 JIT(或静态编译器)是否能够自动进行更改,还是由于速度/时间权衡较差而过于复杂或不值得?

(我知道这在大多数情况下都是微优化,但我对此感兴趣。)

1 个答案:

答案 0 :(得分:1)

对于这种情况,是的,热点服务器编译器可以进行此优化。 reverseBytes()方法在hotspot中注册为vmIntrinsics。当jit编译器编译这些方法时,它会生成一个特殊的IR节点,而不是编译整个方法。此节点将在x86中转换为'bswap'。请参阅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 );
%}