llvm-project/mlir/test/lib/Dialect/OpenACC/TestRecipePopulate.cpp
jeanPerier 9a8c018081
[mlir][acc] add VariableInfo attribute to thread language specific information about privatized variables (#186368)
Add a new acc::VariableInfoAttr attribute that can be extended and implemented by
language dialects to carry language specific information about variables that is
not reflected into the MLIR type system and is needed in the implementation
of the init/copy/destroy APIs.
A new genPrivateVariableInfo API is added to the MappableTypeInterface to generate
such attribute from an mlir::Value for the host variable.
The use case and motivation is the Fortran OPTIONAL attribute. This patch adds
a new fir::OpenACCFortranVariableInfoAtt that implements the acc::VariableInfoAttr
to carry the OPTIONAL information around.
2026-03-30 16:03:14 +02:00

134 lines
4.3 KiB
C++

//===- TestRecipePopulate.cpp - Test Recipe Population -------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains test passes for testing the createAndPopulate methods
// of the recipe operations.
//
//===----------------------------------------------------------------------===//
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/IR/Builders.h"
#include "mlir/Pass/Pass.h"
#include "llvm/Support/CommandLine.h"
using namespace mlir;
using namespace mlir::acc;
namespace {
struct TestRecipePopulatePass
: public PassWrapper<TestRecipePopulatePass, OperationPass<ModuleOp>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestRecipePopulatePass)
TestRecipePopulatePass() = default;
TestRecipePopulatePass(const TestRecipePopulatePass &pass)
: PassWrapper(pass) {
recipeType = pass.recipeType;
}
Pass::Option<std::string> recipeType{
*this, "recipe-type",
llvm::cl::desc("Recipe type: private or firstprivate"),
llvm::cl::init("private")};
StringRef getArgument() const override { return "test-acc-recipe-populate"; }
StringRef getDescription() const override {
return "Test OpenACC recipe population";
}
void runOnOperation() override;
void getDependentDialects(DialectRegistry &registry) const override {
registry.insert<acc::OpenACCDialect>();
registry.insert<arith::ArithDialect>();
registry.insert<memref::MemRefDialect>();
}
};
void TestRecipePopulatePass::runOnOperation() {
auto module = getOperation();
OpBuilder builder(&getContext());
// Collect all test variables
SmallVector<std::tuple<Operation *, Value, std::string>> testVars;
module.walk([&](Operation *op) {
if (auto varName = op->getAttrOfType<StringAttr>("test.var")) {
for (auto result : op->getResults()) {
testVars.push_back({op, result, varName.str()});
}
}
});
// Generate recipes at module level
builder.setInsertionPoint(&module.getBodyRegion().front(),
module.getBodyRegion().front().begin());
for (auto [op, var, varName] : testVars) {
Location loc = op->getLoc();
std::string recipeName = recipeType.getValue() + "_" + varName;
ValueRange bounds; // No bounds for memref tests
if (recipeType == "private") {
auto recipe = PrivateRecipeOp::createAndPopulate(builder, loc, recipeName,
var, varName, bounds);
if (!recipe) {
op->emitError("Failed to create private recipe for ") << varName;
}
} else if (recipeType == "firstprivate") {
auto recipe = FirstprivateRecipeOp::createAndPopulate(
builder, loc, recipeName, var, varName, bounds);
if (!recipe) {
op->emitError("Failed to create firstprivate recipe for ") << varName;
}
} else if (recipeType == "private_from_firstprivate") {
// First create a firstprivate recipe, then use it to drive creation of a
// matching private recipe via the convenience overload. Give each recipe
// a stable, predictable name so tests can check both.
std::string firstprivName = "first_firstprivate_" + varName;
std::string privName = "private_from_firstprivate_" + varName;
auto firstpriv = FirstprivateRecipeOp::createAndPopulate(
builder, loc, firstprivName, var, varName, bounds);
if (!firstpriv) {
op->emitError("Failed to create firstprivate recipe for ") << varName;
return;
}
auto priv = PrivateRecipeOp::createAndPopulate(builder, loc, privName,
*firstpriv);
if (!priv) {
op->emitError(
"Failed to create private recipe (from firstprivate) for ")
<< varName;
}
}
}
}
} // namespace
namespace mlir {
namespace test {
void registerTestRecipePopulatePass() {
PassRegistration<TestRecipePopulatePass>();
}
} // namespace test
} // namespace mlir