l oop увеличивает value
count
раз, если m_NeedParentUpdate
не false
.
Из сгенерированного кода кажется, что m_NeedParentUpdate
является логическим значением, сохраненным как беззнаковое байт по смещению 0
от this
. Оптимизатор, вероятно, обнаружит, что m_NeedParentUpdate
является константой в l oop, поэтому тест можно переместить за пределы l oop. Программист уже должен был написать код таким образом, и это может быть то, что Майк Эктон называет Я уверен, что вы можете оптимизировать это в своей голове .
Вот переписанная версия:
class Foo {
bool m_NeedParentUpdate;
int Bar(int count);
};
int Foo::Bar(int count) {
int value = 0;
if (m_NeedParentUpdate) {
for (int i = 0; i < count; i++) {
value++;
}
}
return value;
}
Обратите внимание, однако, что дальнейшая оптимизация кода в вашей голове может привести к уменьшению l oop до value += count;
, но это будет неверно для отрицательных значений count
, что не так очевидно на первый взгляд.
Оптимизатор может обнаружить шаблон l oop и выполнить оптимизацию как:
int Foo::Bar(int count) {
int value = 0;
if (m_NeedParentUpdate) {
if (count >= 0) {
value += count;
}
}
return value;
}
Или, что эквивалентно:
int Foo::Bar(int count) {
int value = 0;
if (count >= 0) {
if (m_NeedParentUpdate) {
value = count;
}
}
return value;
}
Преобразование m_ParentNeedUpdate
в unsigned
и его отрицание дает 0
для false
и все биты один для true
. Маскирование count
с этим значением даст 0
или count
.
int Foo::Bar(int count) {
int value = 0;
if (count >= 0) {
value = -(unsigned)m_NeedParentUpdate & count;
}
return value;
}
Обратите внимание, однако, что в коде все еще есть тест и инструкция перехода. Его можно дополнительно оптимизировать как:
int Foo::Bar(int count) {
// equivalent code, but definitely not readable
return -(unsigned)m_NeedParentUpdate & -(unsigned)(count >= 0) & count;
}
При компиляции как gcc
, так и clang
получается код без веток, как это можно увидеть в GodBolt's Compiler Explorer . Но ни один из компиляторов не сокращает исходный код до этого единственного лайнера.