On Saturday, February 15, 2020 at 7:43:56 PM UTC-8, JCampbell wrote:
> I am finding some variation in the way "do i = m1,m2"
> vs "do i = m1,m2,m3"
> The first appears to use a test "if ( i > m2 ) exit" and
> overflows for int8
> The second appears to use a do_trip_count of optional kind,
> which 2 compilers treat differently.
> I presume there is some flexibility in the standard as to what
> the compiler does. ( has this changed since F90? )
In comp.lang.c, this is called the "as if" rule.
If it gives the result that the standard requires, in all cases where
the standard requires it, then it is fine.
In the case of m3=1, and I suspect for most positive m3 (constant
so that the compiler knows it is positive), it is fairly easy to
do it, as previously noted, the old way. This is especially true
using a wider type than the actual DO variable. (For example, when
it is kept in a register.)
I suspect that is also true when m3 is negative.
When m3 is a variable, I might expect compilers to compute the
loop count as described. Otherwise, it isn't so easy to get all
the cases to work. I might have known compilers to generate two
loops and a test for the sign if m3, but only for small loops.
> for : DO i = m1,m2,m3
> where i,m1,m2,m3 are kind=int8
> We have the assumption that do_trip_count = (m2 - m1 + m3) / m3
> and potentially the kind for this trip count is the same "int8" (or higher kind ?)
> My testing suggests that for gFortran this is not always the case,
> as DO i = m1,m2 may not use a trip_count (and fails for if ( i > 127_1 )
> exit
As noted, in cases where the trip count overflows, undefined behavior
means that the compiler can do anything. It can be an infinite loop,
or loop the number of times that it might do "the old way".
These are interesting. In this case, presumably, the compiler
does not know that values at compile time (some optimizing compilers
might be good enough to figure this out), so treats them as variables.
You might try the do i=1_1,127_1 case, where it terminates
properly with a loop count, but not with 8 bit signed arithmetic
waiting for 128. Note that one of the examples showing the internal
form from gfortran tests for 127 before incrementing.
As previously noted, the 0,127 case is undefined behavior,
but the 1,127 case is not. It has to get the 1,127 case right.
> What might be the case if we had integer(int64) :: m1,m2,m3 ?
Don't try:
integer(int64): i
do i=1,huge(i)
enddo
Well, some compilers will optimize away the whole loop,
so maybe try something else.