Прежде всего, в качестве общего комментария, этот тип микрооптимизации не стоит вашего времени.Более важным является ответ на вопрос: Что легче отлаживать, понимать и переносить?
Обязательный пост: GOTO по-прежнему считается вредным?
С учетом вышесказанного я, к сожалению, должен сообщить вам, что у OP есть ошибка в его примерах кода (здесьприходит хищник).Используемая вами вычисляемая инструкция GOTO имеет следующие свойства:
Выполнение вычисленной инструкции GOTO приводит к вычислению целочисленного скалярного выражения.Если это значение равно i , так что 1 ≤ i ≤ n , где n - количество меток в списке меток, происходит переход к целевому оператору переходаидентифицируется по метке i th в списке меток. Если i меньше 1 или больше n , последовательность выполнения продолжается, как если бы выполнялся оператор CONTINUE.
источник: Fortran 2008 Standard
Это означает, что правильная версия должна выглядеть следующим образом:
INTEGER WHICH
GOTO(100,200,300) WHICH
GOTO 400 << missing part
100 do something
GOTO 400
200 do something else
GOTO 400
300 do a third thing
GOTO 400
400 CONTINUE
Когда вы генерируете код сборки из следующих 3 файлов (см. Ниже), вы фактически заметите, что код сборки идентичен при оптимизации.Вы можете быстро проверить это самостоятельно, используя следующие строки в bash-скрипте:
$ for i in f{1,2,3}.f90; do ifort -O3 -S $i; done
$ meld f{1,2,3}.s
Вы также заметите, что если вы удалите отсутствующий goto 400
, код сборки goto будет быстрее нанесколько инструкций.
источник f1.f90:
subroutine g(a)
integer a
goto(100,200,300) a
goto 400
100 call f1()
goto 400
200 call f2()
goto 400
300 call f3()
goto 400
400 continue
end subroutine g
источник f2.f90:
subroutine g(a)
integer a
if(a.eq.1)then
call f1()
elseif(a.eq.2)then
call f2()
elseif(a.eq.3)then
call f3()
endif
end subroutine g
источник f3.f90:
subroutine g(a)
integer a
select case (a)
case (1)
call f1()
case (2)
call f2()
case (3)
call f3()
end select
end subroutine g