Self Expanding Loops in C

Imagine you want to define a C preprocessor statement like this:

#define NUM_NOPS(i) .....

and later on, in your code:

NUM_NOPS(5);

and you want your preprocessor to roll out the following code:

asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");

This is not as easy as it looks like. One possibility is to use Boost’s Preprocessor Repetition Utility: <boost/preprocessor/repetition/repeat.hpp>. But however, let’s assume you don’t want to use any third party libraries. There is one further possibility. You can use GCC’s unrool loops functionality:

#pragma GCC push_options
#pragma GCC optimize ("unroll-loops")
#pragma GCC optimize ("O2")
void nops() {
 int i = 0;
 for(; i < 10 ; i++) {
   asm volatile("nop");
 }
}
#pragma GCC pop_options

int main(void) {
  nops();
}

You should compile it with:

gcc -c -o test.o -O3 test.c

Having a look at the disassembly proves, that your loop was rolled out:

objdump -d test.o

test.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <nops>:
   0:   90                      nop
   1:   90                      nop
   2:   90                      nop
   3:   90                      nop
   4:   90                      nop
   5:   90                      nop
   6:   90                      nop
   7:   90                      nop
   8:   90                      nop
   9:   90                      nop
   a:   c3                      retq   

Disassembly of section .text.startup:

0000000000000000 <main>:
   0:   31 c0                   xor    %eax,%eax
   2:   e8 00 00 00 00          callq  7 <main+0x7>
   7:   f3 c3                   repz retq 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.