//===- ACCDataDirectivePatterns.cpp - ACC 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 data constructs - data, enter data, exit data,
// update and declare - to the data entry points of the OpenACC runtime. Each
// construct becomes one call per point where it establishes or tears down its
// mappings, which carries the argument arrays its operands are packed into,
// the queue its async clause selects and, before them, the wait its wait
// clause asks for. An if clause guards the calls it applies to, and the body
// of a structured construct is left in place of the construct.
//
//===----------------------------------------------------------------------===//

#include "mlir/Conversion/OpenACCToLLVM/ACCDataRuntime.h"
#include "mlir/Conversion/OpenACCToLLVM/ACCToLLVM.h"
#include "mlir/Conversion/OpenACCToLLVM/ACCToLLVMUtils.h"

#include "mlir/Conversion/LLVMCommon/Pattern.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/Dialect/OpenACC/OpenACCUtilsCG.h"
#include "mlir/Interfaces/FunctionInterfaces.h"

using namespace mlir;
using namespace mlir::acc;

/// Emits the call to the mapping entry point \p fn for \p mappingOperands, the
/// data-clause operands of a data construct, paired with their type converted
/// values in \p convertedOperands. \p regionFlags describe the data region
/// the call opens or closes.
static LogicalResult emitDataRuntimeCall(
    Location loc, RuntimeFunction fn, ValueRange mappingOperands,
    ValueRange convertedOperands, ACCDataCallKind callKind,
    ConversionPatternRewriter &rewriter, OpenACCSupport &accSupport,
    Region &globalSymbolRegion, SymbolTable &symbolTable,
    const ACCRuntimeCallConfig &config, ArrayRef<Value> trailingArguments,
    ACCDataRegionFlags regionFlags = ACCDataRegionFlags::None) {
  ACCDataCallOptions options;
  options.callKind = callKind;
  options.flags = static_cast<int64_t>(regionFlags);
  return emitACCDataRuntimeCall(
      loc, fn, mappingOperands, convertedOperands, rewriter, accSupport,
      globalSymbolRegion, symbolTable, config, trailingArguments, options);
}

/// Returns the action that the declare-action recipe holding \p op carries
/// out, which the recipe states by naming itself in the matching slot of its
/// `acc.declare_action` attribute. Returns a null attribute when \p op is not
/// in such a recipe.
static DeclareActionAttr getEnclosingDeclareAction(Operation *op) {
  auto func = dyn_cast<FunctionOpInterface>(op);
  if (!func)
    func = op->getParentOfType<FunctionOpInterface>();
  if (!func)
    return {};
  return func->getAttrOfType<DeclareActionAttr>(getDeclareActionAttrName());
}

static Value getDeclareAsyncQueue(Location loc,
                                  ConversionPatternRewriter &rewriter,
                                  const ACCRuntimeCallConfig &config) {
  return LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(),
                                  config.getAsyncSyncRuntimeValue());
}

namespace {
template <typename OpTy>
struct ACCDataDirectivePattern : public ConvertOpToLLVMPattern<OpTy> {
  ACCDataDirectivePattern(const LLVMTypeConverter &converter,
                          OpenACCSupport &accSupport,
                          Region &globalSymbolRegion, SymbolTable &symbolTable,
                          const ACCRuntimeCallConfig &config,
                          DeviceType clauseDeviceType,
                          PatternBenefit benefit = 1)
      : ConvertOpToLLVMPattern<OpTy>(converter, benefit),
        accSupport(accSupport), globalSymbolRegion(globalSymbolRegion),
        symbolTable(symbolTable), config(config),
        clauseDeviceType(clauseDeviceType) {}

  /// Returns the queue that the mapping calls of \p op run on.
  Value getAsyncQueue(OpTy op, ConversionPatternRewriter &rewriter) const {
    return acc::getAsyncQueue(op, clauseDeviceType, rewriter, config);
  }

  /// Emits the wait that a wait clause on \p op asks for before its mapping
  /// calls.
  LogicalResult emitWaitClause(OpTy op, Value asyncQueue,
                               ConversionPatternRewriter &rewriter) const {
    return acc::emitWaitClause(op, clauseDeviceType, asyncQueue, rewriter,
                               accSupport, globalSymbolRegion, symbolTable,
                               config);
  }

