-
Notifications
You must be signed in to change notification settings - Fork 8.3k
cmake: drop -fno-strict-overflow for better performance #41553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
a5f4748 to
16f5925
Compare
|
Any objection, comment? This switch was apparently planned in 2018's #8924 but did not happen at the time, maybe because Github auto-closed the issue? Please subscribe anyone who may care. |
|
@marc-hb The one remaining issue was fixed, so seems no blockers to submit as non-draft (and just remove the no-strict-overlow)? |
16f5925 to
e7d2bba
Compare
The `-fno-strict-overflow` option blocks some gcc optimizations, removing it in SOF showed a measurable performance improvement: see code review zephyrproject-rtos#41457 of commit 6032501 ("samples/subsys/audio/sof: use -fstrict-overflow for SOF"). Add these optimizations to every Zephyr project beyond the somewhat awkward and maybe temporary way the SOF `samples/` (?) is currently built. There are non-SOF specific discussions in zephyrproject-rtos#41457 BTW. Fixes zephyrproject-rtos#8924 which already had a plan to remove this option in 2018. It looks like some bad Github feature unfortunately auto-closed the issue before it was actually removed. `-fno-strict-overflow` is needed only for code that relies on signed or pointer wrapping, which is an undefined C behavior. Most security policies seem to forbid undefined C behaviors. (Digression: _unsigned_ integer wrapping is _defined_ behavior and expected from any half-decent compiler.) Until gcc version 7, the default -fstrict-overflow value was depending on the -On optimization level. In gcc version 8, the whole feature was greatly simplified: -fnostrict-overflow became a simple alias for `-fwrapv` and `-fwrapv-pointer`: wrapping or no wrapping, period. For the subtle, pre-v8 difference between -fno-strict-overflow and -fwrapv please read this great, pre-v8 intro from the author of strict-overflow: - https://www.airs.com/blog/archives/120 And also: - https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/Code-Gen-Options.html - https://gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/Optimize-Options.html Important quote from Code-Gen-Options.html: > Most of the options have both positive and negative forms; the > negative form of -ffoo is -fno-foo. In the table below, only one of the > forms is listed: the one that is not the default. This means _undefined_ wrapping is the default. So simply removing this zephyr_cc_option() line is enough to switch and great if any project desires overriding it locally: no need to scrutinize the command line order and pray it does the right thing (have a look at the precedence between -f[no]-wrapv and -f[no-]trapv for some of that fun). With gcc, the documented `-Wall` list includes `-Wstrict-overflow=1`: - https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/Warning-Options.html -Wextra does not increase the level of this warning. This warning reports some of the cases where a gcc optimization comes and actually "breaks" signed (and undefined!) wrapping. A real example was just fixed in commit f38c6b6 ("samples: big_http_download: make num_iterations unsigned"). Note this reporting is incomplete and it also assumes that developers look at warnings (not always true) or that CI defines `-DEXTRA_CFLAGS=-Werror` as it should (I am pretty sure I remember Zephyr CI adding -Werror in the past but I'm afraid it's gone right now). Increasing the level to -Wstrict-overflow=2 or more seems to report too many false positives: zephyrproject-rtos#41551 Additional info: - gcc also supports `-ftrapv` to catch signed overflow at _run-time_. - Clang has `-fsanitize=signed-integer-overflow`. I did not test it. https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html - zephyr_cc_option() silently discards its argument for toolchains that fail it (so arguments with typos are silently ignored globally) Signed-off-by: Marc Herbert <marc.herbert@intel.com>
e7d2bba to
002dcc0
Compare
andyross
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes please.
Wait, I did not even include the (fascinating!) git archeology. This flag came directly from... the Linux kernel. No joke, see commit a9b1c74 in 2015:
So here's the original Linux commit in 2009 from Linus: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a137802ee839ace And even before that, in 2009 too: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=68df3755e383
During this dig, found this interesting online tool to test compiler flags and look at the generated assembly: https://godbolt.org/z/odq8h9 |
It does here: zephyr/scripts/pylib/twister/twisterlib.py Line 2141 in 190c9ba
which defaults here: zephyr/scripts/pylib/twister/twisterlib.py Line 2338 in 190c9ba
Line 920 in 190c9ba
|
tejlmand
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm.
Thanks for the digging.
This does not work when compiling I can file a bug, I have detailed and very fast reproduction steps. |
|
Twister fix: |
Thanks to "peer pressure" from @kv2019i , here comes the longest and most-time consuming commit message for removing a single line of code.
The
-fno-strict-overflowoption blocks some gcc optimizations,removing it in SOF showed a measurable performance improvement: see code
review #41457 of commit 6032501 ("samples/subsys/audio/sof: use
-fstrict-overflow for SOF").
Add these optimizations to every Zephyr project beyond the somewhat
awkward and maybe temporary way the SOF
samples/(?) is currentlybuilt. There are non-SOF specific discussions in #41457 BTW.
Fixes #8924 which already had a plan to remove this option in 2018. It
looks like some bad Github feature unfortunately auto-closed the issue
before it was actually removed.
-fno-strict-overflowis needed only for code that relies on signed orpointer wrapping, which is an undefined C behavior. Most security
policies seem to forbid undefined C behaviors.
(Digression: unsigned integer wrapping is defined behavior and
expected from any half-decent compiler.)
Until gcc version 7, the default -fstrict-overflow value was depending
on the -On optimization level. In gcc version 8, the whole feature was
greatly simplified: -fnostrict-overflow became a simple alias for
-fwrapvand-fwrapv-pointer: wrapping or no wrapping, period. Forthe subtle, pre-v8 difference between -fno-strict-overflow and -fwrapv
please read this great, pre-v8 intro from the author of strict-overflow:
And also:
Important quote from Code-Gen-Options.html:
This means undefined wrapping is the default. So simply removing this
zephyr_cc_option() line is enough to switch and great if any project
desires overriding it locally: no need to scrutinize the command line
order and pray it does the right thing (have a look at the precedence
between -f[no]-wrapv and -f[no-]trapv for some of that fun).
With gcc, the documented
-Walllist includes-Wstrict-overflow=1:-Wextra does not increase the level of this warning.
This warning reports some of the cases where a gcc optimization comes
and actually "breaks" signed (and undefined!) wrapping. A real example
was just fixed in commit f38c6b6 ("samples: big_http_download: make
num_iterations unsigned"). Note this reporting is incomplete and it also
assumes that developers look at warnings (not always true) or that CI
defines
-DEXTRA_CFLAGS=-Werroras it should (I am pretty sure Iremember Zephyr CI adding -Werror in the past but I'm afraid it's gone
right now).
Increasing the level to -Wstrict-overflow=2 or more seems to report too
many false positives: #41551
Additional info:
gcc also supports
-ftrapvto catch signed overflow at run-time.Clang has
-fsanitize=signed-integer-overflow. I did not test it.https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
zephyr_cc_option() silently discards its argument for toolchains that
fail it (so arguments with typos are silently ignored globally)
Signed-off-by: Marc Herbert marc.herbert@intel.com