まずフロントエンドのFetch/Decodeある(Photo06)。従来は4命令/CycleのデコーダにMacroFusionやLoop Stream Detectorを組み合わせる形で実装されていたわけだが、このMacroFusionには色々と制限が多かった。以前こちらでちょっと触れている通り、MacroFusionの対象はCMP+JCCかTest+JCCに限られていたが、Nehalemではこのバリエーションが増やされ、かつ64bitモードでも動作するようになった(Photo07)。
Stream Detectorにも大幅な変更が入った。従来は命令Fetch後にこれが入り、Loop構造を検出すると再FetchしなくてもLoop Stream Detectorから命令を取り出せる構造になっていた(Photo08)。NehalemではこのLoop Stream Detectorを、Decodeの後に持ってきている(Photo09)。これによりLoop構造内ではDecoderを動かす必要がなくなるので、省電力化が図れる(x86において一番激しく動いているのはDecoder→Rename/Alloc→Scheduler/Retirement Unitの部分であり、Decoderが動かなくなるだけで大幅に省電力化が図れるのは自明の事である)上に、バッファサイズも28 MicroOpsに増加されたことで、やや長いループにも対処できるようになった。
ところでこの構造であるが、見方を変えればNetBurst Architectureで採用されたTrace Cacheの再来とも言える。NetBurstでは12K語分のキャッシュだったから、これに比べれば遥かに小さいとはいえ、うまくLoop構造に入ると全く同じ動作をする事になる。見方を変えれば、これこそがL1命令キャッシュであり、Photo05に出てくる32KB Instruction CacheというのはL2命令キャッシュとも捉えられる訳だ。Stream Loop Detectorは、プログラムの非Loop構造部分の実行中は単にFIFOとして動作することになるから、これはキャッシュそのものと見るのが正しいと筆者は考える。
このLoop Stream Detectorの制御を行うBranch Predictorにも手が入った(Photo10)。もっともその方向性を見ると、非常に興味深い(Photo11)。Banias~Yonah~Merom~Penrynの世代はやはりMobile向けの設計だから、巨大サーバー向けのワークロードなどを考慮する必要はない(というか、それを考慮した結果としてメカニズムが増え、消費電力が増加することは容認できない)というポリシーで、この結果として同じアーキテクチャを使ったXeonなどが、結果としてOpteronに遅れを取る事になったとしても、これは仕方が無い事である。ただいつまでも「仕方が無い」では済ませられなかったようで、Opteron同様にマルチレベルのBranch Predictionを搭載することになった様だ。
Photo10:この説明そのものは至極当然というか、ごく当たり前の話である。 |
Photo11:具体的にはどんな? という話は今回はまだ未公開。ちなみに競合製品であるBarcelonaの場合はこんな具合。 |
Branch Predictionに関してもう一つはReturn Stack Buffer(RSB)に手が入った(Photo12)。RSBはCALL/RETを利用する際に、RETで復帰すべきアドレスをあらかじめBufferに格納しておき、RET命令が来たら素早く復帰できるようにするためのものだ。ただし、分岐予測にミスをした場合、RSBが上書きされたり、またRSBがあふれた場合に古いデータを上書きして、結果として破壊されてしまう場合がある。これを防ぐために、RSBのRenamingをサポートすることになった。