The main purpose of this patch is to centralize the logic for creating MLIR operation entry blocks and for binding them to the corresponding symbols. This minimizes the chances of mixing arguments up for operations having multiple entry block argument-generating clauses and prevents divergence while binding arguments. Some changes implemented to this end are: - Split into two functions the creation of the entry block, and the binding of its arguments and the corresponding Fortran symbol. This enabled a significant simplification of the lowering of composite constructs, where it's no longer necessary to manually ensure the lists of arguments and symbols refer to the same variables in the same order and also match the expected order by the `BlockArgOpenMPOpInterface`. - Removed redundant and error-prone passing of types and locations from `ClauseProcessor` methods. Instead, these are obtained from the values in the appropriate clause operands structure. This also simplifies argument lists of several lowering functions. - Access block arguments of already created MLIR operations through the `BlockArgOpenMPOpInterface` instead of directly indexing the argument list of the operation, which is not scalable as more entry block argument-generating clauses are added to an operation. - Simplified the implementation of `genParallelOp` to no longer need to define different callbacks depending on whether delayed privatization is enabled.
164 lines
6.0 KiB
C++
164 lines
6.0 KiB
C++
//===-- Lower/OpenMP/ReductionProcessor.h -----------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef FORTRAN_LOWER_REDUCTIONPROCESSOR_H
|
|
#define FORTRAN_LOWER_REDUCTIONPROCESSOR_H
|
|
|
|
#include "Clauses.h"
|
|
#include "flang/Optimizer/Builder/FIRBuilder.h"
|
|
#include "flang/Optimizer/Dialect/FIRType.h"
|
|
#include "flang/Parser/parse-tree.h"
|
|
#include "flang/Semantics/symbol.h"
|
|
#include "flang/Semantics/type.h"
|
|
#include "mlir/IR/Location.h"
|
|
#include "mlir/IR/Types.h"
|
|
|
|
namespace mlir {
|
|
namespace omp {
|
|
class DeclareReductionOp;
|
|
} // namespace omp
|
|
} // namespace mlir
|
|
|
|
namespace Fortran {
|
|
namespace lower {
|
|
class AbstractConverter;
|
|
} // namespace lower
|
|
} // namespace Fortran
|
|
|
|
namespace Fortran {
|
|
namespace lower {
|
|
namespace omp {
|
|
|
|
class ReductionProcessor {
|
|
public:
|
|
// TODO: Move this enumeration to the OpenMP dialect
|
|
enum ReductionIdentifier {
|
|
ID,
|
|
USER_DEF_OP,
|
|
ADD,
|
|
SUBTRACT,
|
|
MULTIPLY,
|
|
AND,
|
|
OR,
|
|
EQV,
|
|
NEQV,
|
|
MAX,
|
|
MIN,
|
|
IAND,
|
|
IOR,
|
|
IEOR
|
|
};
|
|
|
|
static ReductionIdentifier
|
|
getReductionType(const omp::clause::ProcedureDesignator &pd);
|
|
|
|
static ReductionIdentifier
|
|
getReductionType(omp::clause::DefinedOperator::IntrinsicOperator intrinsicOp);
|
|
|
|
static bool
|
|
supportedIntrinsicProcReduction(const omp::clause::ProcedureDesignator &pd);
|
|
|
|
static const semantics::SourceName
|
|
getRealName(const semantics::Symbol *symbol);
|
|
|
|
static const semantics::SourceName
|
|
getRealName(const omp::clause::ProcedureDesignator &pd);
|
|
|
|
static std::string getReductionName(llvm::StringRef name,
|
|
const fir::KindMapping &kindMap,
|
|
mlir::Type ty, bool isByRef);
|
|
|
|
static std::string
|
|
getReductionName(omp::clause::DefinedOperator::IntrinsicOperator intrinsicOp,
|
|
const fir::KindMapping &kindMap, mlir::Type ty,
|
|
bool isByRef);
|
|
|
|
/// This function returns the identity value of the operator \p
|
|
/// reductionOpName. For example:
|
|
/// 0 + x = x,
|
|
/// 1 * x = x
|
|
static int getOperationIdentity(ReductionIdentifier redId,
|
|
mlir::Location loc);
|
|
|
|
static mlir::Value getReductionInitValue(mlir::Location loc, mlir::Type type,
|
|
ReductionIdentifier redId,
|
|
fir::FirOpBuilder &builder);
|
|
|
|
template <typename FloatOp, typename IntegerOp>
|
|
static mlir::Value getReductionOperation(fir::FirOpBuilder &builder,
|
|
mlir::Type type, mlir::Location loc,
|
|
mlir::Value op1, mlir::Value op2);
|
|
template <typename FloatOp, typename IntegerOp, typename ComplexOp>
|
|
static mlir::Value getReductionOperation(fir::FirOpBuilder &builder,
|
|
mlir::Type type, mlir::Location loc,
|
|
mlir::Value op1, mlir::Value op2);
|
|
|
|
static mlir::Value createScalarCombiner(fir::FirOpBuilder &builder,
|
|
mlir::Location loc,
|
|
ReductionIdentifier redId,
|
|
mlir::Type type, mlir::Value op1,
|
|
mlir::Value op2);
|
|
|
|
/// Creates an OpenMP reduction declaration and inserts it into the provided
|
|
/// symbol table. The declaration has a constant initializer with the neutral
|
|
/// value `initValue`, and the reduction combiner carried over from `reduce`.
|
|
/// TODO: add atomic region.
|
|
static mlir::omp::DeclareReductionOp
|
|
createDeclareReduction(fir::FirOpBuilder &builder,
|
|
llvm::StringRef reductionOpName,
|
|
const ReductionIdentifier redId, mlir::Type type,
|
|
mlir::Location loc, bool isByRef);
|
|
|
|
/// Creates a reduction declaration and associates it with an OpenMP block
|
|
/// directive.
|
|
static void addDeclareReduction(
|
|
mlir::Location currentLocation, lower::AbstractConverter &converter,
|
|
const omp::clause::Reduction &reduction,
|
|
llvm::SmallVectorImpl<mlir::Value> &reductionVars,
|
|
llvm::SmallVectorImpl<bool> &reduceVarByRef,
|
|
llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols,
|
|
llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSymbols);
|
|
};
|
|
|
|
template <typename FloatOp, typename IntegerOp>
|
|
mlir::Value
|
|
ReductionProcessor::getReductionOperation(fir::FirOpBuilder &builder,
|
|
mlir::Type type, mlir::Location loc,
|
|
mlir::Value op1, mlir::Value op2) {
|
|
type = fir::unwrapRefType(type);
|
|
assert(type.isIntOrIndexOrFloat() &&
|
|
"only integer, float and complex types are currently supported");
|
|
if (type.isIntOrIndex())
|
|
return builder.create<IntegerOp>(loc, op1, op2);
|
|
return builder.create<FloatOp>(loc, op1, op2);
|
|
}
|
|
|
|
template <typename FloatOp, typename IntegerOp, typename ComplexOp>
|
|
mlir::Value
|
|
ReductionProcessor::getReductionOperation(fir::FirOpBuilder &builder,
|
|
mlir::Type type, mlir::Location loc,
|
|
mlir::Value op1, mlir::Value op2) {
|
|
assert((type.isIntOrIndexOrFloat() || fir::isa_complex(type)) &&
|
|
"only integer, float and complex types are currently supported");
|
|
if (type.isIntOrIndex())
|
|
return builder.create<IntegerOp>(loc, op1, op2);
|
|
if (fir::isa_real(type))
|
|
return builder.create<FloatOp>(loc, op1, op2);
|
|
return builder.create<ComplexOp>(loc, op1, op2);
|
|
}
|
|
|
|
} // namespace omp
|
|
} // namespace lower
|
|
} // namespace Fortran
|
|
|
|
#endif // FORTRAN_LOWER_REDUCTIONPROCESSOR_H
|