diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -3925,14 +3925,29 @@ mlir::Type type0 = fir::unwrapRefType(tsource.getType()); bool isCharRslt = fir::isa_char(type0); // result is same as first argument mlir::Value mask = builder.createConvert(loc, builder.getI1Type(), rawMask); - // FSOURCE has the same type as TSOURCE, but they may not have the same MLIR - // types (one can have dynamic length while the other has constant lengths, - // or one may be a fir.logical<> while the other is an i1). Insert a cast to - // fulfill mlir::SelectOp constraint that the MLIR types must be the same. - mlir::Value fsourceCast = - builder.createConvert(loc, tsource.getType(), fsource); - auto rslt = - builder.create(loc, mask, tsource, fsourceCast); + + // The result is polymorphic if and only if both TSOURCE and FSOURCE are + // polymorphic. TSOURCE and FSOURCE are required to have the same type + // (for both declared and dynamic types) so a simple convert op can be + // used. + mlir::Value tsourceCast = tsource; + mlir::Value fsourceCast = fsource; + if (fir::isPolymorphicType(tsource.getType()) && + !fir::isPolymorphicType(fsource.getType())) { + tsourceCast = builder.createConvert(loc, fsource.getType(), tsource); + } else if (!fir::isPolymorphicType(tsource.getType()) && + fir::isPolymorphicType(fsource.getType())) { + fsourceCast = builder.createConvert(loc, tsource.getType(), fsource); + } else { + // FSOURCE and TSOURCE are not polymorphic. + // FSOURCE has the same type as TSOURCE, but they may not have the same MLIR + // types (one can have dynamic length while the other has constant lengths, + // or one may be a fir.logical<> while the other is an i1). Insert a cast to + // fulfill mlir::SelectOp constraint that the MLIR types must be the same. + fsourceCast = builder.createConvert(loc, tsource.getType(), fsource); + } + auto rslt = builder.create(loc, mask, tsourceCast, + fsourceCast); if (isCharRslt) { // Need a CharBoxValue for character results const fir::CharBoxValue *charBox = args[0].getCharBox(); diff --git a/flang/test/Lower/polymorphic-temp.f90 b/flang/test/Lower/polymorphic-temp.f90 --- a/flang/test/Lower/polymorphic-temp.f90 +++ b/flang/test/Lower/polymorphic-temp.f90 @@ -215,7 +215,6 @@ call check_scalar(merge(a, b, i==1)) end subroutine - ! CHECK-LABEL: func.func @_QMpoly_tmpPtest_merge_intrinsic2( ! CHECK-SAME: %[[A:.*]]: !fir.ref>>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref>>> {fir.bindc_name = "b"}, %[[I:.*]]: !fir.ref {fir.bindc_name = "i"}) { ! CHECK: %[[LOAD_A:.*]] = fir.load %[[A]] : !fir.ref>>> @@ -223,7 +222,7 @@ ! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]] : !fir.ref ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 ! CHECK: %[[CMPI:.*]] = arith.cmpi eq, %[[LOAD_I]], %[[C1]] : i32 -! CHECK: %[[B_CONV:.*]] = fir.convert %[[LOAD_B]] : (!fir.box>>) -> !fir.class>> -! CHECK: %{{.*}} = arith.select %[[CMPI]], %[[LOAD_A]], %[[B_CONV]] : !fir.class>> +! CHECK: %[[A_CONV:.*]] = fir.convert %[[LOAD_A]] : (!fir.class>>) -> !fir.box>> +! CHECK: %{{.*}} = arith.select %[[CMPI]], %[[A_CONV]], %[[LOAD_B]] : !fir.box>> end module