On Fri, Jun 15, 2018 at 08:27:49PM +0300, Janne Blomqvist wrote: > On Fri, Jun 15, 2018 at 8:06 PM, Thomas Koenig <tkoe...@netcologne.de> > wrote: > > > > > What about more complicated expressions like, say, "func() .and. flag .and > >> func2() .and. flag2" etc.? Can it move all the function calls to the end? > >> > > > > Not at the moment. > > > > Like many of the front-end optimizations, this aims for the easy 80% > > which are relatively easy to achieve. > > > > Come to think about it, is this optimization also done for impure > functions? E.g. if func() changes the value of flag, then exchanging the > order they are evaluated might change the result. Of course, this is all > the fault of the programmer, but still..
It doesn't matter. The code is invalid. A compiler can do anything. F2018: 10.1.4 Evaluation of operations An intrinsic operation requires the values of its operands. Execution of a function reference in the logical expression in an IF statement (11.1.8.4), the mask expression in a WHERE statement (10.2.3.1), or the concurrent-limits and concurrent-steps in a FORALL statement (10.2.4) is permitted to define variables in the subsidiary action-stmt, where-assignment-stmt, or forall-assignment-stmt respectively. Except in those cases: · the evaluation of a function reference shall neither affect nor be affected by the evaluation of any other entity within the statement; · if a function reference causes definition or undefinition of an actual argument of the function, that argument or any associated entities shall not appear elsewhere in the same statement. > > But at least for pure functions, this optimization looks Ok. > Why is everyone fixated on PURE vs IMPURE functions? The Fortran standard allows short circuiting regardless of the pureness of a function. F2018: 10.1.5.4.2 Evaluation of logical intrinsic operations Once the interpretation of a logical intrinsic operation is established, the processor may evaluate any other expression that is logically equivalent, provided that the integrity of parentheses in any expression is not violated. Two expressions of type logical are logically equivalent if their values are equal for all possible values of their primaries. '.false. .and. func()' and 'func() .and. .false.' are logically equivalent to '.false.' F2018: 10.1.7 Evaluation of operands It is not necessary for a processor to evaluate all of ther operands of an expression, or to evaluate entirely each operand, if the value of the expression can be determined otherwise. In fact, F2018 NOTE 10.28 describes this exact situation. NOTE 10.28 This principle is most often applicable to logical expressions, zero-sized arrays, and zero-length strings, but it applies to all expressions. For example, in evaluating the expression X > Y .OR. L(Z) where X, Y, and Z are real and L is a function of type logical, the function reference L(Z) need not be evaluated if X is greater than Y. There is no statement about L(Z) being PURE or not. Thomas' patch is simply trying to alert users to the fact that their code may not do what they think. His check for pureness versus impureness is an attempt to reduce warnings where the the non-evaluation of pure function cannot change the outcome of program. Finally, I think that he can change the warning from + if (f->symtree == NULL || f->symtree->n.sym == NULL + || !gfc_implicit_pure (f->symtree->n.sym)) + { + if (name) + gfc_warning (OPT_Wsurprising, "Impure function %qs at %L " + "might not be evaluated", name, &f->where); + else + gfc_warning (OPT_Wsurprising, "Impure function at %L " + "might not be evaluated", &f->where); + } to + if (f->symtree == NULL || f->symtree->n.sym == NULL + || !gfc_implicit_pure (f->symtree->n.sym)) + { + if (name) + gfc_warning (OPT_Wsurprising, "Function %qs at %L " + "might not be evaluated", name, &f->where); + else + gfc_warning (OPT_Wsurprising, "Function at %L " + "might not be evaluated", &f->where); + } That is, remove the word 'Impure' as it can be misleading. -- Steve