//===- OpenACCUtils.h - OpenACC Utilities -----------------------*- 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 // //===----------------------------------------------------------------------===// #ifndef MLIR_DIALECT_OPENACC_OPENACCUTILS_H_ #define MLIR_DIALECT_OPENACC_OPENACCUTILS_H_ #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/Remarks.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include #include namespace mlir { class DominanceInfo; class PostDominanceInfo; namespace acc { /// Used to obtain the enclosing compute construct operation that contains /// the provided `region`. Returns nullptr if no compute construct operation /// is found. The returned operation is one of types defined by /// `ACC_COMPUTE_CONSTRUCT_OPS`. mlir::Operation *getEnclosingComputeOp(mlir::Region ®ion); /// If `v` is not a block argument of an `acc.compute_region` body, returns /// nullptr. Otherwise maps the block argument to its operand and returns it. mlir::Value getACCOperandForBlockArg(mlir::Value v); /// If `v` is not a block argument of an `acc.compute_region` body, returns /// nullptr. Otherwise maps the block argument to its operand and returns the /// defining operation if it is one of `ACC_DATA_ENTRY_OPS`. mlir::Operation *getACCDataClauseOpForBlockArg(mlir::Value v); /// Returns true if this value is only used by `acc.private` operations in the /// `region`. bool isOnlyUsedByPrivateClauses(mlir::Value val, mlir::Region ®ion); /// Returns true if this value is only used by `acc.reduction` operations in /// the `region`. bool isOnlyUsedByReductionClauses(mlir::Value val, mlir::Region ®ion); /// Looks for an OpenACC default attribute on the current operation `op` or in /// a parent operation which encloses `op`. This is useful because OpenACC /// specification notes that a visible default clause is the nearest default /// clause appearing on the compute construct or a lexically containing data /// construct. std::optional getDefaultAttr(mlir::Operation *op); /// Get the type category of an OpenACC variable. mlir::acc::VariableTypeCategory getTypeCategory(mlir::Value var); /// Attempts to extract the variable name from a value by walking through /// view-like operations until an `acc.var_name` attribute is found. Returns /// empty string if no name is found. std::string getVariableName(mlir::Value v); /// Get the recipe name for a given recipe kind and type. /// Returns an empty string if not possible to generate a recipe name. std::string getRecipeName(mlir::acc::RecipeKind kind, mlir::Type type); // Get the base entity from partial entity access. This is used for getting // the base `struct` from an operation that only accesses a field or the // base `array` from an operation that only accesses a subarray. mlir::Value getBaseEntity(mlir::Value val); /// Check if a symbol use is valid for use in an OpenACC region. /// This includes looking for various attributes such as `acc.routine_info` /// and `acc.declare` attributes. /// \param user The operation using the symbol /// \param symbol The symbol reference being used /// \param definingOpPtr Optional output parameter to receive the defining op /// \return true if the symbol use is valid, false otherwise bool isValidSymbolUse(mlir::Operation *user, mlir::SymbolRefAttr symbol, mlir::Operation **definingOpPtr = nullptr); /// Check if a value represents device data. /// This checks if the value represents device data via the /// MappableType, PointerLikeType, and GlobalVariableOpInterface interfaces, /// and whether the defining operation carries `acc.declare` with the deviceptr /// clause. /// \param val The value to check /// \return true if the value is device data, false otherwise bool isDeviceValue(mlir::Value val); /// Check if a value use is valid in an OpenACC region. /// This is true if: /// - The value is produced by an ACC data entry operation /// - The value is device data /// - The value is only used by private clauses in the region /// \param val The value to check /// \param region The OpenACC region /// \return true if the value use is valid, false otherwise bool isValidValueUse(mlir::Value val, mlir::Region ®ion); /// Collects all data clauses that dominate the compute construct. /// This includes data clauses from: /// - The compute construct itself /// - Enclosing data constructs /// - Applicable declare directives (those that dominate and post-dominate) /// This is used to determine if a variable is already covered by an existing /// data clause. /// \param computeConstructOp The compute construct operation /// \param domInfo Dominance information /// \param postDomInfo Post-dominance information /// \return Vector of data clause values that dominate the compute construct llvm::SmallVector getDominatingDataClauses(mlir::Operation *computeConstructOp, mlir::DominanceInfo &domInfo, mlir::PostDominanceInfo &postDomInfo); /// Emit an OpenACC remark with lazy message generation. /// /// The messageFn is only invoked if remarks are enabled, allowing callers /// to avoid constructing expensive messages when remarks are disabled. /// /// \param op The operation to emit the remark for. /// \param messageFn A callable that returns the remark message. /// \param category Optional category for the remark. Defaults to "openacc". /// \return An in-flight remark object that can be used to append /// additional information to the remark. remark::detail::InFlightRemark emitRemark(mlir::Operation *op, const std::function &messageFn, llvm::StringRef category = "openacc"); /// Emit an OpenACC remark for the given operation with the given message. /// /// \param op The operation to emit the remark for. /// \param message The remark message. /// \param category Optional category for the remark. Defaults to "openacc". /// \return An in-flight remark object that can be used to append /// additional information to the remark. inline remark::detail::InFlightRemark emitRemark(mlir::Operation *op, const llvm::Twine &message, llvm::StringRef category = "openacc") { return emitRemark( op, std::function([msg = message.str()]() { return msg; }), category); } } // namespace acc } // namespace mlir #endif // MLIR_DIALECT_OPENACC_OPENACCUTILS_H_