[flang] Fix folding of CMPLX

The code for folding calls to the intrinsic function CMPLX was
incorrectly dependent on the number of arguments to distinguish its
two cases (conversion from one kind of complex to another, and
composition of a complex value from real & imaginary parts).
This was wrong since the optional KIND= argument has already been
taken into account by intrinsic processing; instead, the type of
the first argument should decide the issue.

Differential Revision: https://reviews.llvm.org/D103568
This commit is contained in:
peter klausler 2021-06-02 16:59:31 -07:00
parent 53ab2d821e
commit 6fa5353a56

View File

@ -34,25 +34,23 @@ Expr<Type<TypeCategory::Complex, KIND>> FoldIntrinsicFunction(
return FoldElementalIntrinsic<T, T>(
context, std::move(funcRef), &Scalar<T>::CONJG);
} else if (name == "cmplx") {
using Part = typename T::Part;
if (args.size() == 2) { // CMPLX(X, [KIND])
if (args.size() > 0 && args[0].has_value()) {
if (auto *x{UnwrapExpr<Expr<SomeComplex>>(args[0])}) {
// CMPLX(X [, KIND]) with complex X
return Fold(context, ConvertToType<T>(std::move(*x)));
} else {
// CMPLX(X [, Y [, KIND]]) with non-complex X
using Part = typename T::Part;
Expr<SomeType> re{std::move(*args[0].value().UnwrapExpr())};
Expr<SomeType> im{args.size() >= 2 && args[1].has_value()
? std::move(*args[1]->UnwrapExpr())
: AsGenericExpr(Constant<Part>{Scalar<Part>{}})};
return Fold(context,
Expr<T>{
ComplexConstructor<KIND>{ToReal<KIND>(context, std::move(re)),
ToReal<KIND>(context, std::move(im))}});
}
Expr<SomeType> re{std::move(*args[0].value().UnwrapExpr())};
Expr<SomeType> im{AsGenericExpr(Constant<Part>{Scalar<Part>{}})};
return Fold(context,
Expr<T>{ComplexConstructor<KIND>{ToReal<KIND>(context, std::move(re)),
ToReal<KIND>(context, std::move(im))}});
}
// CMPLX(X, [Y, KIND])
CHECK(args.size() == 3);
Expr<SomeType> re{std::move(*args[0].value().UnwrapExpr())};
Expr<SomeType> im{args[1] ? std::move(*args[1].value().UnwrapExpr())
: AsGenericExpr(Constant<Part>{Scalar<Part>{}})};
return Fold(context,
Expr<T>{ComplexConstructor<KIND>{ToReal<KIND>(context, std::move(re)),
ToReal<KIND>(context, std::move(im))}});
} else if (name == "merge") {
return FoldMerge<T>(context, std::move(funcRef));
}