私も気になったのでVisual C++ 6.0で計測してみました。
結果としては、
・powの片方にでも変数が入ると展開してくれない
・両方定数(constでも可)なら展開する
・volatileが付くと最適化防止がかかるので展開してくれない
といったところでしょうか。
そこまで深いチェックはしてないので間違ってるかも知れませんが・・・。まぁ。予想通りではあります。
double pow(double x, double y)なので(ですよね?)、pow(x,2)はpow(x,2.0)とキャストされて渡されるわけで、これをx*xと解釈するのはむずかしい気がします。
というわけで普段x*xを使っているのですが、
例えば、(a+b+c)^2が欲しいときに、
(a+b+c)*(a+b+c)とやるか、
x=a+b+c;としておいてx*xとやるかはよく迷います。
後者が速い気がしますが、めんどうなので。
それは最適化してもらえるのかな。
>hajimeさん
VC6での検証、ありがとうございます。両方定数なら、というのが曲者ですね。片方が定数の場合(今回は2のみ)の展開もサポートしてくれると嬉しいよね、というのがこのお題の本質でした。
>cataclyさん
確かに標準的なC言語ではpow(double, double)となっていますが、C++ではオーバーロード(引数の型や数が別なら同一名でも複数の定義が可能)の機能があるので、pow(double, int)というのが隠れてあったりします。その証拠にアセンブラ出力を見ると、今回は内部的には_Pow_intというテンプレート関数が呼び出されていることが確認できると思います。
(x * x)の件ですが、xが簡単の場合は最適化がかかると思いますが、複雑な場合は怪しいですね。これも試してみる価値があると思います。