diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp --- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp @@ -138,7 +138,18 @@ } else { fir::runtime::genAssign(builder, loc, to, from); } - } else if (lhs.isArray()) { + } else if (lhs.isArray() || + // Special case for element-by-element (or scalar) assignments + // generated for creating polymorphic expressions. + // The LHS of these assignments is a box describing just + // a single element, not the whole allocatable temp. + // They do not have 'realloc' attribute, because reallocation + // must not happen. The only expected effect of such an + // assignment is the copy of the contents, because the dynamic + // types of the LHS and the RHS must match already. We use the + // runtime in this case so that the polymorphic (including + // unlimited) content is copied properly. + (lhs.isPolymorphic() && assignOp.isTemporaryLHS())) { // Use the runtime for simplicity. An optimization pass will be added to // inline array assignment when profitable. mlir::Value from = emboxRHS(rhsExv); diff --git a/flang/test/HLFIR/assign-codegen.fir b/flang/test/HLFIR/assign-codegen.fir --- a/flang/test/HLFIR/assign-codegen.fir +++ b/flang/test/HLFIR/assign-codegen.fir @@ -370,3 +370,59 @@ } // CHECK-LABEL: func.func @_QFPtest_scalar_temp_lhs_no_finalization( // CHECK-NOT: fir.call @_FortranADestroy + +func.func @test_upoly_expr_assignment(%arg0: !fir.class> {fir.bindc_name = "y"}) { + %0 = fir.alloca !fir.class>> + %c0 = arith.constant 0 : index + %2:2 = hlfir.declare %arg0 {uniq_name = "_QFtestEy"} : (!fir.class>) -> (!fir.class>, !fir.class>) + %3:3 = fir.box_dims %2#0, %c0 : (!fir.class>, index) -> (index, index, index) + %8:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = ".tmp.array"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + %22 = fir.load %8#0 : !fir.ref>>> + %c1_2 = arith.constant 1 : index + fir.do_loop %arg2 = %c1_2 to %3#1 step %c1_2 unordered { + %27 = hlfir.designate %2#0 (%arg2) : (!fir.class>, index) -> !fir.class + %c0_3 = arith.constant 0 : index + %28:3 = fir.box_dims %22, %c0_3 : (!fir.class>>, index) -> (index, index, index) + %c1_4 = arith.constant 1 : index + %29 = arith.subi %28#0, %c1_4 : index + %30 = arith.addi %arg2, %29 : index + %31 = hlfir.designate %22 (%30) : (!fir.class>>, index) -> !fir.class + hlfir.assign %27 to %31 temporary_lhs : !fir.class, !fir.class + } + return +} +// CHECK-LABEL: func.func @test_upoly_expr_assignment( +// CHECK-SAME: %[[VAL_0:.*]]: !fir.class> {fir.bindc_name = "y"}) { +// CHECK: %[[VAL_1:.*]] = fir.alloca !fir.class +// CHECK: %[[VAL_2:.*]] = fir.alloca !fir.class>> +// CHECK: %[[VAL_3:.*]] = arith.constant 0 : index +// CHECK: %[[VAL_4:.*]] = fir.declare %[[VAL_0]] {uniq_name = "_QFtestEy"} : (!fir.class>) -> !fir.class> +// CHECK: %[[VAL_5:.*]] = fir.rebox %[[VAL_4]] : (!fir.class>) -> !fir.class> +// CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_5]], %[[VAL_3]] : (!fir.class>, index) -> (index, index, index) +// CHECK: %[[VAL_7:.*]] = fir.declare %[[VAL_2]] {fortran_attrs = #fir.var_attrs, uniq_name = ".tmp.array"} : (!fir.ref>>>) -> !fir.ref>>> +// CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]] : !fir.ref>>> +// CHECK: %[[VAL_9:.*]] = arith.constant 1 : index +// CHECK: fir.do_loop %[[VAL_10:.*]] = %[[VAL_9]] to %[[VAL_6]]#1 step %[[VAL_9]] unordered { +// CHECK: %[[VAL_11:.*]] = fir.array_coor %[[VAL_4]] %[[VAL_10]] : (!fir.class>, index) -> !fir.ref +// CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]] source_box %[[VAL_4]] : (!fir.ref, !fir.class>) -> !fir.class +// CHECK: %[[VAL_13:.*]] = arith.constant 0 : index +// CHECK: %[[VAL_14:.*]]:3 = fir.box_dims %[[VAL_8]], %[[VAL_13]] : (!fir.class>>, index) -> (index, index, index) +// CHECK: %[[VAL_15:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_16:.*]] = arith.subi %[[VAL_14]]#0, %[[VAL_15]] : index +// CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_10]], %[[VAL_16]] : index +// CHECK: %[[VAL_18:.*]] = arith.constant 0 : index +// CHECK: %[[VAL_19:.*]]:3 = fir.box_dims %[[VAL_8]], %[[VAL_18]] : (!fir.class>>, index) -> (index, index, index) +// CHECK: %[[VAL_20:.*]] = fir.shift %[[VAL_19]]#0 : (index) -> !fir.shift<1> +// CHECK: %[[VAL_21:.*]] = fir.array_coor %[[VAL_8]](%[[VAL_20]]) %[[VAL_17]] : (!fir.class>>, !fir.shift<1>, index) -> !fir.ref +// CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_21]] source_box %[[VAL_8]] : (!fir.ref, !fir.class>>) -> !fir.class +// CHECK: fir.store %[[VAL_22]] to %[[VAL_1]] : !fir.ref> +// CHECK: %[[VAL_23:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref> +// CHECK: %[[VAL_24:.*]] = arith.constant {{.*}} : index +// CHECK: %[[VAL_25:.*]] = arith.constant {{.*}} : i32 +// CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_1]] : (!fir.ref>) -> !fir.ref> +// CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_12]] : (!fir.class) -> !fir.box +// CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_23]] : (!fir.ref>) -> !fir.ref +// CHECK: %[[VAL_29:.*]] = fir.call @_FortranAAssignTemporary(%[[VAL_26]], %[[VAL_27]], %[[VAL_28]], %[[VAL_25]]) : (!fir.ref>, !fir.box, !fir.ref, i32) -> none +// CHECK: } +// CHECK: return +// CHECK: }