[flang-commits] [flang] [flang][OpenMP] Diagnose task reduction array sections and elements (PR #215997)
via flang-commits
flang-commits at lists.llvm.org
Mon Sep 7 21:13:32 PDT 2026
================
@@ -1705,11 +1706,132 @@ getObjectsSyms(llvm::ArrayRef<Object> objects) {
return syms;
}
+enum class UserDefinedReductionSubobject {
+ None,
+ ArrayElement,
+ PartialArraySection,
+};
+
+static bool isUserDefinedReductionOperator(
+ const omp::clause::ReductionOperator &reductionOperator,
+ const Object &object, lower::AbstractConverter &converter,
+ semantics::SemanticsContext &semaCtx) {
+ const semantics::Symbol *objectSymbol = object.sym();
+ const semantics::DeclTypeSpec *objectType =
+ objectSymbol ? objectSymbol->GetUltimate().GetType() : nullptr;
+ if (!objectType)
+ return false;
+
+ return common::visit(
+ common::visitors{
+ [&](const omp::clause::DefinedOperator &definedOperator) {
+ return common::visit(
+ common::visitors{
+ [&](const omp::clause::DefinedOperator::IntrinsicOperator
+ &op) {
+ using IntrinsicOperator =
+ omp::clause::DefinedOperator::IntrinsicOperator;
+ switch (op) {
+ case IntrinsicOperator::Add:
+ case IntrinsicOperator::Multiply:
+ case IntrinsicOperator::AND:
+ case IntrinsicOperator::OR:
+ case IntrinsicOperator::EQV:
+ case IntrinsicOperator::NEQV:
+ break;
+ default:
+ return false;
+ }
+
+ parser::CharBlock mangledName =
+ semantics::omp::MangledIntrinsicOperatorReductionName(
+ ReductionProcessor::toParserIntrinsicOperator(op),
+ semaCtx);
+ return semantics::omp::FindUserReductionSymbol(
+ converter.getCurrentScope(), mangledName,
+ objectType) != nullptr;
+ },
+ [&](const omp::clause::DefinedOperator::DefinedOpName &op) {
+ const semantics::Symbol *operatorSymbol = op.v.sym();
+ return operatorSymbol &&
+ semantics::omp::FindOperatorUserReductionSymbol(
+ converter.getCurrentScope(), *operatorSymbol,
+ objectType);
+ },
+ },
+ definedOperator.u);
+ },
+ [&](const omp::clause::ProcedureDesignator &procedureDesignator) {
+ const semantics::Symbol *symbol = procedureDesignator.v.sym();
+ return (symbol &&
+ symbol->GetUltimate()
+ .detailsIf<semantics::UserReductionDetails>()) ||
+ ReductionProcessor::findUserDefinedReductionForIntrinsic(
+ converter.getCurrentScope(), procedureDesignator,
+ objectType) != nullptr;
+ },
+ },
+ reductionOperator.u);
+}
+
+template <typename ReductionClause>
+static UserDefinedReductionSubobject
+getUserDefinedReductionSubobject(const ReductionClause &clause,
+ lower::AbstractConverter &converter,
+ semantics::SemanticsContext &semaCtx) {
+ // ReductionProcessor receives only base symbols, so classify unsupported
+ // subobjects before lowering discards their designators.
+ const auto &reductionOperators =
+ std::get<omp::clause::ReductionOperatorList>(clause.t);
+ assert(reductionOperators.size() == 1 && "expected one reduction operator");
+
+ for (const Object &object : std::get<omp::ObjectList>(clause.t)) {
+ if (!object.ref())
+ continue;
+
+ UserDefinedReductionSubobject subobject =
+ UserDefinedReductionSubobject::None;
+ if (object.ref()->Rank() == 0 &&
----------------
MattPD wrote:
A user-defined reduction on a complex part of an array element bypasses this classification:
```fortran
subroutine s(z)
complex :: z(4)
!$omp declare reduction(+: real : omp_out = omp_out + omp_in) &
!$omp& initializer(omp_priv = 1.0)
!$omp parallel reduction(+: z(2)%re)
z(2)%re = z(2)%re + 1.0
!$omp end parallel
end
```
The compiler emits the user-defined reduction for `real`. The `omp.parallel` operation still references `@add_reduction_byref_box_4xz32`, the predefined reduction over the whole complex array. Its combiner processes all four complex elements, and the body updates only the real part of element 2.
`z(2)%re` has rank zero, and the classification does not descend through `ComplexPart`. Reduction lookup then uses the complex type of the base symbol instead of the `real` type of the list item.
Could this check classify the whole designator, including the complex part, and look the reduction up by the type of the list item? Until lowering preserves the complex part, the user-defined case could report the same error this patch reports for a user-defined reduction on an array element. A predefined reduction on a complex part could stay accepted.
https://github.com/llvm/llvm-project/pull/215997
More information about the flang-commits
mailing list