Skip to content

Commit 3b7989c

Browse files
authored
[flang] remove support for std::complex value lowering. (#110643)
To avoid ABIs issues, std::complex should be passed/returned by reference to the runtime. Part of the [RFC to use mlir complex type](https://discourse.llvm.org/t/rfc-flang-replace-usages-of-fir-complex-by-mlir-complex-type/82292).
1 parent 30ea7e8 commit 3b7989c

File tree

2 files changed

+52
-20
lines changed

2 files changed

+52
-20
lines changed

flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -400,17 +400,19 @@ constexpr TypeBuilderFunc getModel<bool &>() {
400400
return fir::ReferenceType::get(f(context));
401401
};
402402
}
403-
template <>
404-
constexpr TypeBuilderFunc getModel<std::complex<float>>() {
405-
return [](mlir::MLIRContext *context) -> mlir::Type {
406-
return mlir::ComplexType::get(mlir::FloatType::getF32(context));
407-
};
408-
}
403+
404+
// getModel<std::complex<T>> are not implemented on purpose.
405+
// Prefer passing/returning the complex by reference in the runtime to
406+
// avoid ABI issues.
407+
// C++ std::complex is not an intrinsic type, and while it is storage
408+
// compatible with C/Fortran complex type, it follows the struct value passing
409+
// ABI rule, which may differ from how C complex are passed on some platforms.
410+
409411
template <>
410412
constexpr TypeBuilderFunc getModel<std::complex<float> &>() {
411413
return [](mlir::MLIRContext *context) -> mlir::Type {
412-
TypeBuilderFunc f{getModel<std::complex<float>>()};
413-
return fir::ReferenceType::get(f(context));
414+
mlir::Type floatTy = getModel<float>()(context);
415+
return fir::ReferenceType::get(mlir::ComplexType::get(floatTy));
414416
};
415417
}
416418
template <>
@@ -422,16 +424,10 @@ constexpr TypeBuilderFunc getModel<const std::complex<float> *>() {
422424
return getModel<std::complex<float> *>();
423425
}
424426
template <>
425-
constexpr TypeBuilderFunc getModel<std::complex<double>>() {
426-
return [](mlir::MLIRContext *context) -> mlir::Type {
427-
return mlir::ComplexType::get(mlir::FloatType::getF64(context));
428-
};
429-
}
430-
template <>
431427
constexpr TypeBuilderFunc getModel<std::complex<double> &>() {
432428
return [](mlir::MLIRContext *context) -> mlir::Type {
433-
TypeBuilderFunc f{getModel<std::complex<double>>()};
434-
return fir::ReferenceType::get(f(context));
429+
mlir::Type floatTy = getModel<double>()(context);
430+
return fir::ReferenceType::get(mlir::ComplexType::get(floatTy));
435431
};
436432
}
437433
template <>
@@ -521,10 +517,45 @@ REDUCTION_VALUE_OPERATION_MODEL(double)
521517
REDUCTION_REF_OPERATION_MODEL(long double)
522518
REDUCTION_VALUE_OPERATION_MODEL(long double)
523519

524-
REDUCTION_REF_OPERATION_MODEL(std::complex<float>)
525-
REDUCTION_VALUE_OPERATION_MODEL(std::complex<float>)
526-
REDUCTION_REF_OPERATION_MODEL(std::complex<double>)
527-
REDUCTION_VALUE_OPERATION_MODEL(std::complex<double>)
520+
// FIXME: the runtime is not using the correct ABIs when calling complex
521+
// callbacks. lowering either need to create wrappers or just have an inline
522+
// implementation for it. https://github.com/llvm/llvm-project/issues/110674
523+
template <>
524+
constexpr TypeBuilderFunc
525+
getModel<Fortran::runtime::ValueReductionOperation<std::complex<float>>>() {
526+
return [](mlir::MLIRContext *context) -> mlir::Type {
527+
mlir::Type cplx = mlir::ComplexType::get(getModel<float>()(context));
528+
auto refTy = fir::ReferenceType::get(cplx);
529+
return mlir::FunctionType::get(context, {cplx, cplx}, refTy);
530+
};
531+
}
532+
template <>
533+
constexpr TypeBuilderFunc
534+
getModel<Fortran::runtime::ValueReductionOperation<std::complex<double>>>() {
535+
return [](mlir::MLIRContext *context) -> mlir::Type {
536+
mlir::Type cplx = mlir::ComplexType::get(getModel<double>()(context));
537+
auto refTy = fir::ReferenceType::get(cplx);
538+
return mlir::FunctionType::get(context, {cplx, cplx}, refTy);
539+
};
540+
}
541+
template <>
542+
constexpr TypeBuilderFunc
543+
getModel<Fortran::runtime::ReferenceReductionOperation<std::complex<float>>>() {
544+
return [](mlir::MLIRContext *context) -> mlir::Type {
545+
mlir::Type cplx = mlir::ComplexType::get(getModel<float>()(context));
546+
auto refTy = fir::ReferenceType::get(cplx);
547+
return mlir::FunctionType::get(context, {refTy, refTy}, refTy);
548+
};
549+
}
550+
template <>
551+
constexpr TypeBuilderFunc getModel<
552+
Fortran::runtime::ReferenceReductionOperation<std::complex<double>>>() {
553+
return [](mlir::MLIRContext *context) -> mlir::Type {
554+
mlir::Type cplx = mlir::ComplexType::get(getModel<double>()(context));
555+
auto refTy = fir::ReferenceType::get(cplx);
556+
return mlir::FunctionType::get(context, {refTy, refTy}, refTy);
557+
};
558+
}
528559

529560
REDUCTION_CHAR_OPERATION_MODEL(char)
530561
REDUCTION_CHAR_OPERATION_MODEL(char16_t)

flang/unittests/Optimizer/RTBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
1010
#include "gtest/gtest.h"
1111
#include "flang/Optimizer/Support/InitFIR.h"
12+
#include <complex>
1213

1314
// Check that it is possible to make a difference between complex runtime
1415
// function using C99 complex and C++ std::complex. This is important since

0 commit comments

Comments
 (0)