実測しないでアセンブリ出力を較べてみた。
static int sign0(int n) {if (n > 0) return 1;if (n < 0) return -1;return 0;}
static int sign1(int n) {if (n < 0) return -1;if (n > 0) return 1;return 0;}
static int sign2(int n) {return ((n > 0) - (n < 0));}
static int sign3(int n) {return n < 0 ? -1 : n > 0;}
・gcc3.4.4@cygwin
sign1とsign3で全く同じコードを吐く。それらは条件ジャンプ1回と条件セットでシフトはなし。
sign2はシフトと条件セットを駆使している。sign0は無駄なジャンプあり。
・gcc3.2.3@linux
cygwin版とほぼ同じ。こちらの方が積極的にインライン展開しようとする。一部無駄なジャンプあり。
sign0とsign2でシフトを使う。
・icc(32)9.0@linux
sign2以外はジャンプし捲くりのほぼ同じコード。
プロファイリングでジャンプしない条件を探すことが前提か。
・icc(64)9.0@linux
sign2以外ではシフトは使わない。ジャンプはするが、32ビット版ほどではない。
sign2以外は同じロジックになり、条件ジャンプ1回無条件ジャンプ1回、条件つきコピー1回。
・総括
インライン展開しないとどっち道関数呼び出しが遅いと思われ。
インライン展開するならロジックによる速度差が出るだろうけれど、
iccの場合はジャンプの可能性をプロファイリングで正しく見積もるべきだろう。
#詳細は割愛。