To: J3 12-182 From: Nick Maclaren Subject: My Objections to Interpretation F03/0065 Date: 2012 October 13 References: N1939.txt I shall attempt to analyse the answer in detail, and give examples of why I voted "no" and still object to the answer, though not the decision. To clear the decks, I propose to ignore two paragraphs in F03/0065, as they simply state facts: However, Note 7.22 in Fortran 2003 shows this transformation as being acceptable. The erroneous example has been removed in Fortran 2008. The Wording ----------- The remainder of the question and answer is: Given REAL X X = ... some value ... may IF( X+3.0 .EQ. 3.0 )... be transformed into IF( X .EQ. 0.0 )... by the processor? In Fortran 2003, 7.1.8.5 Evaluation of relational intrinsic operations says "Two relational intrinsic operations are relationally equivalent if their logical values are equal for all possible values of their primaries." On a machine where addition of 3.0 to a small value is not exact, the logical values for X+3.0==3.0 are not the same as X==0.0 for all possible values of X, therefore it would seem that this transformation would not be possible. ANSWER: No, the transformation is not permitted unless it gives the same answer for all possible values (of X and X+3.0). The intention was that this is an interpretation about the handling of 'EQ.' - no more - but that is not the only way to read those words. I read them as also making a statement about the arithmetic (in this case, X+3.0), because of the sentence beginning "On a machine ...", and I am sure that at least some other readers will do the same. My points below try to explain why I regard the existing wording as a serious mistake, by showing examples that it appears to forbid but which are important and widely-used optimisations. In all cases, let us consider the common case where: 1) the compiler does NOT define IEEE_NAN in IEEE_FEATURES, or the programmer does NOT access any of the IEEE_... modules, or both, and 2) the processor compiles into IEEE 754 operations, with 32-bit REALs and 64-bit 'registers', and does not trap unordered comparisons. Possible Alternative Answer --------------------------- This is not very good, but would address the issues that I am concerned about. ANSWER: No, transformations across a relational operator are not permitted unless they give the same answer for all possible values of the operands on either side (X, 0.0, X+3.0 and 3.0). The standard does not specify how X+3.0 is calculated, but the transformation would not give the same answer for all values of X in any floating-point arithmetic. In particular, the qualification "across a relational operator" (or similar wording) is essential to resolve my concerns. Example 1 --------- Let us consider three possible implementations, described in terms of IEEE 754 arithmetic with the declared types: Base: IF (X+3.0 .EQ. 3.0) ... Version 1: IF (X .EQ. 0.0) ... Version 2: IF (REAL(X,KIND=KIND(0.0D0))+3.0D0 .EQ. 3.0D0) ... In both modified versions, the condition "the logical values for X+3.0==3.0 are not the same as for all possible values of X" holds. But does this interpretation also forbid a compiler to produce version 2 code? If not, why not? Example 2 --------- Let's consider a closely related example: ! Z is a model property parameter, which can be set to various ! values for different builds REAL, PARAMETER :: Z = 0.0 REAL :: X READ *, X followed by: IF (X+Z .EQ. X) ... versus: IF (.TRUE.) ... Is that transformation allowed? Well, it is in any non-IEEE arithmetic model, but is isn't if the processor supports IEEE NaNs with their preferred comparison semantics. However, we are considering the case when that is NOT so. Programmers can still get a NaN without relying on undefined behaviour, even with our assumptions, by 10.7.2.3.2. What was simple in 1977 isn't today. Do IEEE NaNs count as one of 'all possible values' if the processor uses IEEE 754 hardware, even in the case when it does NOT support IEEE arithmetic and does NOT trap unordered comparisons? The answer implies "yes". Example 3 --------- Let's consider another closely related example: ! Z is a model property parameter, which can be set to various ! values for different builds REAL, PARAMETER :: Z = 0.0 REAL :: X, Y READ *, X Y = X*0.0 IF (X*0.0 .EQ. Y) ... Now, the 'Y = X*0.0' can be optimised to 'Y = 0.0', and the IF statement to either 'IF (.TRUE.) ...' or 'IF (0.0 .EQ. Y) ...', which gives 6 possibilities. Of the few compilers I currently have access to, I get: Y = X*0.0 IF (X*0.0 .EQ. Y) ... and something that appears to be: Y = 0.0 IF (.TRUE.) ... ! or possibly IF (0.0 == Y) ... plus two that trap the undefined exception. But perhaps the second should really be generating: Y = 0.0 IF (X*0.0 .EQ. Y) ... This is like example 2, but even nastier, because it would require different rules for the evaluation of expressions that are the operands of relations and in all other contexts. However, it is important to note that it does not apply just to IEEE 754 NaNs, but to ANY constraint on the arithmetic implied by an answer to this interpretation.