PlatformIO Community

Test fails to start with build option -ffast-math

Hi there!

I am having a weird problem I can’t wrap my head around. I have a Teensy 4.1 project and I am running a test on my code using the test framwork provided byplatformio. So far so good. The test executes as expected and all is fine.
As soon as I add the custom build option -ffast-math to my platformio.ini the test no longer executes. The Teensy seems to not even start. It does not connect to the Serial console or blink the LED. I’ve tried other custom build options like -Wall or -O3 and they seem to work fine.
I somehow feels like a weird bug to me… Am I doing something wrong or has anybody experienced something similar?

Thanks in advance,
Foaly

Well -ffast-math is an unsafe optimization after all. ‘Here be dragons’. Bugs related to -ffast-math are usually closed by the compiler makers as “won’t fix, expected breakage”.

Does a blinky sketch also not work the moment you activate `-ffast-math?

Hmm :neutral_face: I was afraid that something like “here be voodoo territory” might be the case…

Well thats the thing though, my program runs just fine with -ffast-math. I was even able to measure the expected performance increase. Its just once I compile and upload a test to unit test one of the classes, that everything stops working. I tried running an empty test, that does not call any functions of the test framework and that fails as well. Would it be possible that somehow the way test are called is affected?

Then it likely fails in something during the program startup or Unity initialization code (the testing framework). Without a debugger it’ll be hard to know what’s going on when it doesn’t even reach the first line of setup() where you could execute a Serial.println() etc. You did check that, right? If you open a CLI and execute pio test --without-testing -v it will do a (verbose) build and upload of the test firmware, you can inspect its direct serial output via a new serial monitor (Monitor task) then to see if it prints anything at all. The regular output when using the “Test” project task might not show the direct serial output but swallow stuff.

Otherwise you can also use a debugger to debug inside executing unit-tests. The Teensy 4 is however so extremely debugger unfriendly that it’s hard to do that, due to the non-exposed debugger pins for SWD. Unless you learn microsoldering with surgical precision (Teensy 4.1 Uploading with JLink - #18 by sp33).

Thank you for the kind tips! I did have some time and ran a minimal example. This is what my test/test.cpp looks like:

#include <Arduino.h>
void setup() {
    Serial.println("Hello!");
}
void loop() {
    Serial.println("Weeeeeeehhh");
}

and this is what my platformio.ini looks like:

[env:teensy41]
platform = teensy
board = teensy41
framework = arduino
upload_protocol = teensy-cli

If I call pio test the test executes fine and output is generated in the serial monitor.
If I add this line to the bottom of the platform.ini file:

build_flags = -ffast-math

the test stops working. There is no output generated in the monitor and it does not even seem to connect to the serial port. You can still press the reset button to get the teensy into bootloader mode and upload new firmware, but other than that it seems pretty dead.

I did run the pio test --without-testing -v command like you suggested the output looks pretty normal to me… First a bunch of compiler output building the source files, then linking the firmware and then a successfull upload to the device. It’s a bit lengthy but I can also post it here if needed.

I am not very experienced with debugging hardware like this and especially not in microsoldering :smiley: But is there any other way to continue working on this bug? Can I report it somewhere and open an issue maybe?

Per Optimize Options (Using the GNU Compiler Collection (GCC)) the -ffast-math flag is equivalent to -fno-math-errno -funsafe-math-optimizations -ffinite-math-only -fno-rounding-math -fno-signaling-nans -fcx-limited-range -fexcess-precision=fast. Can you delete -ffast-math and subsequently add each flag and see after which flag it crashes? You can maybe still get the perfomance boost without the offending optimization.

Great idea! I will try that later and see what happens. Fortunately it does not really affect my progress, as I can simply turn of -ffast-math while testing and leave it on when running the production build, but the fact that the Teensy does not start at all really seems like a bug to me…
Where would be the correct forum/tracker to report such issues?

Well the obvious one would be https://github.com/platformio/platform-teensy/issues since that is the Platformio integration for teensy. I’m not sure whether they will resolve ‘bugs’ that stem from activating unsafe optimization flags though.

Alrighty so I did go through them all using my minimal example and it seems like there are 3 breaking parameters:

-fno-math-errno # causes the error
-funsafe-math-optimizations # causes the error
-ffinite-math-only # causes the error
-fno-rounding-math # good
-fno-signaling-nans # good
-fcx-limited-range # good
-fexcess-precision=fast # good

I agree that these optimizations might be considered unsafe, but I have seen them being used extensively in production code, so they are not super excotic for high performance code. Also what gets me is that it works fine for a regular build+upload, but calling test breaks. This seems to be a bug to me, even if they are considered unsafe options.
Anyway thank you very much for all your help and ideas! I will open a ticket and see if anything comes of it :slight_smile:

edit: Just FYI here is the issue: https://github.com/platformio/platform-teensy/issues/85