blob: c393e2f90f88ff7e26c20af72905e5514e894788 [file] [edit]
//===- UnimplementedDeviceCheck.cpp ---------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Diagnose not-yet-implemented target device cases.
//
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/OpenMP/Passes.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/IR/BuiltinOps.h"
using namespace mlir;
namespace flangomp {
#define GEN_PASS_DEF_UNIMPLEMENTEDDEVICECHECKPASS
#include "flang/Optimizer/OpenMP/Passes.h.inc"
} // namespace flangomp
/// Check whether all uses of the given symbol inside of the module are only
/// intended for the host.
static bool allUsesInHostCode(Operation *moduleOp, SymbolOpInterface symOp) {
if (auto symUses = symOp.getSymbolUses(moduleOp)) {
for (auto symUse : symUses.value()) {
Operation *symUser = symUse.getUser();
if (!symUser)
continue;
if (symUser->getParentOfType<omp::TargetOp>())
return false;
if (auto declareTargetOp =
symUser->getParentOfType<omp::DeclareTargetInterface>()) {
if (declareTargetOp.isDeclareTarget() &&
declareTargetOp.getDeclareTargetDeviceType() !=
omp::DeclareTargetDeviceType::host)
return false;
}
}
}
return true;
}
/// Emit not-yet-implemented errors for reductions over dynamically-shaped
/// arrays.
static LogicalResult checkReduction(omp::DeclareReductionOp reductionOp) {
if (!reductionOp.getByrefElementType())
return success();
auto seqTy = dyn_cast<fir::SequenceType>(*reductionOp.getByrefElementType());
bool isByRefReductionSupported =
!seqTy || !fir::sequenceWithNonConstantShape(seqTy);
if (!isByRefReductionSupported)
return reductionOp.emitError()
<< "not yet implemented: Reduction of dynamically-shaped arrays on "
"the GPU.";
return success();
}
namespace {
class UnimplementedDeviceCheckPass
: public flangomp::impl::UnimplementedDeviceCheckPassBase<
UnimplementedDeviceCheckPass> {
void runOnOperation() override {
// Only run checks when compiling for a target device.
auto op = dyn_cast<omp::OffloadModuleInterface>(*getOperation());
if (!op || !op.getIsTargetDevice())
return;
bool errorsEmitted = false;
if (op.getIsGPU()) {
op->walk([&](omp::DeclareReductionOp reductionOp) {
// Only check reductions that aren't exclusively used on the host.
if (op.getIsGPU() && !allUsesInHostCode(op, reductionOp)) {
if (failed(checkReduction(reductionOp)))
errorsEmitted = true;
}
});
}
if (errorsEmitted)
signalPassFailure();
markAllAnalysesPreserved();
}
};
} // namespace