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.
|