4.5. Assertions

The _nassert intrinsic generates no code and so is not a typical compiler intrinsic. Instead, it tells the compiler that the expression declared with the assert function is true. It can be used to assert that certain conditions are true, which in turn can be used by the compiler during its optimizations.

Warning

Code can fail at runtime if the condition specified in the _nassert is not true.

Listing 4.12 illustrates an example of using _nassert. In this case, the programmer is guaranteeing that the loop executes at least once and count is a multiple of 4. This enables the compiler to avoid generating code to check for count == 0 and peeled iterations during unrolling.

Listing 4.12 Using nassert to avoid generating unnecessary checks
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <stdint.h>

int16_t sum(int16_t* input, int16_t count)
{
    int16_t sum = 0;
    int16_t i   = 0;

    _nassert(count > 0 && count % 4 == 0);

    for (i = 0; i < count; i++)
        sum += input[i];

    return sum;
}

Table 4.6 shows the assembly generated without and with the _nassert.

Table 4.6 Assembly comparison

Asm generated with _nassert (loop is unrolled 4x)

Asm generated without _nassert (loop is unrolled 2x)

||sum||:
        MOV       AH,AL
        MOVB      AL,#0
        ASR       AH,2
        ADDB      AH,#-1
        MOVZ      AR6,AH
||$C$L1||:
        ADD       AL,*XAR4++
        ADD       AL,*XAR4++
        ADD       AL,*XAR4++
        ADD       AL,*XAR4++
        BANZ      ||$C$L1||,AR6--
        LRETR
||sum||:
        MOV       AH,AL
        MOVB      XAR7,#0
        BF        ||$C$L4||,LEQ
        CMPB      AH,#2
        BF        ||$C$L1||,GEQ
        MOV       PL,#0
        BF        ||$C$L3||,UNC
||$C$L1||:
        AND       AH,AH,#0xfffe
        MOV       PL,AH
        MOVL      XAR5,XAR4
        MOV       AH,AL
        ASR       AH,1
        ADDB      AH,#-1
        MOVZ      AR6,AH
||$C$L2||:
        MOV       AH,AR7
        ADD       AH,*XAR5++
        ADD       AH,*XAR5++
        MOVZ      AR7,AH
        BANZ      ||$C$L2||,AR6--
||$C$L3||:
        TBIT      AL,#0
        BF        ||$C$L4||,NTC
        MOVL      ACC,XAR4
        SETC      SXM
        ADD       ACC,PL
        MOVL      XAR4,ACC
        MOV       AL,AR7
        ADD       AL,*+XAR4[0]
        MOVZ      AR7,AL
||$C$L4||:
        MOV       AL,AR7
        LRETR