# 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)