  /// Emits one mapping call for the data-clause operands of \p op.
  LogicalResult emitMappingCall(OpTy op, ValueRange convertedOperands,
                                Location loc, RuntimeFunction fn,
                                ACCDataCallKind callKind, Value asyncQueue,
                                ConversionPatternRewriter &rewriter) const {
    return emitDataRuntimeCall(loc, fn, op.getDataClauseOperands(),
                               convertedOperands, callKind, rewriter,
                               accSupport, globalSymbolRegion, symbolTable,
                               config, {asyncQueue});
  }

  OpenACCSupport &accSupport;
  Region &globalSymbolRegion;
  SymbolTable &symbolTable;
  ACCRuntimeCallConfig config;
  DeviceType clauseDeviceType;
};

struct DataOpLowering : public ACCDataDirectivePattern<DataOp> {
  using ACCDataDirectivePattern<DataOp>::ACCDataDirectivePattern;

  LogicalResult
  matchAndRewrite(DataOp op, DataOp::Adaptor adaptor,
                  ConversionPatternRewriter &rewriter) const override {
    // The mappings are established where the clause operations are, and torn
    // down where the exit operations of the construct were.
    ValueRange mappingOperands = op.getDataClauseOperands();
    Location beginLoc = mappingOperands.empty()
                            ? op.getLoc()
                            : mappingOperands.front().getLoc();
    Location endLoc =
        acc::getMappingExitLoc(mappingOperands).value_or(beginLoc);
    Value asyncQueue = getAsyncQueue(op, rewriter);
    if (failed(emitWaitClause(op, asyncQueue, rewriter)))
      return failure();

    auto emitBegin = [&]() {
      return emitMappingCall(op, adaptor.getDataClauseOperands(), beginLoc,
                             RuntimeFunction::ACCRTL_tgt_acc_data_begin,
                             ACCDataCallKind::DataEnter, asyncQueue, rewriter);
    };
    if (failed(acc::emitGuardedByIfCond(beginLoc, adaptor.getIfCond(), rewriter,
                                        emitBegin)))
      return failure();

    rewriter.setInsertionPointAfter(op);
    auto emitEnd = [&]() {
      return emitMappingCall(op, adaptor.getDataClauseOperands(), endLoc,
                             RuntimeFunction::ACCRTL_tgt_acc_data_end,
                             ACCDataCallKind::DataExit, asyncQueue, rewriter);
    };
    if (failed(acc::emitGuardedByIfCond(endLoc, adaptor.getIfCond(), rewriter,
                                        emitEnd)))
      return failure();

    acc::spliceConstructRegion(op, op.getRegion(), rewriter);
    rewriter.eraseOp(op);
    return success();
  }
};

/// Lowering shared by the directives that map their operands with a single
/// call: enter data, exit data and update.
template <typename OpTy, RuntimeFunction fn, ACCDataCallKind callKind>
struct ACCDataCallLowering : public ACCDataDirectivePattern<OpTy> {
  using ACCDataDirectivePattern<OpTy>::ACCDataDirectivePattern;

  LogicalResult
  matchAndRewrite(OpTy op, typename OpTy::Adaptor adaptor,
                  ConversionPatternRewriter &rewriter) const override {
    Location loc = op.getLoc();
    Value asyncQueue = this->getAsyncQueue(op, rewriter);
    if (failed(this->emitWaitClause(op, asyncQueue, rewriter)))
      return failure();

    auto emit = [&]() {
      return this->emitMappingCall(op, adaptor.getDataClauseOperands(), loc, fn,
                                   callKind, asyncQueue, rewriter);
    };
    if (failed(
            acc::emitGuardedByIfCond(loc, adaptor.getIfCond(), rewriter, emit)))
      return failure();
    rewriter.eraseOp(op);
    return success();
  }
};

using EnterDataOpLowering =
    ACCDataCallLowering<EnterDataOp, RuntimeFunction::ACCRTL_tgt_acc_data_enter,
                        ACCDataCallKind::DataEnter>;
using ExitDataOpLowering =
    ACCDataCallLowering<ExitDataOp, RuntimeFunction::ACCRTL_tgt_acc_data_exit,
                        ACCDataCallKind::DataExit>;
using UpdateOpLowering =
    ACCDataCallLowering<UpdateOp, RuntimeFunction::ACCRTL_tgt_acc_data_update,
                        ACCDataCallKind::DataEnter>;

/// Structured `acc.declare_enter` (token used by a matching exit) maps like
/// `acc.data` enter, with the region flags telling the runtime that a declare
/// directive opened the region. In a declare-action recipe the object the
/// directive names is allocated by the host, so only the device mirror of it is
/// allocated here. An unstructured enter registers the objects it names with
/// `__tgt_acc_declare`.
struct DeclareEnterOpLowering : public ConvertOpToLLVMPattern<DeclareEnterOp> {
  DeclareEnterOpLowering(const LLVMTypeConverter &converter,
                         OpenACCSupport &accSupport, Region &globalSymbolRegion,
                         SymbolTable &symbolTable,
                         const ACCRuntimeCallConfig &config,
                         PatternBenefit benefit = 1)
      : ConvertOpToLLVMPattern<DeclareEnterOp>(converter, benefit),
        accSupport(accSupport), globalSymbolRegion(globalSymbolRegion),
        symbolTable(symbolTable), config(config) {}

