7

私は C# でいくつかの数学コードを書いており、x86 リリースで強制的にコンパイルし、最適化し、windbg で逆アセンブリを見ています。それはたいていかなり上手で、しばしば私よりも優れたアセンブリを作成します (私がアセンブリが得意というわけではありませんが、その通りです)。

しかし、私はこの機能に気付きました:

static void TemporaryWork()
{
    double x = 4;
    double y = 3;
    double z = Math.Atan2(x, y);
}

この逆アセンブリを生成しています:

001f0078 55              push    ebp
001f0079 8bec            mov     ebp,esp
001f007b dd05a0001f00    fld     qword ptr ds:[1F00A0h]
001f0081 83ec08          sub     esp,8
001f0084 dd1c24          fstp    qword ptr [esp]
001f0087 dd05a8001f00    fld     qword ptr ds:[1F00A8h]
001f008d 83ec08          sub     esp,8
001f0090 dd1c24          fstp    qword ptr [esp]
001f0093 e86e9ba66f      call    clr!GetHashFromBlob+0x94e09 (6fc59c06) (System.Math.Atan2(Double, Double), mdToken: 06000de7)
001f0098 ddd8            fstp    st(0)
001f009a 5d              pop     ebp
001f009b c3              ret

x86 の専門家でなくても、System.Math.Atan2 への呼び出しがあることに気付くはずです。関数呼び出しのように。

しかし、実際にはそれを行う x86 オペコードがあります: FPATAN

操作を実行する実際のアセンブリ命令があるのに、JITer が関数を呼び出すのはなぜですか? System.Math は基本的にネイティブ アセンブリ命令のラッパーだと思っていました。そこにあるほとんどの操作には、直接アセンブリ オペコードがあります。しかし、どうやらそうではないのでしょうか?

JITerがこのかなり明白な最適化を実行できない/実行できない理由について、誰かが情報を持っていますか?

4

1 に答える 1

6

この回答から理由を追跡できます。これらの数学関数がジッターによってどのようにマッピングされるかを示しています。

clr/src/classlibnative/float/comfloat.cpp、ComDouble::Atan2() 関数に移動します。その理由は次のとおりです。

   // the intrinsic for Atan2 does not produce Nan for Atan2(+-inf,+-inf)
   if (IS_DBL_INFINITY(x) && IS_DBL_INFINITY(y)) {
       return(x / y);      // create a NaN
   }
   return (double) atan2(x, y);

そのため、CLI に準拠していない FPU の動作を修正することは回避策です。

于 2013-04-21T14:24:02.153 に答える