arduino / arduino/ArduinoCore-avr
Inline library functions based on constant-ness of arguments
- Dominant language
- C
- Stars
- 1.5k
- Forks
- 1.1k
- PR merge metrics
- No merged PRs in 30d
Description
Many fundamental functions could be effectively inlined without causing significant binary size increase if they could be inlined only if certain arguments were constants, as in such a case significant parts of the function body would turn into dead code, and could be therefore eliminated.
Samples of this kind of functions include: `digitalWrite`, `digitalRead`, `analogWrite`, `analogRead`, `pinMode`, `turnOffPWM` and so on.
GCC apparently does not do this automatically, but it can be done. One way is as follows (let's take [`analogWrite`](https://github.com/arduino/ArduinoCore-avr/blob/3055c1efa3c6980c864f661e6c8cc5d5ac773af4/cores/arduino/wiring_analog.c#L104-L293) as an example):
```c
void analogWrite(uint8_t pin, int val)
{
// body...
}
```
If we accept to turn analogWrite into a macro, we can rewrite it as follows:
```c
#define analogWrite(pin, val) \
( __builtin_constant_p(pin) ? _analogWrite_inline((pin), (val)) : _analogWrite((pin), (val)) )
void _analogWrite(uint8_t pin, int val) {
_analogWrite_inline(pin, val);
}
inline __attribute__((__always_inline__)) _analogWrite_inline(uint8_t pin, int val) {
// body...
}
```
In this way, callsites that have a non-constant `pin` argument will get the regular `_analogWrite` function as they do today without causing any increase in binary size, whereas callsites that have a constant `pin` argument will get an inlined version, and constant propagation will take care of eliminating dead code. If done consistently, this would allow GCC to turn a call to e.g. `analogWrite(PIN, HIGH)` into the following:
```c
uint8_t oldSREG = SREG;
cli();
*reg |= regbit; // reg, regbit are constant
SREG = oldSREG;
uint8_t oldSREG = SREG;
cli();
*out |= outbit; // out, outbit are constant
SREG = oldSREG;
```
(that does not take much more space than the original call and that, potentially, opens up the potential, if all callsites use constant args, for `_analogWrite` and related functions to be completely omitted from the final binary)
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with cores/arduino/wiring_analog.c and the analogWrite implementation linked in the issue, then compare it with the related digitalWrite, digitalRead, analogRead, pinMode, and turnOffPWM functions. Investigate how constant and non-constant arguments are handled, and verify that constant call sites can eliminate dead code without increasing binary size for regular calls.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- embedded-iot
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100