blob: 73f5fbc2a829b930290183dadec3d77bb5cc8526 [file] [edit]
//===- ACCHostDataPatterns.cpp - ACC host_data to LLVM ---------*- 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
//
//===----------------------------------------------------------------------===//
//
// Lowering of the OpenACC host_data construct to the OpenACC runtime. Each
// use_device clause of the construct becomes the call that asks the runtime
// for the device address its object is mapped to, so that the body of the
// construct works on device addresses. An if clause on the construct decides
// between that address and the host one, and the body is left in place of the
// construct.
//
//===----------------------------------------------------------------------===//
#include "mlir/Conversion/OpenACCToLLVM/ACCToLLVM.h"
#include "mlir/Conversion/OpenACCToLLVM/ACCToLLVMUtils.h"
#include "mlir/Conversion/LLVMCommon/Pattern.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/IR/PatternMatch.h"
using namespace mlir;
using namespace mlir::acc;
/// Returns the host_data construct \p op gives a device address to, or null
/// when the clause belongs to no such construct.
static HostDataOp getHostDataConstruct(UseDeviceOp op) {
for (Operation *user : op->getUsers())
if (auto hostData = dyn_cast<HostDataOp>(user))
return hostData;
return nullptr;
}
namespace {
/// A use_device clause stands for the device address of the object it names,
/// so it becomes the call that asks the runtime for that address. The call is
/// emitted before the construct, so that every use of the clause in its body
/// is reached by it.
struct UseDeviceOpLowering : public ConvertOpToLLVMPattern<UseDeviceOp> {
UseDeviceOpLowering(const LLVMTypeConverter &converter,
Region &globalSymbolRegion, SymbolTable &symbolTable,
const ACCRuntimeCallConfig &config,
PatternBenefit benefit = 1)
: ConvertOpToLLVMPattern<UseDeviceOp>(converter, benefit),
globalSymbolRegion(globalSymbolRegion), symbolTable(symbolTable),
config(config) {}
LogicalResult
matchAndRewrite(UseDeviceOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
HostDataOp hostData = getHostDataConstruct(op);
if (!hostData)
return rewriter.notifyMatchFailure(
op, "use_device clause of no host_data construct");
Location loc = op.getLoc();
Value hostPtr = adaptor.getVar();
auto emitCall = [&]() -> FailureOr<Value> {
return acc::emitGetDevicePtrCall(op, hostPtr, hostData.getIfPresent(),
rewriter, globalSymbolRegion,
symbolTable, config);
};
// An if clause that does not hold leaves the body on host addresses.
auto keepHostPtr = [&]() -> FailureOr<Value> { return hostPtr; };
Value ifCond = hostData.getIfCond()
? rewriter.getRemappedValue(hostData.getIfCond())
: Value();
if (ifCond)
rewriter.setInsertionPoint(hostData);
FailureOr<Value> devicePtr = acc::emitValueSelectedByIfCond(
loc, ifCond, rewriter, emitCall, keepHostPtr);
if (failed(devicePtr))
return failure();
rewriter.replaceOp(op, *devicePtr);
return success();
}
Region &globalSymbolRegion;
SymbolTable &symbolTable;
ACCRuntimeCallConfig config;
};
/// The construct itself has nothing left to do once its clauses hold device
/// addresses, so its body takes its place.
struct HostDataOpLowering : public ConvertOpToLLVMPattern<HostDataOp> {
using ConvertOpToLLVMPattern<HostDataOp>::ConvertOpToLLVMPattern;
LogicalResult
matchAndRewrite(HostDataOp op, OpAdaptor,
ConversionPatternRewriter &rewriter) const override {
acc::spliceConstructRegion(op, op.getRegion(), rewriter);
rewriter.eraseOp(op);
return success();
}
};
} // namespace
void mlir::configureACCHostDataConversionLegality(ConversionTarget &target) {
target.addIllegalOp<acc::HostDataOp, acc::UseDeviceOp>();
}
void mlir::populateACCHostDataPatterns(
LLVMTypeConverter &converter, RewritePatternSet &patterns,
Region &globalSymbolRegion, SymbolTable &symbolTable,
const acc::ACCRuntimeCallConfig &config) {
patterns.add<UseDeviceOpLowering>(converter, globalSymbolRegion, symbolTable,
config);
patterns.add<HostDataOpLowering>(converter);
}