Newsgroups: comp.arch


> Here's a question that's been puzzling me for a while.  Why don't the latest 
> RISC processors (or any microprocessors) have conditional codes inbedded in
> every instruction?

What you are describing is essentially predicated execution.  HP's PA-RISC
does this.  Each computational instruction (arithmetic, logical and shift
instructions) can specify a condition.  If the condition is met, the
following instruction is "nullified", that is, it is not executed.  This is
equivalent to a conditional "skip" operation, except that it does not
involve the instruction fetch unit.  Not involving the Ifetch unit is, of
course, the point.  Disruptions to fetch are costly and grow more so over
time.

Your example:

  if(a==b)
    c--;
  else 
    d+=10;

could be coded in PA instructions without any branches, as follows:
(for clarity, let me assume that a,b,c, and d are already in registers
1,2,3, and 4)
	
	sub,<>	r1,r2,r0	; compare a and b, nullify next if not equal
	addi	-1,r3,r3	; c <- c-1
	sub,=	r1,r2,r0	; compare a and b, nullify next if equal
	addi	10,r4,r4	; d <- d+10

The comparison here is done with a normal subtract, and the difference is
discarded.  Any computational instruction can be used to control
nullification.  Any instruction can be nullified.

Note that there is only one predicate (the boolean that determines whether
or not to execute some instruction), and that the predication (determining
whether to execute unconditionally or under predicate) is specified
implicitly in the sequence of instructions.  Other approaches involve
having a set of predicates and allowing a predicate to cover several
instructions.  These approaches, though, suffer from the drawback that you
cited, namely that they chew up a fair amount of instruction encoding (the
comparison instruction must name the predicate to set, and the predicated
instruction must name the predicate to be tested).

>  --- If the "condition" blocks are bigger than a couple lines of HLL, 
> maybe the condition code embedding will not speed things up much.

Yes.  This means that you wouldn't get much benefit from being able to name
multiple predicates, so having 1 predicate works out pretty well.  Having
the predicate cover only one instruction is not too bad a limitation.
Quite frequently the instructions to execute a then-clause contain several
instructions that can be pulled up before the if (ones that only affect
temporary results), leaving few (often only 1) instructions that cannot be.

[To be complete, and to avoid flames, let me say that predicates can also
be used to avoid other penalties, and to effectively avoid some of these
you do indeed need to be able to have several predicates active
simultaneously.]


Contrary to what a lot of folks think, the predication scheme maps well
onto instruction-level-parallelism approaches, such as superscalar,
superpipelined and VLIW.  Control dependencies are effectively transformed
into data dependencies, which are must more easily handled (for a given
level of performance), or yield more performance (for a given amount of
design work).

For example, a superscalar design could simply treat the predicate as a
third operand to an instruction.  It comes to the instruction, from the
previous instruction, through a mechanism very like operand/register
bypass.  Obviously, chained nullification, like any chained dependency,
will cause problems in a superscalar design.  Compilers are built to
understand this.

------------------------------------------------------------------------------
Dale Morris	    |  Now is the time, and now is the record...
morris@iag.hp.com   |          of the time.
------------------------------------------------------------------------------


Xref: sparky comp.arch:4781 comp.sys.dec:2463