Как я могу обойти GCC оптимизации-ошибка 90271? - PullRequest
5 голосов
/ 29 апреля 2019

версии GCC, выпущенные до мая 2019 года (и, возможно, позже), не могут оптимизировать этот фрагмент кода:

// 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;
}

как видно здесь (GodBolt): clang правильно оптимизирует этот код, а GCC и MSVC - нет. Это ошибка GCC 90271 , которая в какой-то момент будет исправлена. Но - это не будет исправлено для версий GCC, которые выпущены сегодня, и я хочу написать этот код сегодня ...

Итак: существует ли обходной путь, который заставит GCC генерировать тот же код, что и clang для этой функции, или, по крайней мере, код сопоставимой производительности, сохраняя данные в регистрах и не прибегая к указателям и стеку?

Примечания:

  • Я пометил это как C, так как фрагмент кода находится в C. Я предполагаю, что обходной путь, если таковой существует, также может быть реализован в C.
  • Я заинтересован в оптимизации как встроенной функции, так и встроенной версии.
  • Этот вопрос относится к этому , но касается только GCC и конкретного подхода в этом фрагменте кода; и находится в C, а не C ++.

1 Ответ

7 голосов
/ 29 апреля 2019

Это делает не встроенную версию немного длиннее, но встроенная версия оптимизирована для всех трех компиляторов:

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

Приведение от v2 к unsigned char до необходимости сменыесли char является типом со знаком.В этом случае без регистра v2 будет расширен знак до целого числа, что приведет к тому, что нежелательные биты будут установлены в 1 в результате.

...