Compares
Home Up

 

Pipeline
EPIC
Instruction Format
Instruction Sequencing
Operating Environments
Predication
Compares
Speculation
Branching
Register Rotation
Other

Compare operations play a key role in IA-64, and particularly in relation to predication. Compares operate on a pair of predicate registers.

Normal Compares

Normal compares evaluate the expression and set the value of the first predicate register to the result of the comparison, and set the second predicate register to the complement of the comparison.

An example of this type of normal predicated comparison is a simple if then else statement:

if (a == b) {
    c++;
}  else  {
    d++;
}

The compiled code looks like:

{
    cmp.eq  p1, p2 = ra, rb
    (p1)  add  rc = rc, 1
    (p2)  add  rd = rd, 1
}

Normal compares can themselves be predicated. If the predicate of a normal compare is 1, it executes normally. Otherwise, the compare does nothing, and it's target registers will remain unchanged.

Unconditional Compares

Unconditional compares differ from normal compares due to their actions when predicated themselves. When the predicate of an unconditional compare is 1, the compare executes normally and writes to its target registers as would a normal compare. However, when the predicate of an unconditional compare is 0, an unconditional compare will write 0's to both of it's target registers. This is in contrast to a normal register which would do nothing. The unconditional compare is useful in nested if-conversion such as the following code extracted from [1]:

if (a>b) {
    c++;
}  else  {
    d += c;
    if (e==f) {
        g++;
    }  else  {
        h--;
    }
}

The following is the predicated code:

{
    cmp.gt   p1, p2 = ra, rb
}  {
    (p1)  add  rc = rc, 1
    (p2)  add  rd = rd, rc
    (p2)  cmp.eq.unc  p3, p4 = re, rf
}  {
    (p3)  add  rg = rg, 1
    (p4)  add  rh = rh, -1
}

If a > b then p2 will be set to 0 by the unpredicated compare, and the unconditional compare will set both p3 and p4 to 0. If a <= b then p2 will be set to 1, and the unconditional compare will evaluate e == f to determine the values to write to p3 and p4.

Parallel Compares

IA-64 provides three types of parallel compare operations:

AND - sets both targets to 0 if false
OR - sets both to 1 if true
ANDOR - sets first to 0 and second to 1 if true

Each of these compares have specific conditions for setting target registers, and do nothing otherwise. The following is a code example extracted from [1]:

if (status==FOUND &&
    record==search_key &&
    no_error) {<
    do something useful
}

And this is the code generated using parallel compares:

{
    cmp.eq.or   p1, p2 = r0, r0        // initialize p1=p2=1
}  {
    cmp.eq.and  p1, p2 = rs, FOUND
    cmp.eq.and  p2, p2 = rr, rk
    cmp.ne.and  p1, p2 = rn, 0
}

This allows all three cases to be compared in parallel and the appropriate predicate registers to be set in a single clock cycle.

One restriction on the use of parallel compares is that only combinations of the same type of compare may write simultaneously to the same registers.