Skip to content

Commit e6bef08

Browse files
authored
[flang] Avoid double free in bufferize pass (#93922)
In some cases where we have an `hlfir.no_reassoc` operation, the bufferization pass could not earse the hlfir.destroy op during the `hlfir.associate` op conversion as show in the example below. ``` func.func @double_free(%arg0: !fir.boxchar<1>) { %c5 = arith.constant 5 : index %true = arith.constant true %0 = hlfir.as_expr %arg0 move %true : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>> %1 = hlfir.no_reassoc %0 : !hlfir.expr<!fir.char<1,?>> %2:3 = hlfir.associate %1 typeparams %c5 {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1) fir.call @noop(%2#0) : (!fir.boxchar<1>) -> () hlfir.end_associate %2#1, %2#2 : !fir.ref<!fir.char<1,?>>, i1 hlfir.destroy %0 : !hlfir.expr<!fir.char<1,?>> return } func.func private @noop(!fir.boxchar<1>) ``` The bufferization pass is looking at uses of its source `%1` that is the result of an `hlfir.no_reassoc` operation. In order to avoid double free generation, also look at the indirection in presence of `hlfir.no_reassoc`.
1 parent c5e417a commit e6bef08

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,11 @@ struct AssociateOpConversion
534534
mlir::Value firBase = hlfir::Entity{bufferizedExpr}.getFirBase();
535535
replaceWith(bufferizedExpr, firBase, mustFree);
536536
eraseAllUsesInDestroys(associate.getSource(), rewriter);
537+
// Make sure to erase the hlfir.destroy if there is an indirection through
538+
// a hlfir.no_reassoc operation.
539+
if (auto noReassoc = mlir::dyn_cast_or_null<hlfir::NoReassocOp>(
540+
associate.getSource().getDefiningOp()))
541+
eraseAllUsesInDestroys(noReassoc.getVal(), rewriter);
537542
return mlir::success();
538543
}
539544
if (isTrivialValue) {

flang/test/HLFIR/bufferize01.fir

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,31 @@ fir.global linkonce @_QQclXce30ef70ff16a711a97719fb946c0b3d constant : !fir.char
143143
fir.has_value %0 : !fir.char<1,1>
144144
}
145145
func.func private @_FortranAPushArrayConstructorValue(!fir.llvm_ptr<i8>, !fir.box<none>) -> none attributes {fir.runtime}
146+
147+
// -----
148+
149+
// Test that only a single freemem is generated.
150+
151+
func.func @double_free(%arg0: !fir.boxchar<1>) {
152+
%c5 = arith.constant 5 : index
153+
%true = arith.constant true
154+
%0 = hlfir.as_expr %arg0 move %true : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
155+
%1 = hlfir.no_reassoc %0 : !hlfir.expr<!fir.char<1,?>>
156+
%2:3 = hlfir.associate %1 typeparams %c5 {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)
157+
fir.call @noop(%2#0) : (!fir.boxchar<1>) -> ()
158+
hlfir.end_associate %2#1, %2#2 : !fir.ref<!fir.char<1,?>>, i1
159+
hlfir.destroy %0 : !hlfir.expr<!fir.char<1,?>>
160+
return
161+
}
162+
func.func private @noop(!fir.boxchar<1>)
163+
164+
// CHECK-LABEL: func.func @double_free(
165+
// CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1>) {
166+
// CHECK: %[[NO_REASSOC:.*]] = hlfir.no_reassoc %[[ARG0]] : !fir.boxchar<1>
167+
// CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[NO_REASSOC]] : (!fir.boxchar<1>) -> !fir.ref<!fir.char<1,?>>
168+
// CHECK: fir.call @noop
169+
// CHECK: %[[CONV:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.ref<!fir.char<1,?>>) -> !fir.heap<!fir.char<1,?>>
170+
// CHECK: fir.freemem %[[CONV]] : !fir.heap<!fir.char<1,?>>
171+
// CHECK-NOT: fir.freemem
172+
173+

0 commit comments

Comments
 (0)