Lably
Skip to content

Predication (computer architecture)

  • 7 min read
  • 5 chapters

Related on Lably

Through Conditional (computer programming), Control flow and Execution (computing)

Vector processors, some SIMD ISAs (such as AVX2 and AVX-512) and GPUs in general make heavy use of predication, applying one bit of a conditional mask vector to the corresponding elements in the vector registers being processed, whereas scalar predication in scalar instruction sets only need the one predicate bit. Where predicate masks become particularly powerful in vector processing is if an array of condition codes, one per vector element, may feed back into predicate masks that are then applied to subsequent vector instructions.

Overview

Most computer programs contain conditional code, which will be executed only under specific conditions depending on factors that cannot be determined beforehand, for example depending on user input. As the majority of processors simply execute the next instruction in a sequence, the traditional solution is to insert branch instructions that allow a program to conditionally branch to a different section of code, thus changing the next step in the sequence. This was sufficient until designers began improving performance by implementing instruction pipelining, a method which is slowed down by branches. For a more thorough description of the problems which arose, and a popular solution, see branch predictor.

Luckily, one of the more common patterns of code that normally relies on branching has a more elegant solution. Consider the following pseudocode:

<span id="mwLw"></span><span class="k" id="mwMA">if</span><span class="w" id="mwMQ"> </span><span class="n" id="mwMg">condition</span> <span class="w" id="mwMw"> </span><span class="p" id="mwNA">{</span><span class="n" id="mwNQ">do_something</span><span class="p" id="mwNg">}</span> <span class="k" id="mwNw">else</span> <span class="w" id="mwOA"> </span><span class="p" id="mwOQ">{</span><span class="n" id="mwOg">do_something_else</span><span class="p" id="mwOw">}</span>

On a system that uses conditional branching, this might translate to machine instructions looking similar to:

<span id="mwQg"></span><span class="w" id="mwQw"> </span><span class="n" id="mwRA">branch_if_condition_to</span><span class="w" id="mwRQ"> </span><span class="n" id="mwRg">label1</span> <span class="w" id="mwRw"> </span><span class="n" id="mwSA">do_something_else</span> <span class="w" id="mwSQ"> </span><span class="n" id="mwSg">branch_always_to</span><span class="w" id="mwSw"> </span><span class="n" id="mwTA">label2</span> <span class="nl" id="mwTQ">label1</span><span class="p" id="mwTg">:</span> <span class="w" id="mwTw"> </span><span class="n" id="mwUA">do_something</span> <span class="nl" id="mwUQ">label2</span><span class="p" id="mwUg">:</span> <span class="w" id="mwUw"> </span><span class="p" id="mwVA">...</span>

With predication, all possible branch paths are coded inline, but some instructions execute while others do not. The basic idea is that each instruction is associated with a predicate (the word here used similarly to its usage in predicate logic) and that the instruction will only be executed if the predicate is true. The machine code for the above example using predication might look something like this:

<span id="mwWw"></span><span class="p" id="mwXA">(</span><span class="n" id="mwXQ">condition</span><span class="p" id="mwXg">)</span><span class="w" id="mwXw"> </span><span class="n" id="mwYA">do_something</span> <span class="p" id="mwYQ">(</span><span class="n" id="mwYg">not</span><span class="w" id="mwYw"> </span><span class="n" id="mwZA">condition</span><span class="p" id="mwZQ">)</span><span class="w" id="mwZg"> </span><span class="n" id="mwZw">do_something_else</span>

Besides eliminating branches, less code is needed in total, provided the architecture provides predicated instructions. While this does not guarantee faster execution in general, it will if the do_something and do_something_else blocks of code are short enough.

Predication's simplest form is partial predication, where the architecture has conditional move or conditional select instructions. Conditional move instructions write the contents of one register over another only if the predicate's value is true, whereas conditional select instructions choose which of two registers has its contents written to a third based on the predicate's value. A more generalized and capable form is full predication. Full predication has a set of predicate registers for storing predicates (which allows multiple nested or sequential branches to be simultaneously eliminated) and most instructions in the architecture have a register specifier field to specify which predicate register supplies the predicate.

Sign in to keep reading

4 more chapters are free with a Lably account.

More in Computing and communication