2011-09-13 8 views
1

JITは、プラットフォームに依存しないコードをプロセッサ固有のマシン命令にどの程度まで置き換えることができますか?JITはどれくらいの命令レベルの最適化を適用できますか?

たとえば、x86命令セットには、32ビット整数のバイト順を逆にする命令BSWAPが含まれています。 JavaではInteger.reverseBytes()メソッドは複数のビット単位のマスクとシフトを使用して実装されていますが、x86ネイティブコードではBSWAPを使用して単一の命令で実装できます。 JIT(またはそのような静的コンパイラ)は、自動的に変更を行うことができますか、速度/時間の妥協のために、複雑すぎるのか、それとも価値がありませんか?

(私はこれはほとんどの場合、ミクロの最適化であることを知っているが、私は興味を持って何も少ないよん。)

+1

*缶*このような低レベルの最適化の問題はめったにありません。問題は通常、実際に実行するのに十分有用であると考えられるかどうかです。 – delnan

答えて

1

この場合のために、はい、ホットスポット・サーバ・コンパイラは、この最適化を行うことができます。 reverseBytes()メソッドは、ホットスポットにvmIntrinsicsとして登録されています。 jitコンパイラがこれらのメソッドをコンパイルすると、メソッド全体をコンパイルするのではなく、特別なIRノードが生成されます。そしてこのノードはx86では 'bswap'に翻訳されます。ご覧のsrc /共有/ VM /光/ 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); 
%} 
+0

優秀、ありがとう。したがって、この例(と間違いなく他のもの)では、最適化は、バイトコードを分析するのではなく、「この計算はBSWAPと同等であるので、私はそれを使用します」というより、インライン化の特別なケースとして実装されています。可能であれば、独自のコードをローリングするのではなく、ライブラリを使用する別の理由があります。 – Gnat