clang 14 -O2
От: K13 http://akvis.com
Дата: 25.08.22 07:05
Оценка: 5 (1)
Похоже, оптимизатор там перекрутили в хлам:

https://godbolt.org/z/xMKEhhhfd

функция из Quake, быстрое вычисление 1/sqrt(number) c небольшой погрешностью
Re: clang 14 -O2
От: vopl Россия  
Дата: 25.08.22 07:17
Оценка:
Здравствуйте, K13, Вы писали:

K13>Похоже, оптимизатор там перекрутили в хлам:


K13>https://godbolt.org/z/xMKEhhhfd


K13>функция из Quake, быстрое вычисление 1/sqrt(number) c небольшой погрешностью


Судя по всему, это все из за индус-стайла (копипаста и в прод). Замени long на что нибудь соразмерное float-y и все станет нормально.
Re[2]: clang 14 -O2
От: K13 http://akvis.com
Дата: 25.08.22 07:52
Оценка:
V>Судя по всему, это все из за индус-стайла (копипаста и в прод). Замени long на что нибудь соразмерное float-y и все станет нормально.

Точно: https://godbolt.org/z/M5bnnv1s4

Правда, в продакшин я бы такие хаки пихать все равно не стал.
Токое можно использовать только когда диапазон величин гарантированно укладывается в допустимый, и не страшна погрешность.

Собственно, пихнул я эту функцию на godbolt из любопытства -- будет ли компилятор входной float просто интерпретировать как целочисленный в регистре или полезет через память. и тут вдруг clang 14 выдал мне один ret.
Отредактировано 25.08.2022 8:24 K13 . Предыдущая версия .
Re[3]: clang 14 -O2
От: Zhendos  
Дата: 25.08.22 09:46
Оценка: +1
Здравствуйте, K13, Вы писали:

V>>Судя по всему, это все из за индус-стайла (копипаста и в прод). Замени long на что нибудь соразмерное float-y и все станет нормально.


K13>Точно: https://godbolt.org/z/M5bnnv1s4


Вообще этот код тоже UB. Должен быть memcpy или bit_cast (c++20)
чтобы strict aliasing не нарушался.
Re: clang 14 -O2
От: kov_serg Россия  
Дата: 25.08.22 12:19
Оценка:
Здравствуйте, K13, Вы писали:

K13>Похоже, оптимизатор там перекрутили в хлам:

Я давно заметил, что этот компилятор не вменяемый.
Но почему нельзя было написать так:
float Q_rsqrt( float number ) 
{ 
    union { long i;  float y; };
    float x2; 
    const float threehalfs = 1.5F; 
 
    x2 = number * 0.5F; 
    y  = number; 
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck?  
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration 
//    y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed 
 
    return y; 
}
Re[2]: clang 14 -O2
От: Zhendos  
Дата: 25.08.22 13:40
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Но почему нельзя было написать так:


_>
_>    union { long i;  float y; };
_>


Так использование неактивного члена union это тоже UB в C++
Re[3]: clang 14 -O2
От: vsb Казахстан  
Дата: 25.08.22 14:04
Оценка:
Здравствуйте, Zhendos, Вы писали:

_>>Но почему нельзя было написать так:


_>>
_>>    union { long i;  float y; };
_>>


Z>Так использование неактивного члена union это тоже UB в C++


Компилятор на все эти UB хоть ворнинги пишет?
Re[4]: clang 14 -O2
От: kov_serg Россия  
Дата: 25.08.22 14:08
Оценка: :)
Здравствуйте, vsb, Вы писали:
Z>>Так использование неактивного члена union это тоже UB в C++

vsb>Компилятор на все эти UB хоть ворнинги пишет?

Нет
Re[3]: clang 14 -O2
От: kov_serg Россия  
Дата: 25.08.22 14:10
Оценка:
Здравствуйте, Zhendos, Вы писали:

_>>
_>>    union { long i;  float y; };
_>>


