2007/12/06

if文と三項演算子 このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

カツマさんのところで、javascriptのif文と三項演算子の速度比較をされたようです。

三項演算子の方が速い場合が多い理由(の予想)

if文は「文」なのに対し、三項演算子は「式」なので、解釈系(インタプリタ)や翻訳系(コンパイラ)が分岐除去の最適化をしやすいんじゃないかと思います。

なぜ式だと分岐除去がしやすいかというと、任意の式が2つ与えられたときに、「それらが同程度の計算で実行できるかどうか」の判断が文2つのときよりも簡単に求まるからかな、と思います。

if文の場合も三項演算子の場合も、then節とelse節とがどちらも十分単純で、異なる部分に分岐の有無の差がなかったりする場合に、分岐を除去して2つを投機的に計算して、後から条件の結果より2つの結果を選択するという最適化ができそうですが、

式の場合、true-exprとfalse-exprが関数呼び出しを含まなければ分岐除去できそうなのに対し、文の場合はthen節とelse節が全く同じ構造を持つ文でないと分岐除去できなさそう、という。

処理系の最適化モジュールを書くのに必要な手間が、式の場合の方が少ないからなんじゃないか、という予想です。

個別の処理系に関しては、処理系の実装次第なのでしょう。

ちなみに、gcc 3.4, -O2 の場合は



int main(int args, char** argv)
{
return (int)(args==5 ? "1022" : "1050");
}


でも



int main(int args, char** argv)
{
if(args==5) return (int)"1022"; else return (int)"1050";
}


でも同様に分岐除去されていないアセンブリが出てきました。



ちなみに!Cell/B.E. の SPU は分岐のペナルティが18cyclesくらいあって結構でかいので、できるだけ三項演算子や spu_sel を使って処理系が分岐を除去しやすくする、または明示的に分岐除去する、という方法がオススメされているようであるッッ......!!!