C compilers are getting more advanced, but there is always a trade-off between speed and code size. Compiled code can be faster or smaller, but not both. So you have to choose which part is more important speed or code size.
The Increase in microcontroller code efficiency can be done in many ways. Don’t trust compiler optimization features, as they might not be as effective as you expect. It is better to grab some profiler and inspect what parts of your code take the most time and size.
It is better to follow some techniques that may reduce code execution time and increase microcontroller code efficiency:
Use keyword inline to any function you want. This makes the compiler not call a function, but to copy the function code into the desired place. This technique is effective when the inline function is frequently called and contains a few code lines. On the other hand, bigger functions can fill your code size limit very fast.
Table lookups are implemented by using a switch statement. Be smart using a switch statement. Put most likely sentences firsts and last likely sentences last. This may reduce the execution time.
If there much work to do within switch cases might be it is better to replace the switch sentence with a table of pointers to functions.
Assembly is always the best-optimized code (well, not for all programmers). You can make code efficient as you need. But sometimes, C or C++ compilers produce better code than the average programmer. So decide this is worth your time to mess up with assembly. But using inline assembly can significantly increase microcontroller code efficiency.
Use register values
Register keyword can be used when declaring variables. This makes the compiler assign a variable to a general-purpose register beside a stack. Use this keyword to most frequently used variables.
Consider global variables
Computer software development is strictly recommended to use local variables to make code more universal and readable. But in embedded systems, it is more efficient to use global variables as this eliminates the need to push parameters to the stack before the function call popup. You increase the speed of your code but lose modularity.
Polling vs. Interrupt
In embedded systems, interrupt routines are used frequently. So sometimes might be to use polling routines to communicate the hardware. In some cases, the interrupts cause latencies. Using polling also leads to less modularity.
Don’t use float point arithmetic
Floating-point arithmetic is a killer of microcontroller code efficiency unless your design includes FPU. Otherwise, the compiler uses software subroutines to simulate floating point arithmetics. Many techniques let you avoid using floating-point operations like byte shift instead of divide.