Skip to content

Commit ee47aea

Browse files
authored
[flang] Treat hlfir.associate as Allocate for FIR alias analysis. (#139004)
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 2d12d31 commit ee47aea

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

flang/include/flang/Optimizer/HLFIR/HLFIROps.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,13 @@ def hlfir_AssociateOp : hlfir_Op<"associate", [AttrSizedOperandSegments,
759759
For expressions, this operation is an incentive to re-use the expression
760760
storage, if any, after the bufferization pass when possible (if the
761761
expression is not used afterwards).
762+
763+
For aliasing purposes, hlfir.associate with the source being
764+
a trivial FIR value is considered to be a unique allocation
765+
that does not alias with anything else. For non-trivial cases
766+
it may be a unique allocation or an alias for the source expression
767+
storage, so FIR alias analysis will look through it for finding
768+
the source.
762769
}];
763770

764771
let arguments = (ins

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)