diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -4031,20 +4031,41 @@ template CC genarr(const Fortran::evaluate::ComplexComponent &x) { - TODO(getLoc(), ""); + TODO(getLoc(), "ComplexComponent"); } template CC genarr(const Fortran::evaluate::Parentheses &x) { - TODO(getLoc(), ""); + mlir::Location loc = getLoc(); + if (isReferentiallyOpaque()) { + // Context is a call argument in, for example, an elemental procedure + // call. TODO: all array arguments should use array_load, array_access, + // array_amend, and INTENT(OUT), INTENT(INOUT) arguments should have + // array_merge_store ops. + TODO(loc, "parentheses on argument in elemental call"); + } + auto f = genarr(x.left()); + return [=](IterSpace iters) -> ExtValue { + auto val = f(iters); + mlir::Value base = fir::getBase(val); + auto newBase = + builder.create(loc, base.getType(), base); + return fir::substBase(val, newBase); + }; } - template CC genarr(const Fortran::evaluate::Negate> &x) { - TODO(getLoc(), ""); + mlir::Location loc = getLoc(); + auto f = genarr(x.left()); + return [=](IterSpace iters) -> ExtValue { + mlir::Value val = fir::getBase(f(iters)); + mlir::Type ty = + converter.genType(Fortran::common::TypeCategory::Integer, KIND); + mlir::Value zero = builder.createIntegerConstant(loc, ty, 0); + return builder.create(loc, zero, val); + }; } - template CC genarr(const Fortran::evaluate::Negate> &x) { @@ -4057,7 +4078,11 @@ template CC genarr(const Fortran::evaluate::Negate> &x) { - TODO(getLoc(), ""); + mlir::Location loc = getLoc(); + auto f = genarr(x.left()); + return [=](IterSpace iters) -> ExtValue { + return builder.create(loc, fir::getBase(f(iters))); + }; } //===--------------------------------------------------------------------===// @@ -4100,7 +4125,15 @@ template CC genarr( const Fortran::evaluate::Power> &x) { - TODO(getLoc(), "genarr Power>"); + mlir::Location loc = getLoc(); + mlir::Type ty = converter.genType(TC, KIND); + auto lf = genarr(x.left()); + auto rf = genarr(x.right()); + return [=](IterSpace iters) -> ExtValue { + mlir::Value lhs = fir::getBase(lf(iters)); + mlir::Value rhs = fir::getBase(rf(iters)); + return Fortran::lower::genPow(builder, loc, ty, lhs, rhs); + }; } template CC genarr( @@ -4909,14 +4942,67 @@ TODO(getLoc(), "genarr StructureConstructor"); } + //===--------------------------------------------------------------------===// + // LOCICAL operators (.NOT., .AND., .EQV., etc.) + //===--------------------------------------------------------------------===// + template CC genarr(const Fortran::evaluate::Not &x) { - TODO(getLoc(), "genarr Not"); + mlir::Location loc = getLoc(); + mlir::IntegerType i1Ty = builder.getI1Type(); + auto lambda = genarr(x.left()); + mlir::Value truth = builder.createBool(loc, true); + return [=](IterSpace iters) -> ExtValue { + mlir::Value logical = fir::getBase(lambda(iters)); + mlir::Value val = builder.createConvert(loc, i1Ty, logical); + return builder.create(loc, val, truth); + }; + } + template + CC createBinaryBoolOp(const A &x) { + mlir::Location loc = getLoc(); + mlir::IntegerType i1Ty = builder.getI1Type(); + auto lf = genarr(x.left()); + auto rf = genarr(x.right()); + return [=](IterSpace iters) -> ExtValue { + mlir::Value left = fir::getBase(lf(iters)); + mlir::Value right = fir::getBase(rf(iters)); + mlir::Value lhs = builder.createConvert(loc, i1Ty, left); + mlir::Value rhs = builder.createConvert(loc, i1Ty, right); + return builder.create(loc, lhs, rhs); + }; + } + template + CC createCompareBoolOp(mlir::arith::CmpIPredicate pred, const A &x) { + mlir::Location loc = getLoc(); + mlir::IntegerType i1Ty = builder.getI1Type(); + auto lf = genarr(x.left()); + auto rf = genarr(x.right()); + return [=](IterSpace iters) -> ExtValue { + mlir::Value left = fir::getBase(lf(iters)); + mlir::Value right = fir::getBase(rf(iters)); + mlir::Value lhs = builder.createConvert(loc, i1Ty, left); + mlir::Value rhs = builder.createConvert(loc, i1Ty, right); + return builder.create(loc, pred, lhs, rhs); + }; } - template CC genarr(const Fortran::evaluate::LogicalOperation &x) { - TODO(getLoc(), "genarr LogicalOperation"); + switch (x.logicalOperator) { + case Fortran::evaluate::LogicalOperator::And: + return createBinaryBoolOp(x); + case Fortran::evaluate::LogicalOperator::Or: + return createBinaryBoolOp(x); + case Fortran::evaluate::LogicalOperator::Eqv: + return createCompareBoolOp( + mlir::arith::CmpIPredicate::eq, x); + case Fortran::evaluate::LogicalOperator::Neqv: + return createCompareBoolOp( + mlir::arith::CmpIPredicate::ne, x); + case Fortran::evaluate::LogicalOperator::Not: + llvm_unreachable(".NOT. handled elsewhere"); + } + llvm_unreachable("unhandled case"); } //===--------------------------------------------------------------------===// diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -234,6 +234,7 @@ /// if the argument is an integer, into llvm intrinsics if the argument is /// real and to the `hypot` math routine if the argument is of complex type. mlir::Value genAbs(mlir::Type, llvm::ArrayRef); + mlir::Value genAimag(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genAssociated(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genChar(mlir::Type, llvm::ArrayRef); @@ -333,12 +334,14 @@ /// should be provided for all the intrinsic arguments for completeness. static constexpr IntrinsicHandler handlers[]{ {"abs", &I::genAbs}, + {"aimag", &I::genAimag}, {"associated", &I::genAssociated, {{{"pointer", asInquired}, {"target", asInquired}}}, /*isElemental=*/false}, {"char", &I::genChar}, {"iand", &I::genIand}, + {"min", &I::genExtremum}, {"sum", &I::genSum, {{{"array", asBox}, @@ -1056,6 +1059,14 @@ llvm_unreachable("unexpected type in ABS argument"); } +// AIMAG +mlir::Value IntrinsicLibrary::genAimag(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + return fir::factory::Complex{builder, loc}.extractComplexPart( + args[0], true /* isImagPart */); +} + // ASSOCIATED fir::ExtendedValue IntrinsicLibrary::genAssociated(mlir::Type resultType, diff --git a/flang/lib/Lower/array-elemental-calls-2.f90 b/flang/test/Lower/array-elemental-calls-2.f90 rename from flang/lib/Lower/array-elemental-calls-2.f90 rename to flang/test/Lower/array-elemental-calls-2.f90 --- a/flang/lib/Lower/array-elemental-calls-2.f90 +++ b/flang/test/Lower/array-elemental-calls-2.f90 @@ -81,7 +81,7 @@ ! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32 ! CHECK: %[[VAL_26:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32 ! CHECK: %[[VAL_27:.*]] = arith.cmpi slt, %[[VAL_25]], %[[VAL_26]] : i32 - ! CHECK: %[[VAL_28:.*]] = select %[[VAL_27]], %[[VAL_25]], %[[VAL_26]] : i32 + ! CHECK: %[[VAL_28:.*]] = arith.select %[[VAL_27]], %[[VAL_25]], %[[VAL_26]] : i32 ! CHECK: fir.store %[[VAL_28]] to %[[VAL_0]] : !fir.ref ! CHECK: fir.call @_QPelem_func(%[[VAL_0]]) : (!fir.ref) -> i32 end subroutine