From a3f9ce69eeb2af52b07307e476eb5895a59fb75b Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Fri, 7 Jul 2023 12:54:18 +0000 Subject: [PATCH] [flang][hlfir]: fix associate of expr with more than one use Make a copy of the expression and associate that so that this is the only use. So far as I know, we don't currently generate code for an associate with more than one use. This is here just in case. Depends on D154715 Differential Revision: https://reviews.llvm.org/D154721 --- .../HLFIR/Transforms/BufferizeHLFIR.cpp | 14 +++++- flang/test/HLFIR/associate-codegen.fir | 50 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp index 91633e8c3c2ad3..ce86ae9a9c775e 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp @@ -459,7 +459,19 @@ struct AssociateOpConversion replaceWith(temp, temp, mustFree); return mlir::success(); } - TODO(loc, "hlfir.associate of hlfir.expr with more than one use"); + // non-trivial value with more than one use. We will have to make a copy and + // use that + hlfir::Entity source = hlfir::Entity{adaptor.getSource()}; + auto [temp, cleanup] = createTempFromMold(loc, builder, source); + builder.create(loc, source, temp, /*reassoc=*/false, + /*keep_lhs_length_if_realloc=*/false, + /*temporary_lhs=*/true); + mlir::Value bufferTuple = + packageBufferizedExpr(loc, builder, temp, cleanup); + bufferizedExpr = getBufferizedExprStorage(bufferTuple); + replaceWith(bufferizedExpr, hlfir::Entity{bufferizedExpr}.getFirBase(), + getBufferizedExprMustFreeFlag(bufferTuple)); + return mlir::success(); } }; diff --git a/flang/test/HLFIR/associate-codegen.fir b/flang/test/HLFIR/associate-codegen.fir index aca89dc8df15fa..2f9e6f1485c927 100644 --- a/flang/test/HLFIR/associate-codegen.fir +++ b/flang/test/HLFIR/associate-codegen.fir @@ -288,6 +288,56 @@ func.func @test_cloned_associate() { // CHECK: return // CHECK: } +func.func @test_multiple_associations(%arg0: !hlfir.expr<1x2xi32>) { + %c1 = arith.constant 1 : index + %c2 = arith.constant 2 : index + %shape = fir.shape %c1, %c2 : (index, index) -> !fir.shape<2> + %0:3 = hlfir.associate %arg0(%shape) {uniq_name = "associate 0"} : (!hlfir.expr<1x2xi32>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>, i1) + %1:3 = hlfir.associate %arg0(%shape) {uniq_name = "associate 1"} : (!hlfir.expr<1x2xi32>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>, i1) + hlfir.end_associate %0#1, %0#2 : !fir.ref>, i1 + hlfir.end_associate %1#1, %1#2 : !fir.ref>, i1 + return +} +// CHECK-LABEL: func.func @test_multiple_associations( +// CHECK-SAME: %[[VAL_0:.*]]: !hlfir.expr<1x2xi32>) { +// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_2:.*]] = arith.constant 2 : index +// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2> +// associate 0: +// CHECK: %[[VAL_4:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr<1x2xi32>) -> !fir.shape<2> +// CHECK: %[[VAL_5:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_6:.*]] = arith.constant 2 : index +// CHECK: %[[VAL_7:.*]] = fir.allocmem !fir.array<1x2xi32> {bindc_name = ".tmp", uniq_name = ""} +// CHECK: %[[VAL_8:.*]] = arith.constant true +// CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_4]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<2>) -> (!fir.heap>, !fir.heap>) +// CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_9]]#0 temporary_lhs : !hlfir.expr<1x2xi32>, !fir.heap> +// CHECK: %[[VAL_10:.*]] = fir.undefined tuple>, i1> +// CHECK: %[[VAL_11:.*]] = fir.insert_value %[[VAL_10]], %[[VAL_8]], [1 : index] : (tuple>, i1>, i1) -> tuple>, i1> +// CHECK: %[[VAL_12:.*]] = fir.insert_value %[[VAL_11]], %[[VAL_9]]#0, [0 : index] : (tuple>, i1>, !fir.heap>) -> tuple>, i1> +// CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_9]]#0 : (!fir.heap>) -> !fir.ref> +// CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_9]]#1 : (!fir.heap>) -> !fir.ref> +// associate 1: +// CHECK: %[[VAL_15:.*]] = hlfir.shape_of %[[VAL_0]] : (!hlfir.expr<1x2xi32>) -> !fir.shape<2> +// CHECK: %[[VAL_16:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_17:.*]] = arith.constant 2 : index +// CHECK: %[[VAL_18:.*]] = fir.allocmem !fir.array<1x2xi32> {bindc_name = ".tmp", uniq_name = ""} +// CHECK: %[[VAL_19:.*]] = arith.constant true +// CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_18]](%[[VAL_15]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<2>) -> (!fir.heap>, !fir.heap>) +// CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_20]]#0 temporary_lhs : !hlfir.expr<1x2xi32>, !fir.heap> +// CHECK: %[[VAL_21:.*]] = fir.undefined tuple>, i1> +// CHECK: %[[VAL_22:.*]] = fir.insert_value %[[VAL_21]], %[[VAL_19]], [1 : index] : (tuple>, i1>, i1) -> tuple>, i1> +// CHECK: %[[VAL_23:.*]] = fir.insert_value %[[VAL_22]], %[[VAL_20]]#0, [0 : index] : (tuple>, i1>, !fir.heap>) -> tuple>, i1> +// CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_20]]#0 : (!fir.heap>) -> !fir.ref> +// CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_20]]#1 : (!fir.heap>) -> !fir.ref> +// end associate 0: +// CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_14]] : (!fir.ref>) -> !fir.heap> +// CHECK: fir.freemem %[[VAL_26]] : !fir.heap> +// end associate 1: +// CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_25]] : (!fir.ref>) -> !fir.heap> +// CHECK: fir.freemem %[[VAL_27]] : !fir.heap> +// CHECK: return +// CHECK: } + func.func private @take_i4(!fir.ref) func.func private @take_r4(!fir.ref) func.func private @take_l4(!fir.ref>)