Z>Так использование неактивного члена union это тоже UB в C++

Что значит не активного. И где такое написано?
Re[4]: clang 14 -O2
От: vopl Россия  
Дата: 25.08.22 14:41
Оценка: +1
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, Zhendos, Вы писали:


_>>>
_>>>    union { long i;  float y; };
_>>>


Z>>Так использование неактивного члена union это тоже UB в C++

_>Что значит не активного. И где такое написано?

Про неактивный тут https://eel.is/c++draft/class.union#general-2.sentence-2
Про UB при использовании неактивного (вне lifetime) тут https://eel.is/c++draft/basic.life#7.sentence-4 кейс (7.1)
Re[5]: clang 14 -O2
От: kov_serg Россия  
Дата: 25.08.22 15:04
Оценка:
Здравствуйте, vopl, Вы писали:

_>>>>
_>>>>    union { long i;  float y; };
_>>>>


Z>>>Так использование неактивного члена union это тоже UB в C++

_>>Что значит не активного. И где такое написано?

V>Про неактивный тут https://eel.is/c++draft/class.union#general-2.sentence-2

V>Про UB при использовании неактивного (вне lifetime) тут https://eel.is/c++draft/basic.life#7.sentence-4 кейс (7.1)
И где это нарушается? Тут i и y в разные моменты времени используются.
Re[6]: clang 14 -O2
От: vopl Россия  
Дата: 25.08.22 15:22
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, vopl, Вы писали:


_>>>>>
_>>>>>    union { long i;  float y; };
_>>>>>


Z>>>>Так использование неактивного члена union это тоже UB в C++

_>>>Что значит не активного. И где такое написано?

V>>Про неактивный тут https://eel.is/c++draft/class.union#general-2.sentence-2

V>>Про UB при использовании неактивного (вне lifetime) тут https://eel.is/c++draft/basic.life#7.sentence-4 кейс (7.1)
_>И где это нарушается? Тут i и y в разные моменты времени используются.

Смотри https://eel.is/c++draft/class.union#general-6
float Q_rsqrt( float number ) 
{ 
    union { long i;  float y; }; // никто не активен

    y  = number; // теперь активен y
    i  = 0x5f3759df - ( i >> 1 ); // читаем i, но он не активен, то есть он вне lifetime, это и есть UB. (Затем результат выражения присваивается в i, это делает его активным вместо y, но это уже не важно)
}
Re[4]: clang 14 -O2
От: Аноним  
Дата: 25.08.22 16:58
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Здравствуйте, Zhendos, Вы писали:


_>>>Но почему нельзя было написать так:


_>>>
_>>>    union { long i;  float y; };
_>>>


Z>>Так использование неактивного члена union это тоже UB в C++


vsb>Компилятор на все эти UB хоть ворнинги пишет?


Ну про первоначальный код g++ (с "-O2 -Wall -Wextra") сообщает
"dereferencing type-punned pointer will break strict-aliasing rules".
А вот про "union" не умеет.
Re[7]: clang 14 -O2
От: kov_serg Россия  
Дата: 25.08.22 17:02
Оценка:
Здравствуйте, vopl, Вы писали:

V>Смотри https://eel.is/c++draft/class.union#general-6

V>
V>float Q_rsqrt( float number ) 
V>{ 
V>    union { long i;  float y; }; // никто не активен

V>    y  = number; // теперь активен y
V>    i  = 0x5f3759df - ( i >> 1 ); // читаем i, но он не активен, то есть он вне lifetime, это и есть UB. (Затем результат выражения присваивается в i, это делает его активным вместо y, но это уже не важно)
V>}
V>

Не такой C++ нам не нужен.
Re[8]: clang 14 -O2
От: _NN_ www.nemerleweb.com
Дата: 27.08.22 18:27
Оценка: 9 (1)
Здравствуйте, kov_serg, Вы писали:
_>Не такой C++ нам не нужен.
Таким C++ был издревна.
Для переносимого кода без неопределённого поведения нужно как указали memcpy, bit_cast.

