forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Computed GO TO triggers optimiser bug
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Tue Apr 28, 2015 4:42 am    Post subject: Computed GO TO triggers optimiser bug Reply with quote

A program with about 4,000 lines of text was producing incorrect results when compiled with /OPT. With considerable effort, I was able to pare down the code to the following reproducer.
Code:
program drvr
implicit none
integer :: i,j
do i=0,2
   call cgo(i,j)
   write(*,*)i,j
end do
end program

subroutine cgo(i,j)
implicit none
integer, intent(in) :: i
integer, intent(out) :: j
!
if (i > 0) then
    go to (10, 20) i
end if   
   j=0;     return
10 j=3*i-1; return
20 j=2*i+1; return
end subroutine cgo

When I compiled this using the 7.10 compiler with the /OPT option, the optimiser completely removed the IF block, and running the program gave the erroneous output
Code:
            0           0
            1           0
            2           0

instead of the correct output, which is
Code:
            0           0
            1           2
            2           5


[P.S., 15 June 2015: This bug is also present in FTN95-7.20]


Last edited by mecej4 on Mon Jun 15, 2015 11:15 pm; edited 1 time in total
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Tue Apr 28, 2015 7:59 am    Post subject: Reply with quote

Thanks for the feedback. I have logged this for investigation.
Back to top
View user's profile Send private message AIM Address
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Tue Apr 28, 2015 11:10 am    Post subject: Reply with quote

Someone deprecated the IF block because it contained the deprecated computed GOTO.

Political correctness in Fortran? Where will it all end?

Seriously, now I know what caused me to distrust /OPT - my code contained a single computed GOTO, legacy of an IBM1130 circa 1970. Many thanks MECEJ. Time to send it where the Holleriths and arithmetic IFs went.

I'll bet an assigned GOTO is even worse.

Eddie
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Tue Apr 28, 2015 12:22 pm    Post subject: Reply with quote

The ASSIGN and Assigned GO TO statements were "Deleted features" in F95. The Computed GO TO statement, however, was merely "Obsolescent" in F95, and as far as I know every current compiler accepts it.

The optimiser problem was caused by the presence of computed GO TO in well-respected but old code. If fact, the optimiser bug does not arise if the computed GO TO is used the way it was intended to be used, without the "if (i > 0)then" thrown in as a defensive (?) measure.

The 2003 standard says in 8.2.2:
Quote:
Execution of a computed GO TO 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 transfer of control occurs so that the next statement executed is the one identified by the i-th 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.


The last sentence in the quote is what makes the optimiser-bug inducing IF..ENDIF superfluous.


Last edited by mecej4 on Mon Jun 06, 2016 7:13 pm; edited 1 time in total
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Tue Apr 28, 2015 1:10 pm    Post subject: Reply with quote

I had forgotten ASSIGN. My bet was betting on certainty!
Back to top
View user's profile Send private message
John-Silver



Joined: 30 Jul 2013
Posts: 1520
Location: Aerospace Valley

PostPosted: Tue Apr 28, 2015 4:27 pm    Post subject: Reply with quote

the appears to give the same error if you run it as f77 code too.

Strange that if the calculated goto command was 'obsolete' that the compiler doesn't flag as an error either ?
( unknown command 'go to (**,**)' would maybe be a useful message for example :O) )
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Tue Apr 28, 2015 6:50 pm    Post subject: Reply with quote

If you run the F77 fixed form version of the test program but compile using FTN77 4.03 instead of FTN95, the resulting program runs correctly with or without /OPT.
Back to top
View user's profile Send private message
IanLambley



Joined: 17 Dec 2006
Posts: 490
Location: Sunderland

PostPosted: Wed Apr 29, 2015 12:29 pm    Post subject: Reply with quote

What happens if you replace it with:

Code:


subroutine cgo(i,j)
 implicit none
 integer, intent(in) :: i
 integer, intent(out) :: j
 !
  select case(i)

    case(1)
      j=3*i-1 

    case(2)
      j=2*i+1 

    case default
      j=0
  end select

end subroutine cgo


Regards
Ian
Back to top
View user's profile Send private message Send e-mail
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Wed Apr 29, 2015 10:21 pm    Post subject: Reply with quote

Well the test for i>0 in the code fragment below (copied from above) is redundant. Also it doesn't provide any "safety net" when i = 3 for example.

Code:

if (i > 0) then
    go to (10, 20) i
end if   
   j=0;     return
10 j=3*i-1; return
20 j=2*i+1; return


All you need is the following as control goes to the next line if i isn't 1 or 2 because "go to (10, 20) 3" is the same as "CONTINUE".

