Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
907 views
in Technique[技术] by (71.8m points)

c++ - Unroll a loop using a macro that has a goto and a label in it

This question is strictly related to the C or C++ language capabilities. I don't recommend the code below as a design pattern. I don't use it and I don't encourage it. But I'm just curious to improve my knowledge!

I have a define that contains a label and a goto condition.

#define BROP(num, sum)                  
num = rand_lcg(generated);              
if (num % 2)                            
{                                       
rng1:                                   
    generated = rand_lcg(generated);    
    if (generated < 512)                
        sum -= generated;               
    else                                
        goto rng1;                      
}

And later in the code I use it like this:

for (i = 0; i < iterations; i++)
{
    BROP(num, sum);
    BROP(num, sum);
    BROP(num, sum);
    // ...
}

I end up in a situation where the loop gets unrolled and the label gets redefined.

Is there a smart construct I can use to make the compiler rename the label each time the define is "instantiated"?

I know of ALL the alternatives of avoiding this statement but still, I don't know the answer to the question.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You really should make it a do...while loop:

#define BROP(num, sum)  do{                
   bool again = false;                     
   num = rand_lcg(generated);              
   if (num % 2)  {                         
   do { again = false;                     
     generated = rand_lcg(generated);      
     if (generated < 512)                  
           sum -= generated;               
     else                                  
        again = true;                      
   } while(again); } while(0)

See this for the old outerdo{...}while(0) trick.

If you (wrongly) insist on having a label and are using the GCC compiler (or Clang/LLVM which should be compatible on that), you could use local labels extension (i.e. with __label__ ...)

You might also generate the label from the __LINE__ number using concatenation in the preprocessor. Take inspiration from

#define STUPID_LOOP_BIS(Test,Lin) do { 
 lab##Lin: if (Test) goto lab##Lin; } while(0)
#define STUPID_LOOP_AT(Test,Lin) STUPID_LOOP_BIS(Test,Lin)
#define STUPID_LOOP(Test) STUPID_LOOP_AT(Test,__LINE__)

for obscure reasons you need all the three macros!

And use

  STUPID_LOOP(x++ < 100);
  STUPID_LOOP(y-- > 0);

on separate lines. Of course adapt and improve for your need.

You definitely should use and trust more the compiler optimization abilities and have static inline functions. Not every test is compiled to a machine branch (e.g. because of CMOV instructions); not every loop is compiled to a machine loop (e.g. because of loop unrolling). You are probably losing your developer's time, and more importantly, you are disabling optimizations by your tricks (so your code will likely go slower, not faster).

If using GCC or Clang enable optimizations and warnings: so compile with
gcc -Wall -Wextra -O3 -mtune=native


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...