#Prevent the compiler from optimizing certain code

1 messages · Page 1 of 1 (latest)

idle mantle
#

Is there a way to tell the compiler "don't try to optimize this code!" even if the user provides a flag like ReleaseSmall or ReleaseFast?

I build embedded code for the rp2040 and the compiler seems to remove certain critical functions when I use optimization. Using export helps with ReleaseSmall but unfortunately not with ReleaseSafe.

#

I mean ReleaseFast

noble slate
#

you mean ReleaseFast strips functions which are directly referenced?

idle mantle
#

yes

noble slate
#

if that's happening I imagine it's due to the linker script

#

because afaik zig itself shouldn't do that

#

(lto)

#

if you're using a build script, try setting artifact.want_lto = false;

idle mantle
#

thanks, I'll try

mighty chasm
#

it's not that functions are optimized out, it's that unreferenced functions are never compiled to begin with

noble slate
#

that shouldn't be the case with exported functions

#

exported functions are the "referencers"

#

(also comptime blocks, but not in the same way)

mighty chasm
#

like I said, they aren't optimized out

#

Does it reproduce if you just have an exported function that ends up missing? A minimal repro would be helpful.

noble slate
mighty chasm
#

that doesn't even do anything anymore

noble slate
#

alright _ = &function;

#

regardless

#

an export fn foo() void {} should always be analysed

#

so I don't think it's the tree-shaking

mighty chasm
#

well it isn't analysed if it's in an unanalysed file

noble slate
#

ah true

#

would need to do comptime { _ = @import("other-file.zig"); } for that

#

but that wouldn't explain why it varies by release modes

mighty chasm
#

exactly

#

Another thing to check is whether or not it's in the object file.

#

Maybe a file only referenced from a panic handler or something like that?

#

actually, I'll bet it isn't analysed if it's in any unanalysed namespace

idle mantle
#

Maybe I used the wrong terminology. Thing is that I need certain code exactly as I write it. The context is that I need to copy out a second stage boot loader into ram and then execute some functions that are also located in ram to erase/program the connected flash (over SPI). And the end I have to call the bootloader to reconnect with the flash. If the code gets altered in some way or certain functions are not located in ram, then execution will grind to a halt because the processor cant load further program code from flash. I can make I writeup on github and link it here for further info.

noble slate
#

That kind of sounds like you should be using volatile pointers and the like?

idle mantle
#

Don't know if this is the right approach.

#

I use something like pub export fn flash_init() linksection(".time_critical") void all time critical stuff is placed in .data in debug and ReleaseSmall (for release small I also require export).

#

And for ReleaseFast I haven't figured out yet what happens with my code

noble slate
#

export is what forces the compiler to put the function into the output

#

by the way, did .want_lto = false not do anything?

idle mantle
#

sry havent tried yet. will now

idle mantle
#

probably have to fork microzig directly and then play with its build script.

idle mantle
#

Ah shit, at the end a simple KEEP in the linker script did the trick.

noble slate
#

yeah, I suspected it would have to be a linker script being funny

#

mind posting the fix you used and marking the question as answered?

#

(respond to the post with ✅ )