Skip to main content

Timeline for A strange bug in my Arduino ALU

Current License: CC BY-SA 4.0

12 events
when toggle format what by license comment
Jan 6, 2022 at 15:57 comment added timemage @Majenko last night I also had trouble trying to replicate what you saw in folding. But my thoughts on it were more that regardless of what it does, you're asking it to do something undefined and it's hard to have expectations of the optimizer in such cases. I would have tested -fwrapv to check for a change. But, no original problem, no test. As you said not ultimately relevant. About the only thing I thought to add is that the literal's specified base affects whether unsigned types are considered candidates. E.g. 32768 is long, but 0x8000 is unsigned int with 16-bit systems.
Jan 6, 2022 at 12:40 comment added Majenko @EdgarBonet No, I didn't. I wouldn't expect -flto to have any effect since there's no linking. -Os might but who knows? It doesn't really matter anyway, since the exact "why" is irrelevant. Whatever the compiler decides to do or doesn't decide to do, it's still 16 bit integers unless there's a good reason for it to promote to long.
Jan 6, 2022 at 12:33 comment added Edgar Bonet Mmm... weird. The avr-g++ 7.3.0 shipped with Arduino 1.8.15 does the optimization. Did you compile with -Os -flto?
Jan 6, 2022 at 10:51 comment added Majenko @EdgarBonet Not according to the output of avr-gcc -S in my tests. There was a long list of mul instructions to get the result.
Jan 6, 2022 at 8:25 comment added Edgar Bonet Re “It seems avr-gcc isn't clever enough to fold 60 * 1000 as constants into a single 60000 constant”: It can't do that: that would break the rules of the language about implicit typing. But it is clever: it notices feedLimit doesn't change and folds feedLimit*60*1000 into 30528. No runtime mul calls.
Jan 6, 2022 at 0:11 history edited Majenko CC BY-SA 4.0
added 238 characters in body
Jan 6, 2022 at 0:09 comment added Majenko @thebusybee It seems avr-gcc isn't clever enough to fold 60 * 1000 as constants into a single 60000 constant. Instead it does individual mul calls at runtime - <variable> * 60 followed by <result of previous> * 1000. And at each stage it's working with just 2 8 bit registers per value (or just 1 in the case of 60 of course, it's not that stupid) and all results go into two registers every time. Everything truncates and truncates again. But it doesn't think to coalesce literals like that though...
Jan 5, 2022 at 22:32 comment added the busybee I don't think that a folded constant of 60000 is truncated to 27232. Did you check that in compiled code?
Jan 5, 2022 at 16:10 comment added PMF Alternatively, one can use the types with explicit sizes: int8_t, int16_t, int32_t etc. These will have the expected size regardless of what CPU is used.
Jan 5, 2022 at 11:15 vote accept Z Dhillon
Jan 5, 2022 at 11:15 comment added Z Dhillon This was very helpful. Thank you :)
Jan 5, 2022 at 11:07 history answered Majenko CC BY-SA 4.0