Code:

go to (10, 20) i
j=0;     return
10 j=3*i-1; return
20 j=2*i+1; return


Or use Ian's solution above.

All this said, the purpose of this thread is to point out a bug with the optimiser when /opt is used.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Sat May 02, 2015 2:44 pm    Post subject: Reply with quote

Isn't this the simplest solution (66):

Code:
      J = 0
      IF ((I-1)*(I-2)) 20, 10, 20
 10   J = 3*I - 1
 20   CONTINUE


or (77):

Code:
      J = 0
      IF ((I-1)*(I-2) .EQ. 0)  J = 3*I - 1


or even:

Code:
      J = 0
      IF (I .EQ. 1 .OR. I .EQ. 2)  J = 3*I - 1


The safety net is provided.

Two expressions for J are unnecessary, and if the multiple IFs or computed GOTO must be provided, then surely J=2 and J=5 make calculation redundant.

Whether or not I+I+I-1 or 2*I + I/2 is faster with the routine called many times if a question I leave to others, but certainly it is less clear.

I find that the much unloved arithmetic IF sometimes has a beauty all of its own!

Eddie
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Sat May 02, 2015 3:23 pm    Post subject: Reply with quote

Eddie, your modifications do not give the correct result when I = 2, for which J = 2*I + 1, not 3*I - 1.

I note in this thread a tendency to over-analyse a simple reproducer program. The actual computed GOTO in the larger program was
Code:
GOTO  (999,999,130,150,170,190,210,230,250,270,290,310,330,350,500) I
Would you care to tackle such GOTO-s, with the possibility that a target label (e.g., 999) may appear more than once in the list?

Please note that, as far as I know, FTN95 does not have a problem with compiling computed GOTO statements correctly. It is only when the computed GOTO is preceded by an IF statement that the compiler produces incorrect code.
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Sat May 02, 2015 4:30 pm    Post subject: Re: Reply with quote

mecej4 wrote:
Eddie, your modifications do not give the correct result when I = 2, for which J = 2*I + 1, not 3*I - 1.


eh?

2*2 + 1 = 5
3*2 - 1 = 5
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Sat May 02, 2015 5:01 pm    Post subject: Reply with quote

Mecej4,

Quote:
your modifications do not give the correct result when I = 2, for which J = 2*I + 1, not 3*I - 1


For I=2, (not using Fortran syntax)

2x2 = 4 then add 1 = 5 (J = 2*I + 1)

3x2 = 6 then minus 1 = 5 (J = 3*I - 1)

Now where have I gone wrong? For the life of me I can't see where I erred and failed to get the right answer, which is 5. Perhaps I is REAL, and the computed GOTO is of that ghastly short-lived type that was the work of the devil (to quote Dan).

3i-1 = 2i +1 solves to give i=2, if you prefer algebra to arithmetic. True, it only works for i=2, but it (obviously) gives the right answer for i=1 as well.

You were too quick off the mark, old boy!

Of course, but the reproducer problem was a crock of the proverbial, and indeed, the arithmetic GOTO with statement numbers in the full problem is probably the simplest and most elegant solution to the task presented. But then Backus was a genius, and those who followed him might not have been.

The alternative is a long IF THEN ELSE IF construct, or maybe CASE if you prefer.

So your (unnecessary) goal keeper throws FTN95. Certainly needs fixin'.

My own regular goal keeper, as in:

Code:
IF (A .EQ. 0.0D0) THEN
     do a whole lot of error reporting, probably resulting in a jump
     ELSE
        C = B/A
        ENDIF


makes FTN95 nag me that comparing to zero is a bad thing to do. Not in this context, Silverfrost me old china. At least when it has finished giving me GBH of the eyeball, it works.

Eddie
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Sat May 02, 2015 5:19 pm    Post subject: Reply with quote

DavidB,

Your simplicity shames me. I was too busy making coffee, scoffing down a biscuit, and composing what I thought was a witty reply to Mecej4, whose command of the intricacies of the latest Fortran standard usually leaves me open-mouthed in awe and admiration!

Eddie


Last edited by LitusSaxonicum on Sat May 02, 2015 5:43 pm; edited 1 time in total
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Sat May 02, 2015 5:30 pm    Post subject: Reply with quote

Ah, now I see what Eddie did! It did not occur to me to examine the content of the target statements to modify the GOTO statement. DavidB and Eddie, you are both correct, but you can see the risk of writing such code, and subsequently modifying, say, 2*I + 1 to 2*I + 5. And yes, Eddie, you are wickedly witty!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group