ハードウェア

ある関数fがあって、その関数の中ではAという作業とBという作業をするとする。イメージとしてはこんな感じ。

int f(int arg1){
     return B(A(arg1));
}

さて、ここでAという関数とBという関数は、どちらも整数を受け取って整数を返す関数だとしよう。さらに、関数Aおよび関数Bは、奇数を受け取った場合は奇数を返し、偶数を受け取った場合は偶数を返す。そして、内部の中身は、偶数と奇数で違うソースだとしよう。そして、Aでは偶数の方が時間がかかり、Bでは奇数の方が時間がかかるとする。すなわち、

int a(int arg){
    if(arg % 2 == 0){
        //何かの作業(長い)
        
        return (偶数)
    }else{
        //何かの作業(短い)
        
        return (奇数)
    }
}
int b(int arg){
    if(arg % 2 == 0){
        //何かの作業(短い)
        
        return (偶数)
    }else{
        //何かの作業(長い)
        
        return (奇数)
    }
}

というようになっていたとする。
このような場合、最初からfの中で分岐させてやればいいじゃないか、という話もあるが、ソフトウェアの場合は、aとbに意味がある場合には、このように記述した方が良い場合も多い。単なるサブルーチンであれば、もちろん最初から分岐させてaという関数とbという関数を分離しない方が、分岐の数も少なくて早くなる可能性もあるのだけれど、ソフトウェアの場合にはこの程度の分岐であれば無視して、意味を重視した方が良い。もちろん、最初からaとbに意味がない場合には別だけれども。
しかしながら、これの実行時間をシミュレーションする場合には話は変わる。いや、実際には変わらないとも言えるのだけれども、「シミュレータ上では」変わる可能性が高い。というのは、関数fの実行時間の最大値を計算する時に、通常のシミュレータであれば(関数aの実行時間の最大値)+(関数bの実行時間の最大値)を算出するからだ。そして、ハードウェアではまさしくコレが発生する。
・・・と言うことで、faddの高速化にはこんな感じの部分を消すといいよ、とnakajima氏に教えてもらった。