Files
clang-p2996/flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp
Razvan Lupusoru f16983f7d0 [flang][acc] Ensure fir.class is handled in type categorization (#146174)
fir.class is treated similarly as fir.box - but it has one key
distinction which is that it doesn't hold an element type. Thus the
categorization logic was mishandling this case for this reason (and also
the fact that it assumed that a base object is always a fir.ref).

This PR improves this handling and adds appropriate test exercising both
a class and a class field to ensure categorization works.
2025-06-30 15:04:14 -07:00

119 lines
4.5 KiB
C++

//===- TestOpenACCInterfaces.cpp ------------------------------------------===//
//
// 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 "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/DLTI/DLTI.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Support/LLVM.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
#include "flang/Optimizer/Support/DataLayout.h"
using namespace mlir;
namespace {
struct TestFIROpenACCInterfaces
: public PassWrapper<TestFIROpenACCInterfaces, OperationPass<ModuleOp>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestFIROpenACCInterfaces)
StringRef getArgument() const final { return "test-fir-openacc-interfaces"; }
StringRef getDescription() const final {
return "Test FIR implementation of the OpenACC interfaces.";
}
void getDependentDialects(::mlir::DialectRegistry &registry) const override {
registry.insert<fir::FIROpsDialect, hlfir::hlfirDialect,
mlir::arith::ArithDialect, mlir::acc::OpenACCDialect,
mlir::DLTIDialect>();
}
void runOnOperation() override {
mlir::ModuleOp mod = getOperation();
auto datalayout =
fir::support::getOrSetMLIRDataLayout(mod, /*allowDefaultLayout=*/true);
mlir::OpBuilder builder(mod);
getOperation().walk([&](Operation *op) {
if (isa<ACC_DATA_ENTRY_OPS>(op)) {
Value var = acc::getVar(op);
Type typeOfVar = var.getType();
// Attempt to determine if the variable is mappable-like or if
// the pointee itself is mappable-like. For example, if the variable is
// of type !fir.ref<!fir.box<>>, we want to print both the details about
// the !fir.ref since it is pointer-like, and about !fir.box since it
// is mappable.
auto mappableTy = dyn_cast_if_present<acc::MappableType>(typeOfVar);
if (!mappableTy) {
mappableTy =
dyn_cast_if_present<acc::MappableType>(acc::getVarType(op));
}
llvm::errs() << "Visiting: " << *op << "\n";
llvm::errs() << "\tVar: " << var << "\n";
if (auto ptrTy = dyn_cast_if_present<acc::PointerLikeType>(typeOfVar)) {
llvm::errs() << "\tPointer-like: " << typeOfVar << "\n";
// If the pointee is not mappable, print details about it. Otherwise,
// we defer to the mappable printing below to print those details.
if (!mappableTy) {
acc::VariableTypeCategory typeCategory =
ptrTy.getPointeeTypeCategory(
cast<TypedValue<acc::PointerLikeType>>(var),
acc::getVarType(op));
llvm::errs() << "\t\tType category: " << typeCategory << "\n";
}
}
if (mappableTy) {
llvm::errs() << "\tMappable: " << mappableTy << "\n";
acc::VariableTypeCategory typeCategory =
mappableTy.getTypeCategory(var);
llvm::errs() << "\t\tType category: " << typeCategory << "\n";
if (datalayout.has_value()) {
auto size = mappableTy.getSizeInBytes(
acc::getVar(op), acc::getBounds(op), datalayout.value());
if (size) {
llvm::errs() << "\t\tSize: " << size.value() << "\n";
}
auto offset = mappableTy.getOffsetInBytes(
acc::getVar(op), acc::getBounds(op), datalayout.value());
if (offset) {
llvm::errs() << "\t\tOffset: " << offset.value() << "\n";
}
}
builder.setInsertionPoint(op);
auto bounds = mappableTy.generateAccBounds(acc::getVar(op), builder);
if (!bounds.empty()) {
for (auto [idx, bound] : llvm::enumerate(bounds)) {
llvm::errs() << "\t\tBound[" << idx << "]: " << bound << "\n";
}
}
}
}
});
}
};
} // namespace
//===----------------------------------------------------------------------===//
// Pass Registration
//===----------------------------------------------------------------------===//
namespace fir {
namespace test {
void registerTestFIROpenACCInterfacesPass() {
PassRegistration<TestFIROpenACCInterfaces>();
}
} // namespace test
} // namespace fir