bug in 1.35's sp_counted_base_gcc_sparc.hpp

The cas _asm_ instruction for the gcc/sparc environment has a slight flaw: it does not prevent the gcc compiler from generating assembly that contains a invalid register/offset. In other words, the existing _asm_ can cause gcc to generate something like: cas [%i0+80], %i1, %i2 the relative offset is an illegal address mode for cas instruction. I'm not a sparc assembly guy, by any stretch of the imagination, but doing some reading at http://blogs.sun.com/wesolows/entry/gcc_inline_assembly_part_2 would seem to indicate that this code: inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) { __asm__ __volatile__( "cas %0, %2, %1" : "+m" (*dest_), "+r" (swap_) : "r" (compare_) : "memory" ); return swap_; } is not exactly correct. When using -O3 optimization option to gcc, the aforementioned "bad" cas instruction is generated. Base upon how much code there is surrounding the call to compare_and_swap(), different combinations of register allocation occurs and may or may not hide this problem. I'm done some experimenting and with the following code, gcc seems to generate the proper code: inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) { __asm__ __volatile__( "cas [%2], %3, %0" : "=&r" (swap_) : "0" (swap_), "r" (dest_), "r" (compare_) : "memory" ); return swap_; } Somebody with more experience in sparc should look this over. If it's good (or a better way), it would be nice to get it into the next version of boost that contains support for boost/detail/sp_counted_base_gcc_sparc.hpp. Jerry Lawson

Jerry Lawson wrote:
The cas _asm_ instruction for the gcc/sparc environment has a slight flaw: it does not prevent the gcc compiler from generating assembly that contains a invalid register/offset. In other words, the existing _asm_ can cause gcc to generate something like:
cas [%i0+80], %i1, %i2
the relative offset is an illegal address mode for cas instruction.
I'm not a sparc assembly guy, by any stretch of the imagination, but doing some reading at http://blogs.sun.com/wesolows/entry/gcc_inline_assembly_part_2 would seem to indicate that this code:
inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) { __asm__ __volatile__( "cas %0, %2, %1"
: "+m" (*dest_), "+r" (swap_) : "r" (compare_) : "memory" );
return swap_; }
is not exactly correct. When using -O3 optimization option to gcc, the aforementioned "bad" cas instruction is generated.
Sounds like a gcc bug. Which versions of gcc have you tried?
I'm done some experimenting and with the following code, gcc seems to generate the proper code:
inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) { __asm__ __volatile__( "cas [%2], %3, %0"
: "=&r" (swap_) : "0" (swap_), "r" (dest_), "r" (compare_) : "memory" );
return swap_; }
We might be able to use that as a fix if it works, but it's not correct in principle. One case where it fails is on 64 bit machines that use 32 bit pointers. This may not be a problem on SPARCs though.

Sounds like a gcc bug. Which versions of gcc have you tried?
I have gcc 4.1.1 on a solaris10 sparv9 machine (64 bit).
I'm done some experimenting and with the following code, gcc seems to generate the proper code:
inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) { __asm__ __volatile__( "cas [%2], %3, %0"
: "=&r" (swap_) : "0" (swap_), "r" (dest_), "r" (compare_) : "memory" );
return swap_; }
We might be able to use that as a fix if it works, but it's not correct in principle. One case where it fails is on 64 bit machines that use 32 bit pointers. This may not be a problem on SPARCs though.
I'm not sure how one would go about using 32-bit pointers on a 64-bit machine. Is that a gcc option or a hardwired thing in the processor?
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Jerry Lawson wrote:
Sounds like a gcc bug. Which versions of gcc have you tried?
I have gcc 4.1.1 on a solaris10 sparv9 machine (64 bit).
Can you please try reporting it on the GCC Bugzilla?
I'm not sure how one would go about using 32-bit pointers on a 64-bit machine. Is that a gcc option or a hardwired thing in the processor?
I've only seen this odd memory model on some HP IA64 boxes. It probably won't be a problem for SPARC, so your proposed fix is a viable option. Another alternative is to take advantage of the __sync intrinsics for GCC 4.1+: http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html

Peter Dimov wrote:
Another alternative is to take advantage of the __sync intrinsics for GCC 4.1+:
http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html
This is now done. Please let me know if it fixes the problems on SPARC.
participants (2)
-
Jerry Lawson
-
Peter Dimov