FIR real and complex type were added before MLIR had all the real/complex types needed by Fortran.
Having to live with both these core FIR and MLIR types adds unnecessary complexity in flang code and makes it more inconvenient to interact with other dialects where MLIR built-in types are baked in.
Proposal:
- Replace fir.complex usages by mlir complex type
- Use
tuple<fxx, fxx>
type when translating C++ complex values in function signatures in flang. - Keep fir complex operations for now, but have them operate on mlir complex
Rational for 1. :
Previous efforts replaced fir.real usages by MLIR built-in floating point types. The same was attempted for fir.complex, but I rejected it, on the basis of ABIs issues: Fortran complex values are handled like C complex in function passing/returning ABIs. MLIR does not do any kind of target specific rewrite of its builtin complex type in func.func code generation, which ends-up having mlir complex being treated like an std::complex
(i.e., a struct of two floats). This led me think that we should keep fir.complex as a C complex like complex, and use MLIR complex type in signatures of functions taking/returning C++ complex.
I now think this was unneeded, and that MLIR intent was not to have mlir complex type be the C++ complex. In fact --convert-complex-to-libm
pass uses mlir complex type when generating libm calls like ccosf
, and it came to my attention that flang target-rewrite pass already treats mlir complex as the C complex (here).
Note that there is a thread to clarify the ABI intentions for convert-complex-to-libm
: Complex to Libm conversion ABI issues, but there is no conclusion (X86 32 bits is probably not a big MLIR priority). We can currently rely on flang target-rewrite pass to get the correct ABI, as long as convert-complex-to-libm
is run before it.
Rational for 2. :
Flang has also very little need for std::complex
support, its runtime was updated to takes and return std::complex
by reference to avoid ABIs issues. So using tuple<f32,f32>
with inserts/extracts to convert from/to mlir complex around any C++ calls with std::complex
values if needed in the future is good enough in my opinion.
Rational for 3. :
In the long term, it would be great to fully rely on the complex dialect for the sake of simplicity, but there previously was accuracy issues where the MLIR complex dialect codegen was not precise enough for what Fortran user expect by default. So more work is needed to access/test the accuracy of MLIR complex dialect for Fortran, and I would rather keep this separate from the type change.