  LogicalResult
  matchAndRewrite(DeclareEnterOp op, DeclareEnterOp::Adaptor adaptor,
                  ConversionPatternRewriter &rewriter) const override {
    Location loc = op.getLoc();
    ValueRange mappingOperands = op.getDataClauseOperands();
    ValueRange convertedOperands = adaptor.getDataClauseOperands();
    Value asyncQueue = getDeclareAsyncQueue(loc, rewriter, config);

    LogicalResult emitted = success();
    if (getEnclosingDeclareAction(op)) {
      emitted = emitDataRuntimeCall(
          loc, RuntimeFunction::ACCRTL_tgt_acc_mirror_alloc, mappingOperands,
          convertedOperands, ACCDataCallKind::DataEnter, rewriter, accSupport,
          globalSymbolRegion, symbolTable, config, {});
    } else if (!op.getToken().use_empty()) {
      emitted = emitDataRuntimeCall(
          loc, RuntimeFunction::ACCRTL_tgt_acc_data_begin, mappingOperands,
          convertedOperands, ACCDataCallKind::DataEnter, rewriter, accSupport,
          globalSymbolRegion, symbolTable, config, {asyncQueue},
          ACCDataRegionFlags::Declare);
    } else {
      Value binaryDescriptor =
          config.createDeclareBinaryDescriptor(loc, rewriter);
      emitted = emitDataRuntimeCall(
          loc, RuntimeFunction::ACCRTL_tgt_acc_declare, mappingOperands,
          convertedOperands, ACCDataCallKind::DataEnter, rewriter, accSupport,
          globalSymbolRegion, symbolTable, config,
          {asyncQueue, binaryDescriptor});
    }
    if (failed(emitted))
      return failure();

    if (op.getToken().use_empty()) {
      rewriter.eraseOp(op);
    } else {
      // The token only ties a structured enter to its exit. Keep a converted
      // placeholder until the exit is erased; it carries no runtime state.
      Type tokenTy = getTypeConverter()->convertType(op.getToken().getType());
      rewriter.replaceOp(op, LLVM::ZeroOp::create(rewriter, loc, tokenTy));
    }
    return success();
  }

  OpenACCSupport &accSupport;
  Region &globalSymbolRegion;
  SymbolTable &symbolTable;
  ACCRuntimeCallConfig config;
};

/// A recipe that runs before the host object is deallocated frees the device
/// mirror of it, as the mapping is torn down once the host storage is gone.
/// Every other `acc.declare_exit` ends the mapping with `__tgt_acc_data_end`;
/// a structured exit (one holding the token of its enter) carries the declare
/// region flag, as its enter did.
struct DeclareExitOpLowering : public ConvertOpToLLVMPattern<DeclareExitOp> {
  DeclareExitOpLowering(const LLVMTypeConverter &converter,
                        OpenACCSupport &accSupport, Region &globalSymbolRegion,
                        SymbolTable &symbolTable,
                        const ACCRuntimeCallConfig &config,
                        PatternBenefit benefit = 1)
      : ConvertOpToLLVMPattern<DeclareExitOp>(converter, benefit),
        accSupport(accSupport), globalSymbolRegion(globalSymbolRegion),
        symbolTable(symbolTable), config(config) {}

