Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions flang/include/flang/Optimizer/Dialect/FIRType.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,9 @@ bool isBoxedRecordType(mlir::Type ty);
/// Return true iff `ty` is a type that contains descriptor information.
bool isTypeWithDescriptor(mlir::Type ty);

/// Return true if CLASS(*)
bool isClassStarType(mlir::Type ty);

/// Return true iff `ty` is a scalar boxed record type.
/// e.g. !fir.box<!fir.type<derived>>
/// !fir.box<!fir.heap<!fir.type<derived>>>
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2169,7 +2169,8 @@ IntrinsicLibrary::genElementalCall<IntrinsicLibrary::ExtendedGenerator>(
for (const fir::ExtendedValue &arg : args) {
auto *box = arg.getBoxOf<fir::BoxValue>();
if (!arg.getUnboxed() && !arg.getCharBox() &&
!(box && fir::isScalarBoxedRecordType(fir::getBase(*box).getType())))
!(box && (fir::isScalarBoxedRecordType(fir::getBase(*box).getType()) ||
fir::isClassStarType(fir::getBase(*box).getType()))))
fir::emitFatalError(loc, "nonscalar intrinsic argument");
}
if (outline)
Expand Down
19 changes: 13 additions & 6 deletions flang/lib/Optimizer/Dialect/FIRType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,17 @@ bool isBoxedRecordType(mlir::Type ty) {
return false;
}

// CLASS(*)
bool isClassStarType(mlir::Type ty) {
if (auto clTy = mlir::dyn_cast<fir::ClassType>(fir::unwrapRefType(ty))) {
if (mlir::isa<mlir::NoneType>(clTy.getEleTy()))
return true;
mlir::Type innerType = clTy.unwrapInnerType();
return innerType && mlir::isa<mlir::NoneType>(innerType);
}
return false;
}

