Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I work around GCC optimization-miss bug 90271?

GCC versions released before May 2019 (and maybe later) fail to optimize this piece of code:

// Replace the k'th byte within an int
int replace_byte(int v1 ,char v2, size_t k) 
{
   memcpy( (void*) (((char*)&v1)+k) , &v2 , sizeof(v2) );
   return v1;
}

as can be seen here (GodBolt): clang optimizes this code properly GCC and MSVC do not. This is GCC bug 90271, which will at some point be fixed. But - it won't be fixed for GCC versions that are out today, and I want to write this code today...

So: Is there a workaround which will make GCC generate the same code as clang for this function, or at least - code of comparable performance, keeping data in registers and not resorting to pointers and the stack?

Notes:

  • I marked this as C, since the code snippet is in C. I assume a workaround, if one exists, can also be implemented in C.
  • I'm interested in optimizing both the non-inlined function and the inlined version.
  • This question is related to this one, but only regards GCC and the specific approach in the piece of code here; and is in C rather than C++.
like image 937
einpoklum Avatar asked Apr 29 '19 20:04

einpoklum


People also ask

How do I enable optimization in GCC?

The -O level option to gcc turns on compiler optimization, when the specified value of level has the following effects: 0. The default reduces compilation time and has the effect that debugging always yields the expected result. This level is equivalent to not specifying the -O option at all.

What compiler option can be used to enable all optimizations?

The /Ox compiler option enables a combination of optimizations that favor speed.

How do I change the optimization level in GCC?

GCC has a range of optimization levels, plus individual options to enable or disable particular optimizations. The overall compiler optimization level is controlled by the command line option -On, where n is the required optimization level, as follows: -O0 . (default).

How do I stop GCC optimization?

The gcc option -O enables different levels of optimization. Use -O0 to disable them and use -S to output assembly.


1 Answers

This makes the non-inlined version a little longer, but the inlined version is optimized for all three compilers:

int replace_bytes(int v1 ,char v2, size_t k)
{
    return (v1 & ~(0xFF << k * 8)) | ((unsigned char)v2 << k * 8);
}

The cast of v2 to an unsigned char before the shift is necessary if char is a signed type. When that's the case, without the case v2 will be sign extended to an integer, which will cause unwanted bits to be set to 1 in the result.

like image 127
1201ProgramAlarm Avatar answered Oct 31 '22 17:10

1201ProgramAlarm