  LogicalResult
  matchAndRewrite(DeclareExitOp op, DeclareExitOp::Adaptor adaptor,
                  ConversionPatternRewriter &rewriter) const override {
    Location loc = op.getLoc();
    ValueRange mappingOperands = op.getDataClauseOperands();
    ValueRange convertedOperands = adaptor.getDataClauseOperands();
    Value asyncQueue = getDeclareAsyncQueue(loc, rewriter, config);

    LogicalResult emitted = success();
    DeclareActionAttr action = getEnclosingDeclareAction(op);
    if (action && action.getPreDealloc()) {
      emitted = emitDataRuntimeCall(
          loc, RuntimeFunction::ACCRTL_tgt_acc_mirror_dealloc, mappingOperands,
          convertedOperands, ACCDataCallKind::DataEnter, rewriter, accSupport,
          globalSymbolRegion, symbolTable, config, {});
    } else {
      ACCDataRegionFlags regionFlags = op.getToken()
                                           ? ACCDataRegionFlags::Declare
                                           : ACCDataRegionFlags::None;
      emitted = emitDataRuntimeCall(
          loc, RuntimeFunction::ACCRTL_tgt_acc_data_end, mappingOperands,
          convertedOperands, ACCDataCallKind::DataExit, rewriter, accSupport,
          globalSymbolRegion, symbolTable, config, {asyncQueue}, regionFlags);
    }
    if (failed(emitted))
      return failure();
    rewriter.eraseOp(op);
    return success();
  }

  OpenACCSupport &accSupport;
  Region &globalSymbolRegion;
  SymbolTable &symbolTable;
  ACCRuntimeCallConfig config;
};

/// A data clause operation only describes a mapping; the runtime calls of the
/// construct carry everything it said, so the operation itself goes away once
/// they are in place. Whatever else referred to the mapped object is given the
/// address of that object, which is what the clause result stood for.
template <typename OpTy>
struct DataEntryOpLowering : public ConvertOpToLLVMPattern<OpTy> {
  using ConvertOpToLLVMPattern<OpTy>::ConvertOpToLLVMPattern;
  using OpAdaptor = typename OpTy::Adaptor;

  LogicalResult
  matchAndRewrite(OpTy op, OpAdaptor adaptor,
                  ConversionPatternRewriter &rewriter) const override {
    rewriter.replaceOp(op, adaptor.getVar());
    return success();
  }
};

/// An `acc.getdeviceptr` clause stands for the device address of an object
/// whose mapping was established elsewhere. Where it names the object of a
/// data exit operation, the runtime call of that construct carries the host
/// address and looks the device one up itself, so the clause is replaced by
/// the address of the object as any other data entry clause is. Read as a
/// value, it is the runtime that has to be asked for the address.
struct GetDevicePtrOpLowering
    : public ConvertOpToLLVMPattern<acc::GetDevicePtrOp> {
  GetDevicePtrOpLowering(const LLVMTypeConverter &converter,
                         OpenACCSupport &accSupport, Region &globalSymbolRegion,
                         SymbolTable &symbolTable,
                         const ACCRuntimeCallConfig &config,
                         PatternBenefit benefit = 1)
      : ConvertOpToLLVMPattern<acc::GetDevicePtrOp>(converter, benefit),
        accSupport(accSupport), globalSymbolRegion(globalSymbolRegion),
        symbolTable(symbolTable), config(config) {}

  /// Returns whether \p user only states the mapping the clause describes,
  /// which is what a data exit operation and the construct holding the clause
  /// do.
  static bool isMappingUse(Operation *user) {
    return isa<ACC_DATA_EXIT_OPS, ACC_COMPUTE_AND_DATA_CONSTRUCT_OPS,
               acc::KernelEnvironmentOp>(user);
  }

  LogicalResult
  matchAndRewrite(acc::GetDevicePtrOp op, OpAdaptor adaptor,
                  ConversionPatternRewriter &rewriter) const override {
    bool readAsValue = llvm::any_of(
        op->getUsers(), [](Operation *user) { return !isMappingUse(user); });
    if (!readAsValue) {
      rewriter.replaceOp(op, adaptor.getVar());
      return success();
    }
    // The mapping hands the host address of the object to the runtime call of
    // the construct, so the clause cannot stand for the device address at the
    // same time.
    if (llvm::any_of(op->getUsers(), isMappingUse)) {
      (void)accSupport.emitNYI(
          op.getLoc(), "device address read from a clause that also states a "
                       "mapping of the object");
      return failure();
    }

    FailureOr<Value> devicePtr = acc::emitGetDevicePtrCall(
        op, adaptor.getVar(), /*ifPresent=*/false, rewriter, globalSymbolRegion,
        symbolTable, config);
    if (failed(devicePtr))
      return failure();
    rewriter.replaceOp(op, *devicePtr);
    return success();
  }

  OpenACCSupport &accSupport;
  Region &globalSymbolRegion;
  SymbolTable &symbolTable;
  ACCRuntimeCallConfig config;
};

/// A data exit operation and the bounds of a mapping have no result to stand
/// in for, so they are simply removed with the construct that used them.
template <typename OpTy>
struct EraseDataClauseOp : public ConvertOpToLLVMPattern<OpTy> {
  using ConvertOpToLLVMPattern<OpTy>::ConvertOpToLLVMPattern;
  using OpAdaptor = typename OpTy::Adaptor;

