Skip to content

Commit f16983f

Browse files
[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.
1 parent 6896d8a commit f16983f

File tree

3 files changed

+86
-6
lines changed

3 files changed

+86
-6
lines changed

flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ static bool isArrayLike(mlir::Type type) {
306306
}
307307

308308
static bool isCompositeLike(mlir::Type type) {
309+
// class(*) is not a composite type since it does not have a determined type.
310+
if (fir::isUnlimitedPolymorphicType(type))
311+
return false;
312+
309313
return mlir::isa<fir::RecordType, fir::ClassType, mlir::TupleType>(type);
310314
}
311315

@@ -320,8 +324,18 @@ template <>
320324
mlir::acc::VariableTypeCategory
321325
OpenACCMappableModel<fir::BaseBoxType>::getTypeCategory(mlir::Type type,
322326
mlir::Value var) const {
327+
// Class-type does not behave like a normal box because it does not hold an
328+
// element type. Thus special handle it here.
329+
if (mlir::isa<fir::ClassType>(type)) {
330+
// class(*) is not a composite type since it does not have a determined
331+
// type.
332+
if (fir::isUnlimitedPolymorphicType(type))
333+
return mlir::acc::VariableTypeCategory::uncategorized;
334+
return mlir::acc::VariableTypeCategory::composite;
335+
}
323336

324337
mlir::Type eleTy = fir::dyn_cast_ptrOrBoxEleTy(type);
338+
assert(eleTy && "expect to be able to unwrap the element type");
325339

326340
// If the type enclosed by the box is a mappable type, then have it
327341
// provide the type category.
@@ -346,7 +360,7 @@ OpenACCMappableModel<fir::BaseBoxType>::getTypeCategory(mlir::Type type,
346360
return mlir::acc::VariableTypeCategory::nonscalar;
347361
}
348362

349-
static mlir::TypedValue<mlir::acc::PointerLikeType>
363+
static mlir::Value
350364
getBaseRef(mlir::TypedValue<mlir::acc::PointerLikeType> varPtr) {
351365
// If there is no defining op - the unwrapped reference is the base one.
352366
mlir::Operation *op = varPtr.getDefiningOp();
@@ -372,7 +386,7 @@ getBaseRef(mlir::TypedValue<mlir::acc::PointerLikeType> varPtr) {
372386
})
373387
.Default([&](mlir::Operation *) { return varPtr; });
374388

375-
return mlir::cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(baseRef);
389+
return baseRef;
376390
}
377391

378392
static mlir::acc::VariableTypeCategory
@@ -384,10 +398,17 @@ categorizePointee(mlir::Type pointer,
384398
// value would both be represented as !fir.ref<f32>. We do not want to treat
385399
// such a reference as a scalar. Thus unwrap interior pointer calculations.
386400
auto baseRef = getBaseRef(varPtr);
387-
mlir::Type eleTy = baseRef.getType().getElementType();
388401

389-
if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(eleTy))
390-
return mappableTy.getTypeCategory(varPtr);
402+
if (auto mappableTy =
403+
mlir::dyn_cast<mlir::acc::MappableType>(baseRef.getType()))
404+
return mappableTy.getTypeCategory(baseRef);
405+
406+
// It must be a pointer-like type since it is not a MappableType.
407+
auto ptrLikeTy = mlir::cast<mlir::acc::PointerLikeType>(baseRef.getType());
408+
mlir::Type eleTy = ptrLikeTy.getElementType();
409+
410+
if (auto mappableEleTy = mlir::dyn_cast<mlir::acc::MappableType>(eleTy))
411+
return mappableEleTy.getTypeCategory(varPtr);
391412

392413
if (isScalarLike(eleTy))
393414
return mlir::acc::VariableTypeCategory::scalar;
@@ -397,8 +418,12 @@ categorizePointee(mlir::Type pointer,
397418
return mlir::acc::VariableTypeCategory::composite;
398419
if (mlir::isa<fir::CharacterType, mlir::FunctionType>(eleTy))
399420
return mlir::acc::VariableTypeCategory::nonscalar;
421+
// Assumed-type (type(*))does not have a determined type that can be
422+
// categorized.
423+
if (mlir::isa<mlir::NoneType>(eleTy))
424+
return mlir::acc::VariableTypeCategory::uncategorized;
400425
// "pointers" - in the sense of raw address point-of-view, are considered
401-
// scalars. However
426+
// scalars.
402427
if (mlir::isa<fir::LLVMPointerType>(eleTy))
403428
return mlir::acc::VariableTypeCategory::scalar;
404429

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
! RUN: bbc -fopenacc -emit-hlfir %s -o - | fir-opt -pass-pipeline='builtin.module(test-fir-openacc-interfaces)' --mlir-disable-threading 2>&1 | FileCheck %s
2+
3+
module mm
4+
type, public :: polyty
5+
real :: field
6+
end type
7+
contains
8+
subroutine init(this)
9+
class(polyty), intent(inout) :: this
10+
!$acc enter data copyin(this, this%field)
11+
end subroutine
12+
subroutine init_assumed_type(var)
13+
type(*), intent(inout) :: var
14+
!$acc enter data copyin(var)
15+
end subroutine
16+
subroutine init_unlimited(this)
17+
class(*), intent(inout) :: this
18+
!$acc enter data copyin(this)
19+
select type(this)
20+
type is(real)
21+
!$acc enter data copyin(this)
22+
class is(polyty)
23+
!$acc enter data copyin(this, this%field)
24+
end select
25+
end subroutine
26+
end module
27+
28+
! CHECK: Visiting: {{.*}} acc.copyin {{.*}} {name = "this", structured = false}
29+
! CHECK: Mappable: !fir.class<!fir.type<_QMmmTpolyty{field:f32}>>
30+
! CHECK: Type category: composite
31+
! CHECK: Visiting: {{.*}} acc.copyin {{.*}} {name = "this%field", structured = false}
32+
! CHECK: Pointer-like: !fir.ref<f32>
33+
! CHECK: Type category: composite
34+
35+
! For unlimited polymorphic entities and assumed types - they effectively have
36+
! no declared type. Thus the type categorizer cannot categorize it.
37+
! CHECK: Visiting: {{.*}} = acc.copyin {{.*}} {name = "var", structured = false}
38+
! CHECK: Pointer-like: !fir.ref<none>
39+
! CHECK: Type category: uncategorized
40+
! CHECK: Visiting: {{.*}} = acc.copyin {{.*}} {name = "this", structured = false}
41+
! CHECK: Mappable: !fir.class<none>
42+
! CHECK: Type category: uncategorized
43+
44+
! TODO: After using select type - the appropriate type category should be
45+
! possible. Add the rest of the test once OpenACC lowering correctly handles
46+
! unlimited polymorhic.

flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "mlir/Dialect/Arith/IR/Arith.h"
10+
#include "mlir/Dialect/DLTI/DLTI.h"
911
#include "mlir/Dialect/OpenACC/OpenACC.h"
1012
#include "mlir/IR/Builders.h"
1113
#include "mlir/IR/BuiltinOps.h"
1214
#include "mlir/Pass/Pass.h"
1315
#include "mlir/Support/LLVM.h"
16+
#include "flang/Optimizer/Dialect/FIRDialect.h"
17+
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
1418
#include "flang/Optimizer/Support/DataLayout.h"
1519

1620
using namespace mlir;
@@ -25,6 +29,11 @@ struct TestFIROpenACCInterfaces
2529
StringRef getDescription() const final {
2630
return "Test FIR implementation of the OpenACC interfaces.";
2731
}
32+
void getDependentDialects(::mlir::DialectRegistry &registry) const override {
33+
registry.insert<fir::FIROpsDialect, hlfir::hlfirDialect,
34+
mlir::arith::ArithDialect, mlir::acc::OpenACCDialect,
35+
mlir::DLTIDialect>();
36+
}
2837
void runOnOperation() override {
2938
mlir::ModuleOp mod = getOperation();
3039
auto datalayout =

0 commit comments

Comments
 (0)