Operating System - OpenVMS
1748215 Members
3447 Online
108759 Solutions
New Discussion юеВ

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation

 
FreeFall
Occasional Advisor

Fortran on VMS 8.3 Itanium Short-Circuit evaluation



Hi,

We are currently looking into migrating a lot of legacy Fortran code from Alpha OpenVMS 8.3 to Itanium OpenVMS 8.3.

A lot of our code apparently depends on if statements short-circuiting after the first .and. test fails. For example we have a lot of instances of:

INTEGER*4 LIST2(2)
INTEGER*4 X

X = 3
IF (X .LE. 2 .AND. LIST2(X) .EQ. 0) THEN
- do something -
ENDIF

When I compile it on Alpha 8.3 it runs with no problems:

$ FOR/VER
HP Fortran V8.2-104679-48H9K
$ FOR/NOOPT/CHECK=BOUNDS FILE.FOR
$ LINK FILE

When I do the same thing on our Itanium it crashes:

$ FOR/VER
HP Fortran V8.2-104939-50H96
$ FOR/NOOPT/CHECK=BOUNDS FILE.FOR
$ LINK FILE
$ RUN FILE
%SYSTEM-F-SUBRNG1, subscript 1 range error, PC=00000000000200F1, PS=0000001B


I'm hoping there is some compiler option I can use to change this behavior but I haven't found anything yet. Does anyone have any suggestions? (other than fixing the code).

Thanks
9 REPLIES 9
Steven Schweda
Honored Contributor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation

Not I. According to the manual:

[...]
You should not write logical expressions
whose results might depend on the
evaluation order of subexpressions. The
compiler is free to evaluate
subexpressions in any order.
[...]

Of course, there is this:

[...]
Some subexpressions might not be
evaluated if the compiler can determine
the result by testing other
subexpressions in the logical expression.
[...]

Unfortunately, "might" leaves the door open
to considerable variability in the
implementation.

http://h21007.www2.hp.com/portal/download/files/unprot/Fortran/docs/vms-i64-lrm/forti64lrm_007.html#index_x_526
Mike Kier
Valued Contributor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation

I doubt you'll like the answer, but "fix the code"

Your code is non-standard. DEC/Compaq/HP has had a tradition of a lot of Fortran language extensions, but I've not seen short-circuiting or any guaranteed order-of-evaluation ever be explicitly stated as one of them. Under the standard (at least through F95), you have to be able to handle any order of evaluation even if one or more of the conditional expressions is a function call with side-effects.

Even if you were to find a compiler switch or CDEC$ directive to get around it this time, you may wish to port to another system someday and be right back where you are.
Practice Random Acts of VMS Marketing
FreeFall
Occasional Advisor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation


Thanks for finding that doc Steven. That's not good news though - 1331 source code files contain ".and.".

I'll probably turn off the /CHECK=BOUNDS for the time being, so I can find any other obvious problems.

Thanks again
John Gillings
Honored Contributor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation

FreeFall,

Unfortunately there is no simple way around this. I've dealt with it on numerous occasions as a customer support "Linguist".

Some languages define all AND and OR operations as short circuit (example: Modula-2), some define long and short versions of the operators (example: OpenVMS Pascal AND, OR, AND_THEN, OR_ELSE), others, like Fortran, define AND and OR as "at the descretion of the compiler".

That being the case, your code sample is invalid Fortran. Thems the rules. If you break them, it's at your peril.

You may get lucky and have the evaluation in the order you really wanted, but then again, you may not. As you've found, sometimes a change in the compiler, or even a change elsewhere in your code may be enough to alter the compiler's choice and thus reveal your bug.

In the case of a bounds check, as in your example, you could disable bounds checks for that module. The code will then "work", but you risk an ACCVIO, and will miss other bounds errors elsewhere in the module.

Note that bounds checking is all or none for the module, so it isn't possible to use a $CDEC directive to disable it for just the affected IF statement, and even if it were possible, editing the directives into your code would be just as much work as fixing it.

Another alternative would be to declare an exception handler, perhaps in the main program, which catches the SUBRNG condition and (somehow) decides if it's one of your IF statements. Resignalling or continuing depending on your decision. Note this is non-trivial!

The general rule is, every time you port your code you will find and fix more bugs.
A crucible of informative mistakes
FreeFall
Occasional Advisor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation


I'd love to fix the code - it's grown into a real mess and it's all F77 at best. However, management doesn't have much appetite for total rewrites so I was really hoping that we wouldn't have to touch almost every source file.

Oh well - I really love testing anyway.
John McL
Trusted Contributor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation

I'm surprised that this code runs okay on Alpha. Fortran isn't C! In particular, optimisation could easily change the order of evaluation within an IF statement.

You just might get away with /NOOPT but (a) your throughput would probably suffer compared to using /OPT and (b) it would be very risky and you'd need to test like crazy to make sure nothing failed. You'd just about have to examine the machine code to check that the order of evaluation was correct and that the processing would branch after each test.

It might be worth considering writing a tool to automatically split those IF statements.
Eg. using your example of

IF (X .LE. 2 .AND. LIST2(X) .EQ. 0) THEN
- do something -
ENDIF

the new code would be

IF (X.LE.2) THEN
IF (LIST2(X).EQ.0) THEN
- do something -
ENDIF
ENDIF

If your code is written in consistent format, and you take care with conditions in parentheses, I think you should be able to correctly rewrite most of these conditionals in a relatively short time.

FreeFall
Occasional Advisor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation


Now that I've looked into this, I'm surprised it works too. On the Alpha I tried:

$for/opt/check=bounds

and expected it to fail but it didn't. Perhaps the /check=bounds somehow influences the compiler also, or maybe I just got lucky.

The production code is compiled with /NOOPT/CHECK=BOUNDS and I suspect that maybe the /NOOPT is what is making this all work.

Thanks for all the helpful replies.
John


John Gillings
Honored Contributor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation

John,

>The production code is compiled
>with /NOOPT/CHECK=BOUNDS

CHECK=BOUNDS is OK for production code (but one would hope superfluous, assuming reasonably defensive programming, and remember bounds checking adds a non-trivial additional processing cost), but /NOOPT is production code??? Definitely not!

There's very little good side to /NOOPT, and plenty of bad side. Indeed, I'd recommend using /OPTIMIZE as your default. The only time to use /NOOPT is when there's a particularly insidious bug that you can't locate otherwise. Yes, /OPTIMIZE makes using DEBUG a bit harder - get used to it! Modern processors, like Alpha, and especially Itanium are wasted on unoptimized code.

/NOOPT code hides too many bugs. Case in point, if your code had been tested and debugged with /OPTIMIZE you probably would have realised the invalid assumptions about short cut evaluation MUCH earlier and fixed it before it spread.
A crucible of informative mistakes
FreeFall
Occasional Advisor

Re: Fortran on VMS 8.3 Itanium Short-Circuit evaluation


The only *real* solution is to fix the code. Hopefully I can convince people that it is the right way to go.

Thanks again,
John