To the two Fortran novelties already announced he added these notes:
Behavior on integer overflow
GCC 13 includes new optimizations which may change behavior on
integer overflow. Traditional code, like linear congruential
pseudo-random number generators in old programs and relying on
a specific, non-standard behavior may now generate unexpected
results. The option -fsanitize=undefined can be used to detect
such code at runtime.
It is recommended to use the intrinsic subroutine RANDOM_NUMBER for random number generators or, if the old behavior is desired, to use
the -fwrapv option. Note that this option can impact performance.
What is the new behavior and what is the workaround? I use linear congruential generators to generate hash values and checksums, and in these cases, I expect the overflows to wrap, mod 2^32. If this is no longer the behavior, then what is the workaround?
The intrinsic RANDOM_NUMBER() only returns floating point values. For applications like hash codes and checksums, one usually wants integer values.
From that text, it is not the fortran standard that defines the behavior but rather āthe processorā, which in practice means the compiler, operating system, and runtime libraries that they use.
So if gfortran (or any other compiler) defined arithmetic so that LCGs work as expected, then those arithmetic operations would not be prohibited, which is a long way of saying they would be allowed (as they have been in fortran processors for some 60+ years). I understand that the fortran standard does not require LCGs to work, but I do think it allows them to work. So I donāt think it is correct for gfortran to try to hide behind the standard for a decision that it made itself.
Also, I donāt understand why specifying -fwrapv would adversely impact performance. It seems like it would be the other way around. If the overflows are trapped, that is what would take the effort, not ignoring them. If not, then what am I missing here?
Given that gfortran is changing legacy behavior, Instead of a compiler option, my preference to address this would have been something more local in the source code. For example, a source code directive, or perhaps an intrinsic function that the compiler would inline, or a mode function that turns off the unwanted behavior temporarily. The ability to ignore integer overflow is only preferred in very limited places, so you donāt want to change compiler options on a whole program just to get a few specific multiplications to work right, just those few places where you want overflows to wrap.
Are these the first adverse comments on this new feature that you have encountered?
I read from this that other gcc languages, including C and C++, are also going to have difficulty implementing LCGs efficiently. LCGs are a common part of many algorithms, not just random number generators, but also the hashes and checksums that I mentioned, cryptography, security, and so on. LCGs are used within other encryption algorithms, primarily because they require just an integer multiplication and possibly an integer addition.
There have always been many good use cases for unisgned integers.
However, with twos-complement arithmetic, multiplications, additions, etc. all work the same in the hardware for signed and unsigned integers. The only difference is how numerical values are assigned to the resulting bits. That is why things like LCGs have always worked correctly in fortran on such hardware, they are really doing 32-bit unsigned arithmetic modulo 2**32 beneath the surface. And as you pointed out before, if the processor works that way, then the fortran standard allows the programmer to take advantage of that arithmetic feature.
Of course we all understand that that behavior cannot be incorporated into the standard because the standard must also accommodate other signed integer conventions, ones-complement, signed magnitude, biased, etc.
This all seems like it would be an important topic to me. Iām surprised that the gcc people (not just the gfortran people) have not had more push-back for this change from legacy behavior.
Even the people writing compilers, gcc included, use hashes and checksums and LCGs internally. Certainly the people writing operating systems with these languages use them. By changing conventions so that LCGs can no longer be implemented, they are knowingly shooting themselves in the foot. My point was that the compiler writers should be the first ones to recognize the problem.
In this 1988 article is the sentence, āAs a convention we frequently advise our students to respond with the 9 digits of their social security number.ā How times have changed!
Regarding your sample codes, these all rely on the convention that the integer overflows that occur in the statement
jsee = jsee * jm + ja
are silently ignored. The issue being discussed was that those overflows are no longer ignored in the new gcc/gfortran. Right? If the new gcc/gfortran is still treating these overflows the same as before, then this whole discussion has been a red herring.
Iām not sure I understand why the results were wrong in the second run, with the -O compiler option. This is a compiler error, not a code error, right? Is it inlining the code, but missing the fact that the intent(inout) argument is modified?
ālike 1-2 hours of intense compiling using every single thread your CPU has, and typically with computerās fans spinning fastā
Sometimes I forget why I liked my Dell R820 with 40 coresā¦ even though it cost me $6 per month to run in the garage and it wasnāt as performant as my new desktopā¦ man could it compile code fast.