mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 16:11:29 +00:00
[flang] Lower elemental calls
This patch adds more lowering of operations sub-expression inside elemental call arguments. It tests array contexts where an address is needed for each element (for the argument), but part of the array sub-expression must be lowered by value (for the operation) This patch is part of the upstreaming effort from fir-dev branch. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D121606 Co-authored-by: Jean Perier <jperier@nvidia.com> Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
This commit is contained in:
parent
55cf09ae26
commit
7b917fd284
@ -4031,20 +4031,41 @@ public:
|
|||||||
|
|
||||||
template <int KIND>
|
template <int KIND>
|
||||||
CC genarr(const Fortran::evaluate::ComplexComponent<KIND> &x) {
|
CC genarr(const Fortran::evaluate::ComplexComponent<KIND> &x) {
|
||||||
TODO(getLoc(), "");
|
TODO(getLoc(), "ComplexComponent<KIND>");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
CC genarr(const Fortran::evaluate::Parentheses<T> &x) {
|
CC genarr(const Fortran::evaluate::Parentheses<T> &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<fir::NoReassocOp>(loc, base.getType(), base);
|
||||||
|
return fir::substBase(val, newBase);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int KIND>
|
template <int KIND>
|
||||||
CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
|
CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
|
||||||
Fortran::common::TypeCategory::Integer, KIND>> &x) {
|
Fortran::common::TypeCategory::Integer, KIND>> &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<mlir::arith::SubIOp>(loc, zero, val);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int KIND>
|
template <int KIND>
|
||||||
CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
|
CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
|
||||||
Fortran::common::TypeCategory::Real, KIND>> &x) {
|
Fortran::common::TypeCategory::Real, KIND>> &x) {
|
||||||
@ -4057,7 +4078,11 @@ public:
|
|||||||
template <int KIND>
|
template <int KIND>
|
||||||
CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
|
CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type<
|
||||||
Fortran::common::TypeCategory::Complex, KIND>> &x) {
|
Fortran::common::TypeCategory::Complex, KIND>> &x) {
|
||||||
TODO(getLoc(), "");
|
mlir::Location loc = getLoc();
|
||||||
|
auto f = genarr(x.left());
|
||||||
|
return [=](IterSpace iters) -> ExtValue {
|
||||||
|
return builder.create<fir::NegcOp>(loc, fir::getBase(f(iters)));
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
@ -4100,7 +4125,15 @@ public:
|
|||||||
template <Fortran::common::TypeCategory TC, int KIND>
|
template <Fortran::common::TypeCategory TC, int KIND>
|
||||||
CC genarr(
|
CC genarr(
|
||||||
const Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>> &x) {
|
const Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>> &x) {
|
||||||
TODO(getLoc(), "genarr Power<Fortran::evaluate::Type<TC, KIND>>");
|
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 <Fortran::common::TypeCategory TC, int KIND>
|
template <Fortran::common::TypeCategory TC, int KIND>
|
||||||
CC genarr(
|
CC genarr(
|
||||||
@ -4909,14 +4942,67 @@ public:
|
|||||||
TODO(getLoc(), "genarr StructureConstructor");
|
TODO(getLoc(), "genarr StructureConstructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int KIND>
|
//===--------------------------------------------------------------------===//
|
||||||
CC genarr(const Fortran::evaluate::Not<KIND> &x) {
|
// LOCICAL operators (.NOT., .AND., .EQV., etc.)
|
||||||
TODO(getLoc(), "genarr Not");
|
//===--------------------------------------------------------------------===//
|
||||||
}
|
|
||||||
|
|
||||||
|
template <int KIND>
|
||||||
|
CC genarr(const Fortran::evaluate::Not<KIND> &x) {
|
||||||
|
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<mlir::arith::XOrIOp>(loc, val, truth);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
template <typename OP, typename A>
|
||||||
|
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<OP>(loc, lhs, rhs);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
template <typename OP, typename A>
|
||||||
|
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<OP>(loc, pred, lhs, rhs);
|
||||||
|
};
|
||||||
|
}
|
||||||
template <int KIND>
|
template <int KIND>
|
||||||
CC genarr(const Fortran::evaluate::LogicalOperation<KIND> &x) {
|
CC genarr(const Fortran::evaluate::LogicalOperation<KIND> &x) {
|
||||||
TODO(getLoc(), "genarr LogicalOperation");
|
switch (x.logicalOperator) {
|
||||||
|
case Fortran::evaluate::LogicalOperator::And:
|
||||||
|
return createBinaryBoolOp<mlir::arith::AndIOp>(x);
|
||||||
|
case Fortran::evaluate::LogicalOperator::Or:
|
||||||
|
return createBinaryBoolOp<mlir::arith::OrIOp>(x);
|
||||||
|
case Fortran::evaluate::LogicalOperator::Eqv:
|
||||||
|
return createCompareBoolOp<mlir::arith::CmpIOp>(
|
||||||
|
mlir::arith::CmpIPredicate::eq, x);
|
||||||
|
case Fortran::evaluate::LogicalOperator::Neqv:
|
||||||
|
return createCompareBoolOp<mlir::arith::CmpIOp>(
|
||||||
|
mlir::arith::CmpIPredicate::ne, x);
|
||||||
|
case Fortran::evaluate::LogicalOperator::Not:
|
||||||
|
llvm_unreachable(".NOT. handled elsewhere");
|
||||||
|
}
|
||||||
|
llvm_unreachable("unhandled case");
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
@ -234,6 +234,7 @@ struct IntrinsicLibrary {
|
|||||||
/// if the argument is an integer, into llvm intrinsics if the argument is
|
/// 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.
|
/// real and to the `hypot` math routine if the argument is of complex type.
|
||||||
mlir::Value genAbs(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
mlir::Value genAbs(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
||||||
|
mlir::Value genAimag(mlir::Type, llvm::ArrayRef<mlir::Value>);
|
||||||
fir::ExtendedValue genAssociated(mlir::Type,
|
fir::ExtendedValue genAssociated(mlir::Type,
|
||||||
llvm::ArrayRef<fir::ExtendedValue>);
|
llvm::ArrayRef<fir::ExtendedValue>);
|
||||||
fir::ExtendedValue genChar(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
fir::ExtendedValue genChar(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
|
||||||
@ -333,12 +334,14 @@ static constexpr bool handleDynamicOptional = true;
|
|||||||
/// should be provided for all the intrinsic arguments for completeness.
|
/// should be provided for all the intrinsic arguments for completeness.
|
||||||
static constexpr IntrinsicHandler handlers[]{
|
static constexpr IntrinsicHandler handlers[]{
|
||||||
{"abs", &I::genAbs},
|
{"abs", &I::genAbs},
|
||||||
|
{"aimag", &I::genAimag},
|
||||||
{"associated",
|
{"associated",
|
||||||
&I::genAssociated,
|
&I::genAssociated,
|
||||||
{{{"pointer", asInquired}, {"target", asInquired}}},
|
{{{"pointer", asInquired}, {"target", asInquired}}},
|
||||||
/*isElemental=*/false},
|
/*isElemental=*/false},
|
||||||
{"char", &I::genChar},
|
{"char", &I::genChar},
|
||||||
{"iand", &I::genIand},
|
{"iand", &I::genIand},
|
||||||
|
{"min", &I::genExtremum<Extremum::Min, ExtremumBehavior::MinMaxss>},
|
||||||
{"sum",
|
{"sum",
|
||||||
&I::genSum,
|
&I::genSum,
|
||||||
{{{"array", asBox},
|
{{{"array", asBox},
|
||||||
@ -1056,6 +1059,14 @@ mlir::Value IntrinsicLibrary::genAbs(mlir::Type resultType,
|
|||||||
llvm_unreachable("unexpected type in ABS argument");
|
llvm_unreachable("unexpected type in ABS argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AIMAG
|
||||||
|
mlir::Value IntrinsicLibrary::genAimag(mlir::Type resultType,
|
||||||
|
llvm::ArrayRef<mlir::Value> args) {
|
||||||
|
assert(args.size() == 1);
|
||||||
|
return fir::factory::Complex{builder, loc}.extractComplexPart(
|
||||||
|
args[0], true /* isImagPart */);
|
||||||
|
}
|
||||||
|
|
||||||
// ASSOCIATED
|
// ASSOCIATED
|
||||||
fir::ExtendedValue
|
fir::ExtendedValue
|
||||||
IntrinsicLibrary::genAssociated(mlir::Type resultType,
|
IntrinsicLibrary::genAssociated(mlir::Type resultType,
|
||||||
|
@ -81,7 +81,7 @@ module test_ops
|
|||||||
! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32
|
! CHECK: %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xi32>, index) -> i32
|
||||||
! CHECK: %[[VAL_26:.*]] = 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_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<i32>
|
! CHECK: fir.store %[[VAL_28]] to %[[VAL_0]] : !fir.ref<i32>
|
||||||
! CHECK: fir.call @_QPelem_func(%[[VAL_0]]) : (!fir.ref<i32>) -> i32
|
! CHECK: fir.call @_QPelem_func(%[[VAL_0]]) : (!fir.ref<i32>) -> i32
|
||||||
end subroutine
|
end subroutine
|
Loading…
Reference in New Issue
Block a user