Skip to content

Commit ae126b8

Browse files
committed
[flang] Treat hlfir.associate as Allocate for FIR alias analysis.
Early HLFIR optimizations may experience problems with values produced by hlfir.associate. In most cases this is a unique local memory allocation, but it can also reuse some other hlfir.expr memory sometimes. It seems to be safe to assume unique allocation for trivial types, since we always allocate new memory for them.
1 parent e0e3d05 commit ae126b8

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

flang/lib/Optimizer/Analysis/AliasAnalysis.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,20 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
540540
v = op.getVar();
541541
defOp = v.getDefiningOp();
542542
})
543+
.Case<hlfir::AssociateOp>([&](auto op) {
544+
mlir::Value source = op.getSource();
545+
if (fir::isa_trivial(source.getType())) {
546+
// Trivial values will always use distinct temp memory,
547+
// so we can classify this as Allocate and stop.
548+
type = SourceKind::Allocate;
549+
breakFromLoop = true;
550+
} else {
551+
// AssociateOp may reuse the expression storage,
552+
// so we have to trace further.
553+
v = source;
554+
defOp = v.getDefiningOp();
555+
}
556+
})
543557
.Case<fir::AllocaOp, fir::AllocMemOp>([&](auto op) {
544558
// Unique memory allocation.
545559
type = SourceKind::Allocate;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: fir-opt --opt-bufferization %s | FileCheck %s
2+
3+
// Verify that hlfir.eval_in_mem uses the LHS array instead
4+
// of allocating a temporary.
5+
func.func @_QPtest() {
6+
%cst = arith.constant 1.000000e+00 : f32
7+
%c10 = arith.constant 10 : index
8+
%0 = fir.dummy_scope : !fir.dscope
9+
%1 = fir.alloca !fir.array<10xf32> {bindc_name = "x", uniq_name = "_QFtestEx"}
10+
%2 = fir.shape %c10 : (index) -> !fir.shape<1>
11+
%3:2 = hlfir.declare %1(%2) {uniq_name = "_QFtestEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
12+
%4:3 = hlfir.associate %cst {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
13+
%5 = hlfir.eval_in_mem shape %2 : (!fir.shape<1>) -> !hlfir.expr<10xf32> {
14+
^bb0(%arg0: !fir.ref<!fir.array<10xf32>>):
15+
%6 = fir.call @_QParray_func(%4#0) fastmath<contract> : (!fir.ref<f32>) -> !fir.array<10xf32>
16+
fir.save_result %6 to %arg0(%2) : !fir.array<10xf32>, !fir.ref<!fir.array<10xf32>>, !fir.shape<1>
17+
}
18+
hlfir.assign %5 to %3#0 : !hlfir.expr<10xf32>, !fir.ref<!fir.array<10xf32>>
19+
hlfir.end_associate %4#1, %4#2 : !fir.ref<f32>, i1
20+
hlfir.destroy %5 : !hlfir.expr<10xf32>
21+
return
22+
}
23+
// CHECK-LABEL: func.func @_QPtest() {
24+
// CHECK: %[[VAL_0:.*]] = arith.constant 1.000000e+00 : f32
25+
// CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<10xf32> {bindc_name = "x", uniq_name = "_QFtestEx"}
26+
// CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_4:.*]]) {uniq_name = "_QFtestEx"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
27+
// CHECK: %[[VAL_6:.*]]:3 = hlfir.associate %[[VAL_0]] {adapt.valuebyref} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
28+
// CHECK: %[[VAL_7:.*]] = fir.call @_QParray_func(%[[VAL_6]]#0) fastmath<contract> : (!fir.ref<f32>) -> !fir.array<10xf32>
29+
// CHECK: fir.save_result %[[VAL_7]] to %[[VAL_5]]#0(%[[VAL_4]]) : !fir.array<10xf32>, !fir.ref<!fir.array<10xf32>>, !fir.shape<1>
30+
// CHECK: hlfir.end_associate %[[VAL_6]]#1, %[[VAL_6]]#2 : !fir.ref<f32>, i1

0 commit comments

Comments
 (0)