# Coding practices

This chapter describes recommended coding practices when using the
LLVM compilers. These practices typically result in the compiler
generating more optimized code.

## Use int types for loop counters

We strongly recommend using an int type for loop counters, which
results in the compiler generating more efficient code. If the code
uses a non-int type, the compiler must insert zero and
sign-extensions to abide by C rules. For example, we do not recommend
the following code:

extern int A[30], B[30];
    for (short int ctr = 0; ctr < 30; ++ctr) {
       A[ctr] = B[ctr] + 55;
    }
    Copy to clipboard

Use this code instead:

extern int A[30], B[30];
    for (int ctr = 0; ctr < 30; ++ctr) {
       A[ctr] = B[ctr] + 55;
    }
    Copy to clipboard

## Mark function arguments as restrict (if possible)

LLVM supports the restrict keyword for function arguments. Using
restrict on a pointer passed in as a function argument indicates to
the compiler that the pointer will be used exclusively to dereference
the address it points at. This allows the compiler to enable more
aggressive optimizations on memory accesses.

Note

When using the restrict keyword, you must ensure that the
restrict condition holds for all calls made to that function. If an
argument is erroneously marked as restrict, the compiler might
generate incorrect code.

## Do not pass or return structures by value

We strongly recommend that structures are passed to (and returned
from) functions by reference and not by value.

If a structure is passed to a function by value, the compiler must
generate code that makes a copy of the structure during application
runtime. This can be extremely inefficient, and will reduce the
performance of the compiled code. For this reason, we recommend that
structures be passed by pointer.

For example, the following code is inefficient:

struct S {
       int z;
       int y[50];
       char *x;
       long int w[40];
    };
    int bar(struct S arg1) {
       ...
    }
    int baz() {
       struct S s;
       ...
       bar(s);
    }
    Copy to clipboard

While this code is much more efficient:

struct S {
       int z;
       int y[50];
       char *x;
       long int w[40];
    };
    int bar(struct *S arg1) {
       /* Access z here using 'arg1->z' (instead of 'arg1.z') */
       ...
    }
    int baz() {
       struct S s;
       ...
       bar(&s);
    }
    Copy to clipboard

Alternatively, in C++, the efficient code can be simplified by using
reference parameters:

struct S {
       int z;
       int y[50];
       char *x;
       long int w[40];
    };
    int bar(struct &S arg1) {
       ...
    }
    int baz() {
       struct S;
       ... populate elements of S ...
       bar(S);
    }
    Copy to clipboard

## Avoid using inline assembly

Using inline assembly snippets in C files is strongly discouraged for
two reasons:

- Inline assembly snippets are extremely difficult to write correctly.
For instance, omitting the input, output, or clobber parameters
frequently leads to incorrect code. The resulting failure can be
extremely difficult to debug.
- Inline assembly is not portable across processor versions. If you
need to emit a specific assembly instruction, we recommend using a
compiler intrinsic instead of inline assembly.

Intrinsics are easy to insert in a C file, and they are portable
across processor versions. If intrinsics are insufficient, add a new
function written in assembly. The assembly function should be called
from C code.

Last Published: May 10, 2024

[Previous Topic
Port code from GCC](https://docs.qualcomm.com/bundle/publicresource/80-VB419-99/topics/port_code_from_gcc.md) [Next Topic
Language compatibility](https://docs.qualcomm.com/bundle/publicresource/80-VB419-99/topics/language_compatibility.md)