  LogicalResult
  matchAndRewrite(OpTy op, OpAdaptor,
                  ConversionPatternRewriter &rewriter) const override {
    rewriter.eraseOp(op);
    return success();
  }
};

} // namespace

void mlir::configureACCDataDirectiveConversionLegality(
    ConversionTarget &target) {
  // The map entries themselves stay legal: a construct removes the ones it
  // consumes, and the ones describing a construct that is lowered elsewhere
  // have to survive this conversion. An `acc.getdeviceptr` read as a value is
  // the exception, as the address it stands for is only known to the runtime,
  // so leaving it behind would state a mapping that nothing carries out.
  target.addIllegalOp<acc::DataOp, acc::EnterDataOp, acc::ExitDataOp,
                      acc::UpdateOp, acc::DeclareEnterOp, acc::DeclareExitOp,
                      acc::GetDevicePtrOp>();
}

void mlir::populateACCDataClauseOpPatterns(
    LLVMTypeConverter &converter, RewritePatternSet &patterns,
    acc::OpenACCSupport &accSupport, Region &globalSymbolRegion,
    SymbolTable &symbolTable, const acc::ACCRuntimeCallConfig &config) {
  // Bounds describe a mapping rather than data, and they are removed together
  // with the clause operations holding them, so their type only has to survive
  // this conversion.
  converter.addConversion(
      [](acc::DataBoundsType type) -> Type { return type; });

  patterns.add<
      DataEntryOpLowering<acc::MapInfoOp>, DataEntryOpLowering<acc::CopyinOp>,
      DataEntryOpLowering<acc::CreateOp>, DataEntryOpLowering<acc::PresentOp>,
      DataEntryOpLowering<acc::NoCreateOp>, DataEntryOpLowering<acc::AttachOp>,
      DataEntryOpLowering<acc::DevicePtrOp>,
      DataEntryOpLowering<acc::UpdateDeviceOp>,
      DataEntryOpLowering<acc::PrivateOp>,
      DataEntryOpLowering<acc::FirstprivateOp>,
      DataEntryOpLowering<acc::FirstprivateMapInitialOp>,
      DataEntryOpLowering<acc::DeclareDeviceResidentOp>,
      DataEntryOpLowering<acc::DeclareLinkOp>,
      EraseDataClauseOp<acc::CopyoutOp>, EraseDataClauseOp<acc::DeleteOp>,
      EraseDataClauseOp<acc::DetachOp>, EraseDataClauseOp<acc::UpdateHostOp>,
      EraseDataClauseOp<acc::DataBoundsOp>>(converter);
  patterns.add<GetDevicePtrOpLowering>(converter, accSupport,
                                       globalSymbolRegion, symbolTable, config);
}

void mlir::populateACCDataDirectivePatterns(
    LLVMTypeConverter &converter, RewritePatternSet &patterns,
    acc::OpenACCSupport &accSupport, Region &globalSymbolRegion,
    SymbolTable &symbolTable, const acc::ACCRuntimeCallConfig &config,
    acc::DeviceType clauseDeviceType) {
  converter.addConversion([](acc::DeclareTokenType type) -> Type {
    return LLVM::LLVMPointerType::get(type.getContext());
  });

  patterns.add<DataOpLowering, EnterDataOpLowering, ExitDataOpLowering,
               UpdateOpLowering>(converter, accSupport, globalSymbolRegion,
                                 symbolTable, config, clauseDeviceType);
  patterns.add<DeclareEnterOpLowering, DeclareExitOpLowering>(
      converter, accSupport, globalSymbolRegion, symbolTable, config);
}
