This patch adds support for lowering OpenMP clauses and expressions attached to constructs nested inside of a target region that need to be evaluated in the host device. This is done through the use of the `OpenMP_HostEvalClause` `omp.target` set of operands and entry block arguments. When lowering clauses for a target construct, a more involved `processHostEvalClauses()` function is called, which looks at the current and potentially other nested constructs in order to find and lower clauses that need to be processed outside of the `omp.target` operation under construction. This populates an instance of a global structure with the resulting MLIR values. The resulting list of host-evaluated values is used to initialize the `host_eval` operands when constructing the `omp.target` operation, and then replaced with the corresponding block arguments after creating that operation's region. Afterwards, while lowering nested operations, those that might potentially be evaluated on the host (i.e. `num_teams`, `thread_limit`, `num_threads` and `collapse`) check first whether there is an active global host-evaluated information structure and whether it holds values referring to these clauses. If that is the case, the stored values (`omp.target` entry block arguments at that stage) are used instead of lowering these clauses again.
49 lines
1.9 KiB
C++
49 lines
1.9 KiB
C++
//===-- include/flang/Common/OpenMP-utils.cpp ------------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Common/OpenMP-utils.h"
|
|
|
|
#include "mlir/IR/OpDefinition.h"
|
|
|
|
namespace Fortran::common::openmp {
|
|
mlir::Block *genEntryBlock(mlir::OpBuilder &builder, const EntryBlockArgs &args,
|
|
mlir::Region ®ion) {
|
|
assert(args.isValid() && "invalid args");
|
|
assert(region.empty() && "non-empty region");
|
|
|
|
llvm::SmallVector<mlir::Type> types;
|
|
llvm::SmallVector<mlir::Location> locs;
|
|
unsigned numVars = args.hostEvalVars.size() + args.inReduction.vars.size() +
|
|
args.map.vars.size() + args.priv.vars.size() +
|
|
args.reduction.vars.size() + args.taskReduction.vars.size() +
|
|
args.useDeviceAddr.vars.size() + args.useDevicePtr.vars.size();
|
|
types.reserve(numVars);
|
|
locs.reserve(numVars);
|
|
|
|
auto extractTypeLoc = [&types, &locs](llvm::ArrayRef<mlir::Value> vals) {
|
|
llvm::transform(vals, std::back_inserter(types),
|
|
[](mlir::Value v) { return v.getType(); });
|
|
llvm::transform(vals, std::back_inserter(locs),
|
|
[](mlir::Value v) { return v.getLoc(); });
|
|
};
|
|
|
|
// Populate block arguments in clause name alphabetical order to match
|
|
// expected order by the BlockArgOpenMPOpInterface.
|
|
extractTypeLoc(args.hostEvalVars);
|
|
extractTypeLoc(args.inReduction.vars);
|
|
extractTypeLoc(args.map.vars);
|
|
extractTypeLoc(args.priv.vars);
|
|
extractTypeLoc(args.reduction.vars);
|
|
extractTypeLoc(args.taskReduction.vars);
|
|
extractTypeLoc(args.useDeviceAddr.vars);
|
|
extractTypeLoc(args.useDevicePtr.vars);
|
|
|
|
return builder.createBlock(®ion, {}, types, locs);
|
|
}
|
|
} // namespace Fortran::common::openmp
|