以上程序在执行时流水线就不会有断流情况发生。然而,必须注意:调整指令序列时一定不能改变原来程序的数据相关关系,即被移动指令中的所有数据存储单元与移动过程中所经过的指令的所有数据存储单元之间不能有数据的读写、写读和写写相关。另外,还要求,被移动的指令不要破坏机器的条件码,至少不要影响后面的条件码测试指令所使用的条件码。
  如果找不到符号上述条件的指令来调整程序中指令序列,那么,编译程序必须在条件转移指令后面插入空操作指令。如果指令的执行过程分为多个流水段,则要插入多条空操作指令。
  2、指令取消技术
  采用指令延时技术,遇到条件转移指令时,调整指令序列非常困难,在许多情况下找不到可以用来调整的指令。有些RISC处理机采用指令取消技术。
  为了提高程序的执行效率,应该尽量少取消指令,以保持指令流水线处于充满状态。因此,可以采用如下规则:如果是向后转移(转移的目标地址小于当前程序计数器PC的值),则在转移不成功时取消下条指令,否则,执行下条指令;如果是向前转移,则正好相反,在转移不成功时执行下条指令,否则,取消下条指令。
  下面看两个具体的例子。首先是一个向后转移的例子。调整前的程序如图3.7(a)所示,调整前的程序如图3.7(b)所示。
图3.7 指令取消技术

  循环体的第一条指令XXX经调整后安排在两个位置,第一个位置是在循环体的前面,即在进入循环之前要先执行一次。第二个位置安排在循环体的后面,即在循环的出口条件判断指令COMP的下面。如果转移成功,则执行下面的XXX指令,然后返回到LOOP;如果转移不成功,则取消下面的XXX指令,接着执行WWW指令。
  由于向后转移时,绝大多数情况下是转移成功的,只有在循环结束的最后一次,转移才不成功。因此,采用这种指令取消技术能够使指令流水线在绝大多数情况下不断流,保持很高的流水效率。
  对于向前转移的情况,即IF THEN控制结构,有如下一个程序:

  如果COMP指令的转移条件不成立,则下条指令TTT不取消,"THEN"部分的程序代码照常执行;如果转移条件成立,下条指令TTT的执行被取消,程序执行转向THRU位置,"THEN"部分的程序代码全部不执行。
  由于向前转移成功与不成功的概率通常各为50%,因此,采用正常的指令取消技术就可以了。
  对于条件分支中只有一条指令的情况,可以采用隐含转移技术。例如,为了实现下面的语句:
    IF (a<b) THEN b=b+1
  用汇编语言可以写成:
     COMP >=, Ra, Rb ;a与b已经存放在通用寄存器Ra和Rb中
     INC Rb
  指令COMP比较a与b的大小,若(Ra)>=(Rb),则取消下条指令,否则,执行下条指令。
  3、重叠寄存器窗口技术
  RISC的指令系统比较简单,CISC中的一条复杂指令,在RISC中通常要用一段子程序来实现。因此,RISC程序中的CALL和RETURN的子程序指令要比CISC程序中多。
  在执行CALL指令时,必须把硬件现场(主要包括程序计数器和处理机状态字)和程序本身的软件现场(主要指在子程序中要使用的通用寄存器等)保存到主存储器中。另外,还要把执行子程序所需要的参数从主程序传送过去。在执行RETURN指令时,要做相反的工作,最后把运算结果传送回主程序。因此,执行CALL和RETURN指令时,访问存储器的信息量非常大。据统计,在PASCAL语言和C语言中分别有15%和12%的CALL和RETURN指令,而它们访问存储器的信息量却占整个访存信息量的44%和45%。
  为了使CALL和RETURN操作尽量少访问存储器,美国加洲大学伯克利分校的F,Baskett提出重叠寄存器窗口(Overlapping Register Window)技术。并且首先在RISC I上应用。在RISC II中,寄存器的数量增加到138个。
  重叠寄存器窗口技术:在处理机中设置一个数量比较大的寄存器堆,并把它划分成很多个窗口。每个过程使用其中相邻的三个窗口和一个公共的窗口,而在这些窗口中有一个窗口是与前一个过程共用,还有一个窗口是与下一个过程共用的。与前一过程共用的窗口可以用来存放前一过程传送给本过程的参数,同时也存放本过程传送给前一过程的计算结果。同样,与下一过程共用窗口可以用来存放本过程传送给下一过程的参数和存放下一过程传送给本过程的计算结果。
  图3.8是RISC II中采用的重叠寄存器窗口。共有138个寄存器,分成17个窗口,其中,有一个由10个寄存器组成的窗口是全局窗口,能被所有过程访问。另外有8个窗口,每个窗口各10个寄存器,分别作为8个过程的局部寄存器。还有8个窗口,每个窗口各有6个寄存器,是相邻两个过程公用的,称为重叠寄存器窗口。每个过程均可以访问32个寄存器,其中,有10个是所有过程公用的全局寄存器,有10个是只供本过程使用的局部寄存器,有6个是与上一过程公用的寄存器,还有6个是与下一过程公用的寄存器。
  只要调用的深度不超过规定的层数(如8层),重叠寄存器窗口技术可以减少大量的访存操作。当调用层数超过规定层数时,称为寄存器溢出,这时,可以在主存中开辟一个堆栈,把超过规定层数的寄存器中的内容压入堆栈中。
  在SUN公司的SPARC处理机中,以及后来的Super SPARC和Utra SPARC处理机中,还把最后一个过程的公用寄存器与第一个过程的公用寄存器重叠起来,形成一个循环圈。在调用层数很多时,可以循环使用。
  F. Baskett等人使用Quicksort和Puzzle两个程序对寄存器窗口技术的有效性进行了测试。Quicksort程序的特点是过程调用的次数在整个程序中所占的比例比较大,但调用的深度不大,而Puzzle程序正好相反。RISC II与VAX-11两种机器的比较结果如表3.9所示,RISC II的访存次数主要是寄存器窗口溢出引起的,而VAX--11访存次数是为了保持和恢复通用寄存器中内容而引起的。从表中看出,RISC II寄存器溢出的次数很少,只占千分之一左右,影响也不大。由于采用了寄存器窗口技术,由程序调用引起的访问存储器次数只占程序总访存次数的1%左右。
图 3.8 重叠寄存器窗口技术