# Conditional execution The Hexagon processor uses a conditional execution model based on compare instructions that set predicate bits in one of four 8-bit predicate registers (P0 through P3). These predicate bits can conditionally execute certain instructions. Conditional scalar operations examine only the least-significant bit in a predicate register, while conditional vector operations examine multiple bits in the register. Branch instructions are the main consumers of the predicate registers. ## Scalar predicates Scalar predicates are 8-bit values in conditional instructions to represent truth values: - 0xFF represents true - 0x00 represents false The Hexagon processor provides the four 8-bit predicate registers P0 through P3 to hold scalar predicates ([predicate registers](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#v79-prm-predicate-registers)). Predicate-generating instructions assign the predicate registers and predicate-consuming instructions examine the predicate registers. ### Generating scalar predicates The following instructions generate scalar predicates: - Compare byte, halfword, word, doubleword - Compare single- and double-precision floating point - Classify floating-point value - Compare bitmask - Bounds check - TLB match - Store conditional Scalar predicate-generating instructions | **Syntax** | **Operation** | | --- | --- | | Pd = cmpb.eq(Rs,{Rt,#u8})
Pd = cmph.eq(Rs,{Rt,#s8})
Pd = [!]cmp.eq(Rs,{Rt,#s10})
Pd = cmp.eq(Rss,Rtt)
Pd = sfcmp.eq(Rs,Rt)
Pd = dfcmp.eq(Rss,Rtt)
Copy to clipboard | Equal (signed).


Compare register Rs to Rt or a signed immediate for equality.


Assign Pd the resulting truth value. | | Pd = cmpb.gt(Rs,{Rt,#s8})
Pd = cmph.gt(Rs,{Rt,#s8})
Pd = [!]cmp.gt(Rs,{Rt,#s10})
Pd = cmp.gt(Rss,Rtt)
Pd = sfcmp.gt(Rs,Rt)
Pd = dfcmp.gt(Rss,Rtt)
Copy to clipboard | Greater than (signed).


Compare register Rs to Rt or a signed immediate for signed greater than.


Assign Pd the resulting truth value. | | Pd = cmpb.gtu(Rs,{Rt,#u7})
Pd = cmph.gtu(Rs,{Rt,#u7})
Pd = [!]cmp.gtu(Rs,{Rt,#u9})
Pd = cmp.gtu(Rss,Rtt)
Copy to clipboard | Greater than (unsigned).


Compare register Rs to Rt or an unsigned immediate for unsigned greater than.


Assign Pd the resulting truth value. | | Pd = cmp.ge(Rs,#s8)
Pd = sfcmp.ge(Rs,Rt)
Pd = dfcmp.ge(Rss,Rtt)
Copy to clipboard | Greater than or equal (signed).


Compare register Rs to Rt or a signed immediate for signed greater than or equal.


Assign Pd the resulting truth value. | | Pd = cmp.geu(Rs,#u8)
Copy to clipboard | Greater than or equal (unsigned).


Compare register Rs to an unsigned immediate for unsigned greater than or equal.


Assign Pd the resulting truth value. | | Pd = cmp.lt(Rs,Rt)
Copy to clipboard | Less than (signed).


Compare register Rs to Rt for signed less than.


Assign Pd the resulting truth value. | | Pd = cmp.ltu(Rs,Rt)
Copy to clipboard | Less than (unsigned).


Compare register Rs to Rt for unsigned less than.


Assign Pd the resulting truth value. | | Pd = sfcmp.uo(Rs,Rt)
Pd = dfcmp.uo(Rss,Rtt)
Copy to clipboard | Unordered (signed).


Determine if register Rs or Rt is set to the value NaN.


Assign Pd the resulting truth value. | | Pd=sfclass(Rs,#u5)
Pd=dfclass(Rss,#u5)
Copy to clipboard | Classify value (signed).


Determine if register Rs is set to any of the specified classes.


Assign Pd the resulting truth value. | | Pd = [!]tstbit(Rs,{Rt,#u5})
Copy to clipboard | Test if bit set.


Rt or an unsigned immediate specifies a bit position.


Test if the bit in Rs that is specified by the bit position is set.


Assign Pd the resulting truth value. | | Pd = [!]bitsclr(Rs,{Rt,#u6})
Copy to clipboard | Test if bits clear.


Rt or an unsigned immediate specifies a bitmask.


Test if the bits in Rs that are specified by the bitmask are all clear.


Assign Pd the resulting truth value. | | Pd = [!]bitsset(Rs,Rt)
Copy to clipboard | Test if bits set.


Rt specifies a bitmask.


Test if the bits in Rs that are specified by the bitmask are all set.


Assign Pd the resulting truth value. | | memw_locked(Rs,Pd) = Rt
memd_locked(Rs,Pd) = Rtt
Copy to clipboard | Store conditional.


If no other atomic operation has been performed at the address (atomicity is ensured),
perform the store to the word at address Rs.


Assign Pd the resulting truth value. | | Pd = boundscheck(Rs,Rtt)
Copy to clipboard | Bounds check.


Determine if Rs falls in the numeric range defined by Rtt.


Assign Pd the resulting truth value. | | Pd = tlbmatch(Rss,Rt)
Copy to clipboard | Determine if TLB entry in Rss matches the ASID:PPN specified in Rt.


Assign Pd the resulting truth value. | Note One of the compare instructions (cmp.eq) includes a variant that stores a binary predicate value (0 or 1) in a general register not a predicate register. ### Consuming scalar predicates Certain instructions can be conditionally executed based on the value of a scalar predicate (or alternatively specify a scalar predicate as an input to their operation). The conditional instructions that consume scalar predicates examine only the least-significant bit of the predicate value. In the simplest case, this bit value directly determines whether the instruction executes: - 1 indicates that the instruction executes - 0 indicates that the instruction does not execute If a conditional instruction includes the operator ! in its predicate expression, the logical negation of the bit value determines whether the instruction is executed. Conditional instructions are expressed in assembly language with the instruction prefix if (*pred\_expr*), where *pred\_expr* specifies the predicate expression. For example: if (P0) jump target // Jump if P0 is true if (!P2) R2 = R5 // Assign register if !P2 is true if (P1) R0 = sub(R2,R3) // Conditionally subtract if P1 is true if (P2) R0 = memw(R2) // Conditionally load word if P2 is true Copy to clipboard The following instructions can be used as conditional instructions: - Jumps and calls ([software branches](https://docs.qualcomm.com/doc/80-N2040-60/topic/program-flow.html#v79-prm-software-branches)) - Load and store instructions ([conditional loadstores](https://docs.qualcomm.com/doc/80-N2040-60/topic/memory.html#v79-prm-conditional-loadstores)) - Logical instructions (including AND/OR/XOR) - Shift halfword - 32-bit add/subtract by register or short immediate - Sign and zero extend - 32-bit register transfer and 64-bit combine word - Register transfer immediate - Deallocate frame and return When a conditional load or store executes and the predicate expression is false, the instruction is canceled (including any exceptions that might occur). For example, if a conditional load uses an address with a memory permission violation, and the predicate expression is false, the load does not execute and the exception is not raised. The mux instruction accepts a predicate as one of its basic operands: Rd = mux(Ps,Rs,Rt) Copy to clipboard The mux instruction selects either Rs or Rt based on the least significant bit in Ps. If the least- significant bit in Ps is a 1, Rd is set to Rs, otherwise it is set to Rt. ### Auto-AND predicates If multiple compare instructions in a packet write to the same predicate register, the result is the logical AND of the individual compare results. For example: { P0 = cmp(A) // If A && B, jump P0 = cmp(B) if (P0.new) jump:T taken_path } Copy to clipboard To perform the corresponding OR operation, the following instructions can compute the negation of an existing compare (using De Morgan’s law): - Pd = !cmp.{eq,gt}(Rs, {#s10,Rt}) - Pd = !cmp.gtu(Rs, {#u9,Rt}) - Pd = !tstbit(Rs, {#u5,Rt}) - Pd = !bitsclr(Rs, {#u6,Rt}) - Pd = !bitsset(Rs,Rt) Auto-AND predicates have the following restrictions: - If a packet contains endloopN, it cannot perform an auto-AND with predicate register P3. - If a packet contains a register transfer from a general register to a predicate register, no other instruction in the packet can write to the same predicate register. As a result, a register transfer to P3:0 or C5:4 cannot be grouped with any other predicate-writing instruction. - The instructions spNloop0, decbin, tlbmatch, memw\_locked, memd\_locked, a, sub:carry, sfcmp, and dfcmp cannot be grouped with another instruction that sets the same predicate register. Note A register transfer from a predicate register to a predicate register has the same auto-AND behavior as a compare instruction. ### Dot-new predicates The Hexagon processor can generate and use a scalar predicate in the same [instruction packet](https://docs.qualcomm.com/doc/80-N2040-60/topic/instructions.html#v79-prm-instruction-packets). This feature is expressed in assembly language by appending the suffix “.new” to the specified predicate register. For example: if (P0.new) R3 = memw(R4) Copy to clipboard The following C statement and the corresponding assembly code that is generated from it by the compiler is an example of how to use dot-new predicates. **C statement** if (R2 == 4) R3 = *R4; else R5 = 5; Copy to clipboard **Assembly code** { P0 = cmp.eq(R2,#4) if (P0.new) R3 = memw(R4) if (!P0.new) R5 = #5 } Copy to clipboard In this example, a scalar predicate is generated and then consumed twice within the same instruction packet. The following conditions apply to using dot-new predicates: - An instruction in the same packet must generate the predicate. The assembler normally enforces this restriction, but if the processor executes a packet that violates this restriction, the execution result is undefined. - A single packet can contain both the dot-new and normal forms of predicates. The normal form examines the old value in the predicate register, rather than the newly-generated value. For example: { P0 = cmp.eq(R2,#4) if (P0.new) R3 = memw(R4) // Use newly-generated P0 value if (P0) R5 = #5 // Use previous P0 value } Copy to clipboard ### Dependency constraints Two instructions in an instruction packet should not write to the same destination register ([dependency constraints](https://docs.qualcomm.com/doc/80-N2040-60/topic/instructions.html#v79-prm-instructions-dependency-constraints)). An exception to this rule is when the two instructions are conditional, and only one of them ever has the predicate expression value true when the packet executes. For example, the following packet is valid as long as P2 and P3 never both evaluate to true when the packet is executed: { if (P2) R3 = #4 // P2, P3, or both must be false if (P3) R3 = #7 } Copy to clipboard Because predicate values change at runtime, the programmer is responsible for ensuring that such packets are always valid during program execution. If they are invalid, the processor takes the following actions: - When writing to general registers, an error exception is raised. - When writing to predicate or control registers, the result is undefined. ## Vector predicates The predicate registers are also used for conditional vector operations. Unlike scalar predicates, vector predicates contain multiple truth values which are generated by vector predicate- generating operations. For example, a vector compare instruction compares each element of a vector and assigns the compare results to a predicate register. Each bit in the predicate vector contains a truth value indicating the outcome of a separate compare performed by the vector instruction. The vector mux instruction uses a vector predicate to selectively merge elements from two separate vectors into a single destination vector. This operation is useful for enabling the vectorization of loops with control flow (branches). The vector instructions that use predicates are described in the following sections. ### Vector compare A vector compare instruction inputs two 64-bit vectors, performs separate compares for each pair of vector elements, and generates a predicate value which contains a bit vector of truth values. In [vector byte compare](https://docs.qualcomm.com/doc/80-N2040-60/topic/conditional-execution.html#v79-vector-byte-compare) two 64-bit vectors of bytes (contained in Rss and Rtt) are being compared. The result is assigned as a vector predicate to the destination register Pd. In the example vector predicate shown in [vector byte compare](https://docs.qualcomm.com/doc/80-N2040-60/topic/conditional-execution.html#v79-vector-byte-compare), every other compare result in the predicate is true (for example, 1). pic_vcmpub Page-1 Sheet.1 Pd Pd Rectangle.163 1 1 Rectangle.164 0 0 Rectangle.165 1 1 Rectangle.166 0 0 Rectangle.167 1 1 Rectangle.168 0 0 Rectangle.169 1 1 Rectangle.170 0 0 Sheet.18 0 0 Sheet.20 7 7 Sheet.21 Rss Rss Rectangle.130 Sheet.23 Rtt Rtt Sheet.24 Rectangle.25 Rectangle.134 Rectangle.27 Rectangle.136 Rectangle.137 Rectangle.30 Rectangle.31 Rectangle.140 Rectangle.141 Rectangle.142 Rectangle.143 Rectangle.36 Rectangle.37 Rectangle.38 Rectangle.39 Sheet.40 Sheet.41 Rounded rectangle cmp cmp Sheet.43 Sheet.44 Sheet.45 Rounded rectangle.16 cmp cmp Sheet.47 Sheet.48 Sheet.49 Rounded rectangle.21 cmp cmp Sheet.51 Sheet.52 Sheet.53 Rounded rectangle.30 cmp cmp Sheet.55 Sheet.56 Sheet.57 Rounded rectangle.44 cmp cmp Sheet.59 Sheet.60 Sheet.61 Rounded rectangle.48 cmp cmp Sheet.63 Sheet.64 Sheet.65 Rounded rectangle.52 cmp cmp Sheet.67 Sheet.68 Sheet.69 Rounded rectangle.56 cmp cmp **Vector byte compare** [Vector halfword compare](https://docs.qualcomm.com/doc/80-N2040-60/topic/conditional-execution.html#v79-vector-halfword-compare) shows how a vector halfword compare generates a vector predicate. Two 64-bit vectors of halfwords are being compared. The result is assigned as a vector predicate to the destination register Pd. Because a vector halfword compare yields only four truth values, each truth value is encoded as two bits in the generated vector predicate. pic_vcmpub Page-1 Sheet.1 Rss Rss Rectangle.72 Rectangle.73 Rectangle.74 Rectangle.75 Sheet.6 Rtt Rtt Rectangle.50 Rectangle.51 Rectangle.52 Rectangle.80 Sheet.11 Sheet.12 Sheet.13 Sheet.14 Sheet.15 Sheet.16 Sheet.17 Sheet.18 Sheet.19 Sheet.20 Sheet.21 Sheet.22 Rectangle.119 1 1 Rectangle.120 1 1 Rectangle.121 0 0 Rectangle.122 0 0 Rectangle.123 1 1 Rectangle.124 1 1 Rectangle.125 0 0 Rectangle.126 0 0 Sheet.39 0 0 Sheet.41 7 7 Sheet.42 Sheet.43 Sheet.44 Sheet.45 Rounded rectangle.62 cmp cmp Rounded rectangle.63 cmp cmp Rounded rectangle.64 cmp cmp Rounded rectangle.65 cmp cmp Sheet.50 Pd Pd **Vector halfword compare** ### Vector mux instruction A vector mux instruction conditionally selects the elements from two vectors. The instruction takes as input two source vectors and a predicate register. For each byte in the vector, the corresponding bit in the predicate register is used to choose from one of the two input vectors. The combined result is written to the destination register. pic_addh Page-1 Sheet.1 Rss Rss Rectangle.22 Sheet.3 Rtt Rtt Sheet.4 Rectangle.25 Rectangle.26 Rectangle.27 Rectangle.28 Rectangle.29 Rectangle.30 Rectangle.31 Rectangle.32 Rectangle.33 Rectangle.34 Rectangle.15 Rectangle.16 Rectangle.37 Rectangle.38 Rectangle.39 Sheet.20 Sheet.21 Rounded rectangle.42 mux mux Sheet.23 Sheet.24 Sheet.25 Sheet.26 Sheet.27 Sheet.28 Sheet.29 Sheet.30 Sheet.31 Sheet.32 Sheet.33 Sheet.68 Sheet.69 Sheet.70 Rectangle.199 Rectangle.200 Rectangle.201 Rectangle.202 Rectangle.203 Rectangle.204 Rectangle.205 Rectangle.206 Rounded rectangle.46 mux mux Rounded rectangle.50 mux mux Rounded rectangle.54 mux mux Rounded rectangle.58 mux mux Rounded rectangle.90 mux mux Rounded rectangle.94 mux mux Rounded rectangle.98 mux mux Sheet.88 P[6] P[6] Sheet.89 Sheet.90 Sheet.91 P[5] P[5] Sheet.92 Sheet.93 Sheet.94 P[4] P[4] Sheet.95 Sheet.96 Sheet.97 P[3] P[3] Sheet.98 Sheet.99 Sheet.100 P[2] P[2] Sheet.101 Sheet.102 Sheet.103 P[1] P[1] Sheet.104 Sheet.105 Sheet.106 P[0] P[0] Sheet.107 Sheet.108 Sheet.109 P[7] P[7] Sheet.110 Sheet.111 Sheet.112 Sheet.113 Sheet.114 Sheet.115 Sheet.116 Sheet.117 Sheet.118 Sheet.119 Rdd Rdd **Vector mux instruction** Vector mux instruction | **Syntax** | **Operation** | | --- | --- | | Rdd = vmux(Ps,Rss,Rtt) | Select bytes from Rss and Rtt | Changing the order of the source operands in a mux instruction enables formation of both senses of the result. For example: R1:0 = vmux(P0,R3:2,R5:4) // Choose bytes from R3:2 if true R1:0 = vmux(P0,R5:4,R3:2) // Choose bytes from R3:2 if false Copy to clipboard Note By replicating the predicate bits generated by word or halfword compares, the vector mux instruction can select words or halfwords. ### Using vector conditionals Vector conditional support is used to vectorize loops with conditional statements. Consider the following C statement: for (i=0; i<8; i++) { if (A[i]) { B[i] = C[i]; } } Copy to clipboard Assuming arrays of bytes, this code can be vectorized as follows: R1:0 = memd(R_A) // R1:0 holds A[7]-A[0] R3 = #0 // Clear R3:2 R2 = #0 P0 = vcmpb.eq(R1:0,R3:2) // Compare bytes in A to zero R5:4 = memd(R_B) // R5:4 holds B[7]-B[0] R7:6 = memd(R_C) // R7:6 holds C[7]-C[0] R3:2 = vmux(P0,R7:6,R5:4) // if A[i]) B[i]=C[i] memd(R_B) = R3:2 // store B[7]-B[0] Copy to clipboard ## Predicate operations The Hexagon processor provides a set of operations for manipulating and moving predicate registers. **Table 6-3 Predicate register instructions** | **Syntax** | **Operation** | | --- | --- | | `Pd = Ps` | Transfer predicate Ps to Pd | | `Pd = Rs` | Transfer register Rs to predicate Pd | | `Rd = Ps` | Transfer predicate Ps to register Rd | | `Pd = and(Ps,[!]Pt)` | Set Pd to bitwise AND of Ps and [NOT] Pt | | `Pd = or(Ps,[!]Pt)` | Set Pd to bitwise OR of Ps and [NOT] Pt | | `Pd = and(Ps, and(Pt,[!]Pu)` | Set Pd to AND of Ps and (AND of Pt and [NOT] Pu) | | `Pd = and(Ps, or(Pt,[!]Pu)` | Set Pd to AND of Ps and (OR of Pt and [NOT] Pu) | | `Pd = or(Ps, and(Pt,[!]Pu)` | Set Pd to OR of Ps and (AND of Pt and [NOT] Pu) | | `Pd = or(Ps, or(Pt,[!]Pu)` | Set Pd to OR of Ps and (OR of Pt and [NOT] Pu) | | `Pd = not(Ps)` | Set Pd to bitwise inversion of Ps | | `Pd = xor(Ps,Pt)` | Set Pd to bitwise exclusive OR of Ps and Pt | | `Pd = any8(Ps)` | Set Pd to 0xFF if any bit in Ps is 1, 0x00 otherwise | | `Pd = all8(Ps)` | Set Pd to 0x00 if any bit in Ps is 0, 0xFF otherwise | Note These instructions belong to instruction class CR. Predicate registers can be transferred to and from the general registers either individually or as register quadruples ([predicate registers](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#v79-prm-predicate-registers)). Last Published: Jan 16, 2025 [Previous Topic Memory](https://docs.qualcomm.com/bundle/publicresource/80-N2040-60/topics/memory.md) [Next Topic Software stack](https://docs.qualcomm.com/bundle/publicresource/80-N2040-60/topics/software-stack.md)