Занятно, однако... Решил проверить код, генерируемый для такой конструкции (в RELEASE-е, разумеется): Код (Text): // Where: const[b]X[/b] - some values [i]define[/i]-ed earlier if (value==const1) { event1 (); return; } if (value==const2) { event2 (); return; } if (value==const3) { event3 (); return; } // ... more cases of the same Получил вот что: Код (Text): mov eax, value cmp eax, const1 jnz chk1 call event1 ret chk1: cmp eax, const2 jnz chk2 call event2 ret chk2: cmp eax, const3 jnz chk3 call event3 ret // ... и т.д. Странно, потому что постоянно происходит JMP вперёд, который как известно не предсказывается через статический алгоритм предсказания в процессоре. Чем "глубже" лежит константа для сравнения - тем больше должна падать производительность такого кода. По моему мнению, код должен быть такой: Код (Text): mov eax, value cmp eax, const1 jz do_case1 cmp eax, const2 jz do_case2 cmp eax, const3 jz do_case3 // ... и т.д. do_case1: call event1 ret do_case2: call event2 ret do_case3: call event3 ret // ... и т.д. Чтобы процессор "проваливался" на следующие проверки - "проваливание" ведь не надо предсказывать. Заменил код на такой: Код (Text): if (value==const1) goto L1; if (value==const2) goto L2; if (value==const3) goto L3; ... L1: event1 (); return; L2: event2 (); return; L3: event3 (); return; ... Результат в точности остался прежним! Или я неверно понимаю оптимизационные руководства от INTEL-а или компилятор глупит? Может кто подскажет что может быть причиной?
AsmGuru62 А для такой конструкции тоже так поступает? Код (Text): if(v==c1) e1(); else if(v==c2) e2(); ... esle { } return;
AsmGuru62 Просто релиз ни о чём не говорит. Нужно играться с ключами оптимизации. И когда сообщаете о сгенерированном коде, также нужно приводить ключи компилятора. Это тоже не оптимум. Если условий много, тогда по идее нужно вставить таблицу переходов (switch-table), иначе что-то типа такого: Код (Text): sub max_const ja j_default je j_max_const cmp (max_const - const_n) ; или дальнейшие вариации с sub je j_const_n
на уровне АСТ компайлер не видит goto с бубном. если константы из непрерывного диапазона то этот switch должен скомпилироваться в косвенный call.
AsmGuru62 IMHO компилятор генерирует код, исходя из предположения, что положительный результат проверки более вероятен. Надо соответствующим образом писать исходный код. --- А насчёт jmp вперёд, то там где это актуально (т.е. в циклах) компилятор как раз делает jmp назад.