Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent GCC from optimizing out a busy wait loop?

I want to write a C code firmware for Atmel AVR microcontrollers. I will compile it using GCC. Also, I want to enable compiler optimizations (-Os or -O2), as I see no reason to not enable them, and they will probably generate a better assembly way faster than writing assembly manually.

But I want a small piece of code not optimized. I want to delay the execution of a function by some time, and thus I wanted to write a do-nothing loop just to waste some time. No need to be precise, just wait some time.

/* How to NOT optimize this, while optimizing other code? */ unsigned char i, j; j = 0; while(--j) {     i = 0;     while(--i); } 

Since memory access in AVR is a lot slower, I want i and j to be kept in CPU registers.


Update: I just found util/delay.h and util/delay_basic.h from AVR Libc. Although most times it might be a better idea to use those functions, this question remains valid and interesting.


Related questions:

  • How to prevent gcc optimizing some statements in C?
  • Is there a way to tell GCC not to optimise a particular piece of code?
  • How not to optimize away - mechanics of a folly function
like image 938
Denilson Sá Maia Avatar asked Aug 16 '11 18:08

Denilson Sá Maia


People also ask

How do I stop gcc optimization?

Use the command-line option -O0 (-[capital o][zero]) to disable optimization, and -S to get assembly file. Look here to see more gcc command-line options. Show activity on this post.

Is gcc an optimizing compiler?

GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff. As compared to -O , this option increases both compilation time and the performance of the generated code.

What is gcc optimize?

The compiler optimizes to reduce the size of the binary instead of execution speed. If you do not specify an optimization option, gcc attempts to reduce the compilation time and to make debugging always yield the result expected from reading the source code.

How do I know if gcc is not optimized?

Compiler specific pragma gcc provides pragma GCC as a way to control temporarily the compiler behavior. By using pragma GCC optimize("O0") , the optimization level can be set to zero, which means absolutely no optimize for gcc.


2 Answers

I developed this answer after following a link from dmckee's answer, but it takes a different approach than his/her answer.

Function Attributes documentation from GCC mentions:

noinline This function attribute prevents a function from being considered for inlining. If the function does not have side-effects, there are optimizations other than inlining that causes function calls to be optimized away, although the function call is live. To keep such calls from being optimized away, put asm ("");

This gave me an interesting idea... Instead of adding a nop instruction at the inner loop, I tried adding an empty assembly code in there, like this:

unsigned char i, j; j = 0; while(--j) {     i = 0;     while(--i)         asm(""); } 

And it worked! That loop has not been optimized-out, and no extra nop instructions were inserted.

What's more, if you use volatile, gcc will store those variables in RAM and add a bunch of ldd and std to copy them to temporary registers. This approach, on the other hand, doesn't use volatile and generates no such overhead.


Update: If you are compiling code using -ansi or -std, you must replace the asm keyword with __asm__, as described in GCC documentation.

In addition, you can also use __asm__ __volatile__("") if your assembly statement must execute where we put it, (i.e. must not be moved out of a loop as an optimization).

like image 126
Denilson Sá Maia Avatar answered Sep 25 '22 00:09

Denilson Sá Maia


Declare i and j variables as volatile. This will prevent compiler to optimize code involving these variables.

unsigned volatile char i, j; 
like image 45
ks1322 Avatar answered Sep 26 '22 00:09

ks1322