bool isScalarBoxedRecordType(mlir::Type ty) {
if (auto refTy = fir::dyn_cast_ptrEleTy(ty))
ty = refTy;
Expand Down Expand Up @@ -398,12 +409,8 @@ bool isPolymorphicType(mlir::Type ty) {

bool isUnlimitedPolymorphicType(mlir::Type ty) {
// CLASS(*)
if (auto clTy = mlir::dyn_cast<fir::ClassType>(fir::unwrapRefType(ty))) {
if (mlir::isa<mlir::NoneType>(clTy.getEleTy()))
return true;
mlir::Type innerType = clTy.unwrapInnerType();
return innerType && mlir::isa<mlir::NoneType>(innerType);
}
if (isClassStarType(ty))
return true;
// TYPE(*)
return isAssumedType(ty);
}
Expand Down
71 changes: 71 additions & 0 deletions flang/test/Lower/polymorphic-temp.f90
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,75 @@ subroutine test_merge_intrinsic2(a, b, i)
! CHECK: %[[A_REBOX:.*]] = fir.rebox %[[LOAD_A]] : (!fir.class<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>) -> !fir.box<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>
! CHECK: %{{.*}} = arith.select %[[CMPI]], %[[A_REBOX]], %[[LOAD_B]] : !fir.box<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>

subroutine check_unlimited_poly(a)
class(*), intent(in) :: a
end subroutine

subroutine test_merge_intrinsic3(a, b, i)
class(*), intent(in) :: a, b
integer, intent(in) :: i

call check_unlimited_poly(merge(a, b, i==1))
end subroutine

! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic3(
! CHECK-SAME: %[[A:.*]]: !fir.class<none> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.class<none> {fir.bindc_name = "b"}, %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i"}) {
! CHECK: %[[V_0:[0-9]+]] = fir.load %[[I]] : !fir.ref<i32>
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
! CHECK: %[[V_1:[0-9]+]] = arith.cmpi eq, %[[V_0]], %[[C1]] : i32
! CHECK: %[[V_2:[0-9]+]] = arith.select %[[V_1]], %[[A]], %[[B]] : !fir.class<none>
! CHECK: fir.call @_QMpoly_tmpPcheck_unlimited_poly(%[[V_2]]) fastmath<contract> : (!fir.class<none>) -> ()

subroutine test_merge_intrinsic4(i)
integer, intent(in) :: i
class(*), allocatable :: a, b

call check_unlimited_poly(merge(a, b, i==1))
end subroutine

! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic4(
! CHECK-SAME: %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i"}) {
! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.class<!fir.heap<none>> {bindc_name = "a", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic4Ea"}
! CHECK: %[[V_1:[0-9]+]] = fir.zero_bits !fir.heap<none>
! CHECK: %[[V_2:[0-9]+]] = fir.embox %[[V_1]] : (!fir.heap<none>) -> !fir.class<!fir.heap<none>>
! CHECK: fir.store %[[V_2]] to %[[V_0]] : !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[V_3:[0-9]+]] = fir.alloca !fir.class<!fir.heap<none>> {bindc_name = "b", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic4Eb"}
! CHECK: %[[V_4:[0-9]+]] = fir.zero_bits !fir.heap<none>
! CHECK: %[[V_5:[0-9]+]] = fir.embox %[[V_4]] : (!fir.heap<none>) -> !fir.class<!fir.heap<none>>
! CHECK: fir.store %[[V_5]] to %[[V_3]] : !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[V_6:[0-9]+]] = fir.load %[[V_0]] : !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[V_7:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[V_8:[0-9]+]] = fir.load %[[I]] : !fir.ref<i32>
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
! CHECK: %[[V_9:[0-9]+]] = arith.cmpi eq, %[[V_8]], %[[C1]] : i32
! CHECK: %[[V_10:[0-9]+]] = arith.select %[[V_9]], %[[V_6]], %[[V_7]] : !fir.class<!fir.heap<none>>
! CHECK: %[[V_11:[0-9]+]] = fir.rebox %[[V_10]] : (!fir.class<!fir.heap<none>>) -> !fir.class<none>
! CHECK: fir.call @_QMpoly_tmpPcheck_unlimited_poly(%[[V_11]]) fastmath<contract> : (!fir.class<none>) -> ()

subroutine test_merge_intrinsic5(i)
integer, intent(in) :: i
class(*), pointer :: a, b

call check_unlimited_poly(merge(a, b, i==1))
end subroutine

! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic5(
! CHECK-SAME: %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i"}) {
! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.class<!fir.ptr<none>> {bindc_name = "a", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic5Ea"}
! CHECK: %[[V_1:[0-9]+]] = fir.zero_bits !fir.ptr<none>
! CHECK: %[[V_2:[0-9]+]] = fir.embox %[[V_1]] : (!fir.ptr<none>) -> !fir.class<!fir.ptr<none>>
! CHECK: fir.store %[[V_2]] to %[[V_0]] : !fir.ref<!fir.class<!fir.ptr<none>>>
! CHECK: %[[V_3:[0-9]+]] = fir.alloca !fir.class<!fir.ptr<none>> {bindc_name = "b", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic5Eb"}
! CHECK: %[[V_4:[0-9]+]] = fir.zero_bits !fir.ptr<none>
! CHECK: %[[V_5:[0-9]+]] = fir.embox %[[V_4]] : (!fir.ptr<none>) -> !fir.class<!fir.ptr<none>>
! CHECK: fir.store %[[V_5]] to %[[V_3]] : !fir.ref<!fir.class<!fir.ptr<none>>>
! CHECK: %[[V_6:[0-9]+]] = fir.load %[[V_0]] : !fir.ref<!fir.class<!fir.ptr<none>>>
! CHECK: %[[V_7:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<!fir.class<!fir.ptr<none>>>
! CHECK: %[[V_8:[0-9]+]] = fir.load %[[I]] : !fir.ref<i32>
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
! CHECK: %[[V_9:[0-9]+]] = arith.cmpi eq, %[[V_8]], %[[C1]] : i32
! CHECK: %[[V_10:[0-9]+]] = arith.select %[[V_9]], %[[V_6]], %[[V_7]] : !fir.class<!fir.ptr<none>>
! CHECK: %[[V_11:[0-9]+]] = fir.rebox %[[V_10]] : (!fir.class<!fir.ptr<none>>) -> !fir.class<none>
! CHECK: fir.call @_QMpoly_tmpPcheck_unlimited_poly(%[[V_11]]) fastmath<contract> : (!fir.class<none>) -> ()

end module