スケジューリングについては少々複雑です。 パイプライン・プロセッサとスーパースカラ・プロセッサ、 つまり RISC と一部の最新の CISC マシンは、
ある命令の結果が出るのを待つ間に別の命令を処理できます。 通常、 コンパイラーは、
これらの遅延スロットを有効に使用できるように命令を並べ替え(スケジューリング)します。 ただし、 我々の最初の挑戦では、
コンパイラーはプリミティブのスケジューリングをうまく機能させられませんでした。 たとえば、 +
は以下のように実装されます
n=sp[0]+sp[1]; sp++; sp[0]=n; NEXT;
NEXT
は厳密に他のコードの後に配置されます。 つまり、 スケジューリングはまずありえません。
ちょっと考えると問題が明らかになってきます: コンパイラーは、 sp
と ip
が異なるアドレスを指していることを認識できないため(そして、 たとえ認識が可能だったとしても、 私たちが使用した gcc
のバージョンはそれを知りません。)、 ストア上の cfa の負荷を TOS に移動できませんでした。 実際、
スタックのTOSまたはTOS付近に対するコードが実行された場合、 これらのポインターは同一になる可能性があります。 速度を重視して、 私達は、 この、
おそらく未使用の「認識機能」を禁止した上でコンパイラーのスケジューリングを支援します(NEXT
を幾つかの部分、 すなわち、
NEXT_P0
と NEXT_P1
と NEXT_P2
に分割します): そうすると、 +
は以下のようになります:
NEXT_P0; n=sp[0]+sp[1]; sp++; NEXT_P1; sp[0]=n; NEXT_P2;
さまざまな操作を NEXT の部分間でいくつかの方法で分散するさまざまな仕組みがあります。 一般に、 異なる仕組みは異なるプロセッサ上で最高のパフォーマンスを発揮します。 私たちは、 ほとんどのアーキテクチャーに対して、 そのアーキテクチャーのほとんどのプロセッサで良好に動作する仕組みを使用しています。 将来的には、 ベンチマークを実施し、 インストール時に仕組みを選択するように切り替える可能性があります。