#include typedef struct PingPong { int restart; // style 1 int N, i; const char * name; struct PingPong * partner; void * next; // style 2 } PingPong; #define PPCtor( name, N ) { 0, N, 0, name, NULL, NULL } void comain( PingPong * pp ) __attribute__(( noinline )); void comain( PingPong * pp ) { #if 0 if ( __builtin_expect(pp->next != 0, 1) ) goto *pp->next; pp->next = &&cycle; for ( ; pp->i < pp->N; pp->i += 1 ) { #ifdef PRINT printf( "%s %d\n", pp->name, pp->i ); #endif // PRINT asm( "mov %0,%%rdi" : "=m" (pp->partner) ); asm( "mov %rdi,%rax" ); #ifndef OPT #ifdef PRINT asm( "add $16, %rsp" ); #endif // PRINT asm( "popq %rbp" ); #endif // ! OPT #ifdef OPT #ifdef PRINT asm( "popq %rbx" ); #endif // PRINT #endif // OPT asm( "jmp comain" ); cycle: ; } // for #endif // 0 #if 1 static void * states[] = {&&s0, &&s1}; goto *states[pp->restart]; s0: pp->restart = 1; for ( ; pp->i < pp->N; pp->i += 1 ) { #ifdef PRINT printf( "%s %d\n", pp->name, pp->i ); #endif // PRINT asm( "mov %0,%%rdi" : "=m" (pp->partner) ); asm( "mov %rdi,%rax" ); #ifndef OPT #ifdef PRINT asm( "add $16, %rsp" ); #endif // PRINT asm( "popq %rbp" ); #endif // ! OPT #ifdef OPT #ifdef PRINT asm( "popq %rbx" ); #endif // PRINT #endif // OPT asm( "jmp comain" ); s1: ; } // for #endif // 0 } int main() { enum { N = #ifdef PRINT 5 #else 1000000000 #endif // PRINT }; PingPong ping = PPCtor( "ping", N ), pong = PPCtor( "pong", N ); ping.partner = &pong; pong.partner = &ping; comain( &ping ); } // Local Variables: // // tab-width: 4 // // compile-command: "gcc-9 -g -DPRINT PingPong.c" // // End: //