2

We recently upgraded the code to gcc4.3.3 from gcc4.2.4.

void testAndSet(  volatile int*  s, int* val )
{
   __asm__ __volatile__ ( "btsl   $0, %0\n   "
           "jc   bitSet\n   "
           "movl   $0, %1\n   "
           "jmp   returnVector\n"
           "bitSet:\n   "
           "movl   $1, %1\n"
           "returnVector: " : "=m"(*s), "=m"(*val) );
}

Our code now fails with the following errors,

lock.cxx: Assembler messages:
lock.cxx:59: Error: symbol `bitSet' is already defined
lock.cxx:61: Error: symbol `returnVector' is already defined
lock.cxx:59: Error: symbol `bitSet' is already defined
lock.cxx:61: Error: symbol `returnVector' is already defined

Those symbols weren't found anywhere else. (Renaming them causes the same error with the new name).

What's up with this? why do I get the errors twice?

user48956
  • 14,850
  • 19
  • 93
  • 154

3 Answers3

10

Probably the optimizer has changed and is now inlining your testAndSet() function into 2 places. Because you are using global names for your labels, this does not work. You should use local names instead. E.g:

   __asm__ __volatile__ ( "btsl   $0, %0\n   "
           "jc   0f\n   "
           "movl   $0, %1\n   "
           "jmp   1f\n"
           "0:\n   "
           "movl   $1, %1\n"
           "1: " : "=m"(*s), "=m"(*val) );

Local labels are just numbers; to disambiguate cases where there are many labels called "0" you need to use "jmp 0f" for forward jumps and "jmp 0b" for backward jumps.

user9876
  • 10,954
  • 6
  • 44
  • 66
  • Great. That was it. Interestingly, fails with the gcc option -02 but not with -O – user48956 May 18 '09 at 17:40
  • The higher the value to the -O parameter, the more likely it is to inline things; essentially, -O2 and -O3 are going to use optimizations based around increasingly aggressive inlining and loop-unrolling, etc. It might be worth trying '-Os' (optimize without increasing code size) which often provides a good middle-ground optimization. – Jim Dovey May 19 '09 at 02:24
5

This is unrelated to your error, but you could improve your code and avoid branches simply using the setCC instruction:

   __asm__ __volatile__ ( "btsl   $0, %0\n   "
       "mov $0, %1\n"
       "setc %1\n" : "=m"(*s), "=m"(*val) );

The setCC instruction (where CC is one of the condition code flags, analogous to the jCC instruction) sets a byte to 0 or 1 depending on whether or not the given condition was satisfied. Since the destination is a 4-byte value, you need to either preload it with 0 or use the MOVZX instruction to make the upper 3 bytes 0.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
2

Also you may use local label names by adding %= after each local label:

"loop%=:" "\n\t"