0

I know that computer science generally frowns on GOTO statements, but is there a speed advantage to be gained by using

    INTEGER WHICH
    GOTO(100,200,300) WHICH
100 do something
    GOTO 400
200 do something else
    GOTO 400
300 do a third thing
    GOTO 400
400 CONTINUE

versus

    INTEGER WHICH
    IF(WHICH.EQ.1)THEN
      do something
    ELSEIF(WHICH.EQ.2)THEN
      do something else
    ELSEIF(WHICH.EQ.3)THEN
      do a third thing
    ENDIF

since Fortran lacks a SWITCH statement?

kvantour
  • 25,269
  • 4
  • 47
  • 72
Dan Eckhart
  • 245
  • 2
  • 8
  • 2
    The SWITCH statement from F77 onwards is called SELECT CASE. Since you have an ELSE, you must be using at least F77 since that didn't exist in F66 either. – cup Apr 04 '19 at 15:12
  • I was not aware of SELECT CASE. Do you know which of the (now) three options is more efficient? – Dan Eckhart Apr 04 '19 at 15:34
  • btw, I added the fortran77 tag – Dan Eckhart Apr 04 '19 at 15:34
  • 1
    Depends on the compiler. At a guess the goto. Why not try the last case 10000 times and see which one comes out faster? – cup Apr 04 '19 at 15:41
  • 2
    Select Case actually entered Fortran in Fortran 90, so only a quarter of a century or so ago ... – Ian Bush Apr 04 '19 at 15:58

1 Answers1

2

First of all, as a general comment, these type of micro-optimizations are not really worth your time. More important is the answer to the question: What is easier to debug, understand and migrate?

Obligatory post: GOTO still considered harmful?

enter image description here


Having that said, I, unfortunately, have to inform you that the OP has a bug in his code-examples (here comes the raptor). The computed GOTO statement which you use has the following properties:

Execution of a computed GOTO statement causes evaluation of the scalar integer expression. If this value is i such that 1 ≤ i ≤ n where n is the number of labels in label-list, a branch occurs to the branch target statement identified by the ith label in the list of labels. If i is less than 1 or greater than n, the execution sequence continues as though a CONTINUE statement were executed.

source: Fortran 2008 Standard

This implies that the correct version should read:

    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

When you generate the assembly code of the following 3 files (see below), you will actually notice that the assembly code is identical under optimization. You can quickly check this yourself with the following lines in a bash script:

$ for i in f{1,2,3}.f90; do ifort -O3 -S $i; done
$ meld f{1,2,3}.s

You will also notice that, if you remove the goto 400 which was missing, the goto assembly code will be faster by a few instructions.


source of 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

source of 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

source of 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
kvantour
  • 25,269
  • 4
  • 47
  • 72
  • 1
    You are rigt, the compiler can transform the if into the switch in this case. The difference would only emerge in more complicated cases or without optimizations. – Vladimir F Героям слава Apr 04 '19 at 16:55
  • 1
    If "the code will be faster by a few instructions," it's not a bug. It's a feature! That said, the fact that it will produce identical (or even nearly identical) assembly code is all the justification we need for selecting the more readable alternative as we add to a large legacy program. – Dan Eckhart Apr 04 '19 at 17:42
  • @DanEckhart you could call it a feature, but the point i wanted to make was that the two codes behave differently, the GOTO code, will also run the first case if `WHICH` is smaller then 1 or bigger than 3. The IF-code does not do that. Is it a bug? It could be a bug if `WHICH` can have these values for whatever reason. Is it a feature? It is a feature if you are 100% certain that `WHICH` only has values 1,2, or 3. and never ever has another value at the point of this decision tree. – kvantour Apr 05 '19 at 10:22
  • I was only joking. It was a useful point about missing the WHICH<1, of which I was unaware. So I gave your answer an upvote in addition to accepting it. Thanks! – Dan Eckhart Apr 05 '19 at 12:15