Арифметические операции и оптимизация компилятора

Я размышляю над арифметической библиотекой с фиксированной запятой, и для того, чтобы решить, сколько оптимизации следует выполнить самой библиотеке (с помощью шаблонов выражений), я начал задавать вопрос, сколько уже будет сделано оптимизатором. Возьмите следующий пример, например:

//This is a totally useless function to exemplify my point
void Compare(FixedPoint a, FixedPoint b) {
if(a/b>10) {
... do stuff
}
}

Теперь, в этой функции, типичная реализация FixedPoint класс вызовет

if( ( (a_<<N) / b_) > (10 <<N) ) {
... do stuff
}

куда N количество дробных бит Это выражение могло математически быть преобразованным в:

(a_ > 10*b_)

даже если это преобразование не привести к тому же поведению, если учесть целочисленное переполнение. Пользователи моей библиотеки, вероятно, будут заботиться о математической эквивалентности и предпочли бы иметь уменьшенную версию (возможно, предоставленную через шаблоны выражений).

Теперь возникает вопрос: осмелится ли оптимизатор выполнить саму оптимизацию, даже если поведение не является строго таким же? Должен ли я беспокоиться о такой оптимизации? Обратите внимание, что такие оптимизации не являются тривиальными. В действительности вам редко приходится делать какие-либо сдвиги битов, когда вы используете арифметику с фиксированной запятой, если вы действительно делаете эти оптимизации.

3

Решение

Это будет зависеть от того, a_ а также b_ типы подписаны или не подписаны.

В C и C ++ переполнение со знаком является технически неопределенным поведением, в то время как переполнение без знака выполняется с использованием арифметики с двумя дополнениями.

Тем не менее, некоторые компиляторы отказываются оптимизировать этот код, потому что многие программы полагаются на поведение с двумя дополнениями подписанного переполнения.

Хорошие современные компиляторы будут иметь возможность включить / отключить это конкретное предположение: целые числа со знаком не будут переполнены. Какой вариант по умолчанию будет зависеть от компилятора.

Например, с помощью GCC см. Параметры -fstrict-overflow/-fno-strict-overflow и соответствующее предупреждение -Wstrict-overflow,

1

Другие решения

Других решений пока нет …