This is an archive of the discontinued LLVM Phabricator instance.

[flang] AMAX0, MIN1... rewrite to MAX/MIN: make result conversion explicit
ClosedPublic

Authored by jeanPerier on Jun 16 2020, 7:38 AM.

Details

Summary

This patch changes speficic extremum functions rewrite to generic MIN/MAX.
It applies to AMAX0, AMIN0, AMAX1, AMIN1, MAX0, MIN0, MAX1, MIN1, DMAX1,
and DMIN1.

  • Do not re-write specific extremums to MAX/MIN in intrinsic Probe and let

folding rewrite it and introduc the conversion on the MIN/MAX result.

  • Also make operand promotion explicit in MIN/MAX folding.

For instance, after this patch:
AMAX0(int8, int4) is rewritten to REAL(MAX(int8, INT(int4, 8)))

All this care is to avoid rewritting it to MAX(REAL(int8), REAL(int4))
that may not always be numerically equivalent to the first rewrite.

Diff Detail

Event Timeline

jeanPerier created this revision.Jun 16 2020, 7:38 AM
Herald added a project: Restricted Project. · View Herald Transcript
klausler accepted this revision.Jun 16 2020, 10:22 AM
klausler added inline comments.
flang/lib/Evaluate/fold-implementation.h
700

Why is this limited to INTEGER here? Do AMAX0, AMIN0, DMAX1, and DMIN1 have separate handling elsewhere?

flang/lib/Evaluate/fold-integer.cpp
426

Since these are in alphabetical order, you should put the "min" cases lower.

This revision is now accepted and ready to land.Jun 16 2020, 10:22 AM
schweitz accepted this revision.Jun 16 2020, 10:38 AM
schweitz added inline comments.
flang/lib/Evaluate/fold-implementation.h
696

Is sign-extension always correct? Table 16.3 suggests AMAX0 has default integer arguments, which would possibly suggest truncation for something like INTEGER_16.

jeanPerier added inline comments.Jun 16 2020, 10:52 AM
flang/lib/Evaluate/fold-implementation.h
700

No, the real case is handled implicitly in the "then" just above. If the arguments are all real they will all be processed in the first case.
This "else" is only here to handle mixed integer/real operands (in case all previous operands were integer, the first real operand gives the intermediate MIN/MAX result type).
Currently, the intrinsic probing does not prevent such mixed category cases (a warning is emitted, like with non standard kind). So AMAX0(int4, real4) is rewritten to REAL(MAX(real4, int4)) = MAX(real4, REAL(int4)).
I can add a small comment to clarify this here.

jeanPerier marked an inline comment as done.Jun 17 2020, 6:43 AM
jeanPerier added inline comments.
flang/lib/Evaluate/fold-implementation.h
696

The code here is supporting a non standard extension. In standard Fortran, an INTEGER(16) argument in AMAX0 is illegal (unless it is the default integer type). Pgfortran, xlf and ifortran support non standard argument types in AMAX0. XLF and ifort never truncate the arguments but instead use REAL(MAX(a, b), 4), and that what was previously decided to do for f18 (documented in Extensions.md) . So in the INTEGER(16), the MAX would be performed on INTEGER(16) and the result be converted to REAL(4).
Pgfortran behaviour is to truncates the argument in general, but that is not true for all extremum specific intrinsics, so it is simpler and safer to align with ifort/xlf on this extension.
A warning is emitted in such non standard usage (since numerical stability between pgfortran/f18, ifort, xlf might be affected).

Add comments in AMAX0/MIN1... rewrite algorithm.

jeanPerier marked 4 inline comments as done.Jun 17 2020, 10:01 AM
This revision was automatically updated to reflect the committed changes.