Skip to content

Commit 212eb81

Browse files
authored
To support unlimited polymorphic argument for intrinsic MERGE. (#163866)
This PR will allow unlimited polymorphic arguments `class(*)` for intrinsics. Fixes #143582
1 parent 8fe71e0 commit 212eb81

File tree

4 files changed

+89
-7
lines changed

4 files changed

+89
-7
lines changed

flang/include/flang/Optimizer/Dialect/FIRType.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,9 @@ bool isPolymorphicType(mlir::Type ty);
389389
/// value.
390390
bool isUnlimitedPolymorphicType(mlir::Type ty);
391391

392+
/// Return true if CLASS(*)
393+
bool isClassStarType(mlir::Type ty);
394+
392395
/// Return true iff `ty` is the type of an assumed type. In FIR,
393396
/// assumed types are of the form `[fir.ref|ptr|heap]fir.box<[fir.array]none>`,
394397
/// or `fir.ref|ptr|heap<[fir.array]none>`.

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,8 @@ IntrinsicLibrary::genElementalCall<IntrinsicLibrary::ExtendedGenerator>(
21692169
for (const fir::ExtendedValue &arg : args) {
21702170
auto *box = arg.getBoxOf<fir::BoxValue>();
21712171
if (!arg.getUnboxed() && !arg.getCharBox() &&
2172-
!(box && fir::isScalarBoxedRecordType(fir::getBase(*box).getType())))
2172+
!(box && (fir::isScalarBoxedRecordType(fir::getBase(*box).getType()) ||
2173+
fir::isClassStarType(fir::getBase(*box).getType()))))
21732174
fir::emitFatalError(loc, "nonscalar intrinsic argument");
21742175
}
21752176
if (outline)

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,17 @@ bool isBoxedRecordType(mlir::Type ty) {
336336
return false;
337337
}
338338

339+
// CLASS(*)
340+
bool isClassStarType(mlir::Type ty) {
341+
if (auto clTy = mlir::dyn_cast<fir::ClassType>(fir::unwrapRefType(ty))) {
342+
if (mlir::isa<mlir::NoneType>(clTy.getEleTy()))
343+
return true;
344+
mlir::Type innerType = clTy.unwrapInnerType();
345+
return innerType && mlir::isa<mlir::NoneType>(innerType);
346+
}
347+
return false;
348+
}
349+
339350
bool isScalarBoxedRecordType(mlir::Type ty) {
340351
if (auto refTy = fir::dyn_cast_ptrEleTy(ty))
341352
ty = refTy;
@@ -398,12 +409,8 @@ bool isPolymorphicType(mlir::Type ty) {
398409

399410
bool isUnlimitedPolymorphicType(mlir::Type ty) {
400411
// CLASS(*)
401-
if (auto clTy = mlir::dyn_cast<fir::ClassType>(fir::unwrapRefType(ty))) {
402-
if (mlir::isa<mlir::NoneType>(clTy.getEleTy()))
403-
return true;
404-
mlir::Type innerType = clTy.unwrapInnerType();
405-
return innerType && mlir::isa<mlir::NoneType>(innerType);
406-
}
412+
if (isClassStarType(ty))
413+
return true;
407414
// TYPE(*)
408415
return isAssumedType(ty);
409416
}

flang/test/Lower/polymorphic-temp.f90

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,75 @@ subroutine test_merge_intrinsic2(a, b, i)
223223
! 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}>>>
224224
! CHECK: %{{.*}} = arith.select %[[CMPI]], %[[A_REBOX]], %[[LOAD_B]] : !fir.box<!fir.heap<!fir.type<_QMpoly_tmpTp1{a:i32}>>>
225225

226+
subroutine check_unlimited_poly(a)
227+
class(*), intent(in) :: a
228+
end subroutine
229+
230+
subroutine test_merge_intrinsic3(a, b, i)
231+
class(*), intent(in) :: a, b
232+
integer, intent(in) :: i
233+
234+
call check_unlimited_poly(merge(a, b, i==1))
235+
end subroutine
236+
237+
! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic3(
238+
! 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"}) {
239+
! CHECK: %[[V_0:[0-9]+]] = fir.load %[[I]] : !fir.ref<i32>
240+
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
241+
! CHECK: %[[V_1:[0-9]+]] = arith.cmpi eq, %[[V_0]], %[[C1]] : i32
242+
! CHECK: %[[V_2:[0-9]+]] = arith.select %[[V_1]], %[[A]], %[[B]] : !fir.class<none>
243+
! CHECK: fir.call @_QMpoly_tmpPcheck_unlimited_poly(%[[V_2]]) fastmath<contract> : (!fir.class<none>) -> ()
244+
245+
subroutine test_merge_intrinsic4(i)
246+
integer, intent(in) :: i
247+
class(*), allocatable :: a, b
248+
249+
call check_unlimited_poly(merge(a, b, i==1))
250+
end subroutine
251+
252+
! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic4(
253+
! CHECK-SAME: %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i"}) {
254+
! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.class<!fir.heap<none>> {bindc_name = "a", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic4Ea"}
255+
! CHECK: %[[V_1:[0-9]+]] = fir.zero_bits !fir.heap<none>
256+
! CHECK: %[[V_2:[0-9]+]] = fir.embox %[[V_1]] : (!fir.heap<none>) -> !fir.class<!fir.heap<none>>
257+
! CHECK: fir.store %[[V_2]] to %[[V_0]] : !fir.ref<!fir.class<!fir.heap<none>>>
258+
! CHECK: %[[V_3:[0-9]+]] = fir.alloca !fir.class<!fir.heap<none>> {bindc_name = "b", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic4Eb"}
259+
! CHECK: %[[V_4:[0-9]+]] = fir.zero_bits !fir.heap<none>
260+
! CHECK: %[[V_5:[0-9]+]] = fir.embox %[[V_4]] : (!fir.heap<none>) -> !fir.class<!fir.heap<none>>
261+
! CHECK: fir.store %[[V_5]] to %[[V_3]] : !fir.ref<!fir.class<!fir.heap<none>>>
262+
! CHECK: %[[V_6:[0-9]+]] = fir.load %[[V_0]] : !fir.ref<!fir.class<!fir.heap<none>>>
263+
! CHECK: %[[V_7:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<!fir.class<!fir.heap<none>>>
264+
! CHECK: %[[V_8:[0-9]+]] = fir.load %[[I]] : !fir.ref<i32>
265+
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
266+
! CHECK: %[[V_9:[0-9]+]] = arith.cmpi eq, %[[V_8]], %[[C1]] : i32
267+
! CHECK: %[[V_10:[0-9]+]] = arith.select %[[V_9]], %[[V_6]], %[[V_7]] : !fir.class<!fir.heap<none>>
268+
! CHECK: %[[V_11:[0-9]+]] = fir.rebox %[[V_10]] : (!fir.class<!fir.heap<none>>) -> !fir.class<none>
269+
! CHECK: fir.call @_QMpoly_tmpPcheck_unlimited_poly(%[[V_11]]) fastmath<contract> : (!fir.class<none>) -> ()
270+
271+
subroutine test_merge_intrinsic5(i)
272+
integer, intent(in) :: i
273+
class(*), pointer :: a, b
274+
275+
call check_unlimited_poly(merge(a, b, i==1))
276+
end subroutine
277+
278+
! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic5(
279+
! CHECK-SAME: %[[I:.*]]: !fir.ref<i32> {fir.bindc_name = "i"}) {
280+
! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.class<!fir.ptr<none>> {bindc_name = "a", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic5Ea"}
281+
! CHECK: %[[V_1:[0-9]+]] = fir.zero_bits !fir.ptr<none>
282+
! CHECK: %[[V_2:[0-9]+]] = fir.embox %[[V_1]] : (!fir.ptr<none>) -> !fir.class<!fir.ptr<none>>
283+
! CHECK: fir.store %[[V_2]] to %[[V_0]] : !fir.ref<!fir.class<!fir.ptr<none>>>
284+
! CHECK: %[[V_3:[0-9]+]] = fir.alloca !fir.class<!fir.ptr<none>> {bindc_name = "b", uniq_name = "_QMpoly_tmpFtest_merge_intrinsic5Eb"}
285+
! CHECK: %[[V_4:[0-9]+]] = fir.zero_bits !fir.ptr<none>
286+
! CHECK: %[[V_5:[0-9]+]] = fir.embox %[[V_4]] : (!fir.ptr<none>) -> !fir.class<!fir.ptr<none>>
287+
! CHECK: fir.store %[[V_5]] to %[[V_3]] : !fir.ref<!fir.class<!fir.ptr<none>>>
288+
! CHECK: %[[V_6:[0-9]+]] = fir.load %[[V_0]] : !fir.ref<!fir.class<!fir.ptr<none>>>
289+
! CHECK: %[[V_7:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<!fir.class<!fir.ptr<none>>>
290+
! CHECK: %[[V_8:[0-9]+]] = fir.load %[[I]] : !fir.ref<i32>
291+
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
292+
! CHECK: %[[V_9:[0-9]+]] = arith.cmpi eq, %[[V_8]], %[[C1]] : i32
293+
! CHECK: %[[V_10:[0-9]+]] = arith.select %[[V_9]], %[[V_6]], %[[V_7]] : !fir.class<!fir.ptr<none>>
294+
! CHECK: %[[V_11:[0-9]+]] = fir.rebox %[[V_10]] : (!fir.class<!fir.ptr<none>>) -> !fir.class<none>
295+
! CHECK: fir.call @_QMpoly_tmpPcheck_unlimited_poly(%[[V_11]]) fastmath<contract> : (!fir.class<none>) -> ()
296+
226297
end module

0 commit comments

Comments
 (0)