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

发布于 2024-12-04 11:56:44 字数 297 浏览 2 评论 0原文

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

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

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

To what extent can a JIT replace platform independent code with processor-specific machine instructions?

For example, the x86 instruction set includes the BSWAP instruction to reverse a 32-bit integer's byte order. In Java the Integer.reverseBytes() method is implemented using multiple bitwise masks and shifts, even though in x86 native code it could be implemented in a single instruction using BSWAP. Are JITs (or static compilers for that matter) able to make the change automatically or is it too complex or not worth it due to a poor speed/time tradeoff?

(I know that this is in most cases a micro-optimisation, but I'm interested none the less.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无人问我粥可暖 2024-12-11 11:56:44

对于这种情况,是的,热点服务器编译器可以进行这种优化。 verseBytes() 方法在热点中注册为 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 );
%}

For this case, yes, the hotspot server compiler could do this optimization. The reverseBytes() methods are registered as vmIntrinsics in hotspot. When jit compiler compile these methods, it will generate a special IR node, not compile the whole method. And this node will be translated into 'bswap' in x86. see 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;
}

and 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 );
%}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文