//===- OpenACCDataOperandConversion.cpp - OpenACC data operand conversion -===// // // 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/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/Transforms/Passes.h" #include "mlir/Conversion/LLVMCommon/Pattern.h" #include "mlir/Conversion/OpenACCToLLVM/ConvertOpenACCToLLVM.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" namespace fir { #define GEN_PASS_DEF_OPENACCDATAOPERANDCONVERSION #include "flang/Optimizer/Transforms/Passes.h.inc" } // namespace fir #define DEBUG_TYPE "flang-openacc-conversion" #include "flang/Optimizer/CodeGen/TypeConverter.h" using namespace fir; using namespace mlir; //===----------------------------------------------------------------------===// // Conversion patterns //===----------------------------------------------------------------------===// namespace { template class LegalizeDataOpForLLVMTranslation : public ConvertOpToLLVMPattern { using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern; LogicalResult matchAndRewrite(Op op, typename Op::Adaptor adaptor, ConversionPatternRewriter &builder) const override { Location loc = op.getLoc(); fir::LLVMTypeConverter &converter = *static_cast(this->getTypeConverter()); unsigned numDataOperands = op.getNumDataOperands(); // Keep the non data operands without modification. auto nonDataOperands = adaptor.getOperands().take_front( adaptor.getOperands().size() - numDataOperands); SmallVector convertedOperands; convertedOperands.append(nonDataOperands.begin(), nonDataOperands.end()); // Go over the data operand and legalize them for translation. for (unsigned idx = 0; idx < numDataOperands; ++idx) { Value originalDataOperand = op.getDataOperand(idx); if (auto refTy = originalDataOperand.getType().dyn_cast()) { if (refTy.getEleTy().isa()) return builder.notifyMatchFailure(op, "BaseBoxType not supported"); mlir::Type convertedType = converter.convertType(refTy).cast(); mlir::Value castedOperand = builder .create(loc, convertedType, originalDataOperand) .getResult(0); convertedOperands.push_back(castedOperand); } else { // Type not supported. return builder.notifyMatchFailure(op, "expecting a reference type"); } } if constexpr (std::is_same_v || std::is_same_v) { auto newOp = builder.create(op.getLoc(), TypeRange(), convertedOperands, op.getOperation()->getAttrs()); builder.inlineRegionBefore(op.getRegion(), newOp.getRegion(), newOp.getRegion().end()); if (failed(builder.convertRegionTypes(&newOp.getOperation()->getRegion(0), *this->getTypeConverter()))) return failure(); builder.eraseOp(op); } else { builder.replaceOpWithNewOp(op, TypeRange(), convertedOperands, op.getOperation()->getAttrs()); } return success(); } }; } // namespace namespace { struct OpenACCDataOperandConversion : public fir::impl::OpenACCDataOperandConversionBase< OpenACCDataOperandConversion> { using Base::Base; void runOnOperation() override; }; } // namespace void OpenACCDataOperandConversion::runOnOperation() { auto op = getOperation(); auto *context = op.getContext(); // Convert to OpenACC operations with LLVM IR dialect RewritePatternSet patterns(context); LowerToLLVMOptions options(context); options.useOpaquePointers = useOpaquePointers; fir::LLVMTypeConverter converter( op.getOperation()->getParentOfType(), true); patterns.add>(converter); ConversionTarget target(*context); target.addLegalDialect(); target.addLegalDialect(); target.addLegalOp(); auto allDataOperandsAreConverted = [](ValueRange operands) { for (Value operand : operands) { if (!operand.getType().isa()) return false; } return true; }; target.addDynamicallyLegalOp( [allDataOperandsAreConverted](acc::ParallelOp op) { return allDataOperandsAreConverted(op.getReductionOperands()) && allDataOperandsAreConverted(op.getGangPrivateOperands()) && allDataOperandsAreConverted(op.getGangFirstPrivateOperands()); }); if (failed(applyPartialConversion(op, target, std::move(patterns)))) signalPassFailure(); }