Почитать
What is the Strict Aliasing Rule and Why do we care?

https://github.com/ibbles/StrictAliasing
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[9]: clang 14 -O2
От: vsb Казахстан  
Дата: 27.08.22 18:38
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Для переносимого кода без неопределённого поведения нужно как указали memcpy, bit_cast.


Мне кажется, memcpy int-а и переносимый код это оксюморон. C++ даже поведение при переполнении знакового числа не гарантирует, а тут внутреннее представление.
Отредактировано 27.08.2022 18:38 vsb . Предыдущая версия .
Re[10]: clang 14 -O2
От: _NN_ www.nemerleweb.com
Дата: 27.08.22 19:31
Оценка: 10 (1)
Здравствуйте, vsb, Вы писали:

vsb>Здравствуйте, _NN_, Вы писали:


_NN>>Для переносимого кода без неопределённого поведения нужно как указали memcpy, bit_cast.


vsb>Мне кажется, memcpy int-а и переносимый код это оксюморон. C++ даже поведение при переполнении знакового числа не гарантирует, а тут внутреннее представление.


Я не про конверсию int-float на уровне битов.
Это в общем про strict aliasing.

Как например здесь нужен memcpy и нельзя reinterpret_cast

// Simple operation just return the value back
int foo( unsigned int x ) { return x ; }

// Assume len is a multiple of sizeof(unsigned int) 
int bar( unsigned char *p, size_t len ) {
  int result = 0;

  for( size_t index = 0; index < len; index += sizeof(unsigned int) ) {
    unsigned int ui = 0;                                 
    std::memcpy( &ui, &p[index], sizeof(unsigned int) );

    result += foo( ui ) ;
  }

  return result;
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[11]: clang 14 -O2
От: VVV Россия  
Дата: 31.08.22 03:52
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Это в общем про strict aliasing.


_NN>Как например здесь нужен memcpy и нельзя reinterpret_cast


_NN> std::memcpy( &ui, &p[index], sizeof(unsigned int) );


Было бы интересно узнать для каких процессоров/платформ необходим этот трюк с memcpy. Т.к. для x86 x64 бинарные данные прекрасно записываются на диск и обратно считываются и кастятся к структурам без этого трюка (даже при #pragma pack(1)). Также и сетевые данные не нуждаются в такой конверсии на этих процессорах. Допускаю, что есть не очень продвинутые процессоры и компиляторы C++ для них(не умеющие заменить присваивание, как в данном случае при reinterpret_cast на memcpy, если надо). Есть ли список таких процессоров/платформ/устройств?
Re[9]: clang 14 -O2
От: kov_serg Россия  
Дата: 31.08.22 05:03
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Таким C++ был издревна.

https://www.linux.org.ru/forum/development/22475
Нет. Таким его сделали.

_NN>Для переносимого кода без неопределённого поведения нужно как указали memcpy, bit_cast.


Шли бы они в жопу с такими правилами. Мы уж лучше укажем пару ключей -fno-strict-aliasing -fwrapv
Re: clang 14 -O2
От: fk0 Россия https://fk0.name
Дата: 02.09.22 12:09
Оценка: 5 (1)
Здравствуйте, K13, Вы писали:

K13>Похоже, оптимизатор там перекрутили в хлам:

K13>https://godbolt.org/z/xMKEhhhfd
K13>функция из Quake, быстрое вычисление 1/sqrt(number) c небольшой погрешностью

Формально компилятор прав. Тут устроено UB которое проявляется при добавлении -Wcast-align.
Возникает оно на 64-битной платформе, из-за разного выравнивания float и long.
Напоминаю сразу, что размер long в windows и linux -- разный
(https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models)
В связи с чем, при добавлении ключика -m32, при сборке на 32-битную платформу проблема
автомагически исключается.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.