Skip to content

Commit ac221f8

Browse files
committed
[flang][hlfir] refine hlfir.assign side effects
1 parent b81d8e9 commit ac221f8

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def hlfir_DeclareOp : hlfir_Op<"declare", [AttrSizedOperandSegments,
130130
let hasVerifier = 1;
131131
}
132132

133-
def fir_AssignOp : hlfir_Op<"assign", [MemoryEffects<[MemWrite]>]> {
133+
def fir_AssignOp : hlfir_Op<"assign", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
134134
let summary = "Assign an expression or variable value to a Fortran variable";
135135

136136
let description = [{
@@ -166,7 +166,7 @@ def fir_AssignOp : hlfir_Op<"assign", [MemoryEffects<[MemWrite]>]> {
166166
}];
167167

168168
let arguments = (ins AnyFortranEntity:$rhs,
169-
Arg<AnyFortranVariable, "", [MemWrite]>:$lhs,
169+
AnyFortranVariable:$lhs,
170170
UnitAttr:$realloc,
171171
UnitAttr:$keep_lhs_length_if_realloc,
172172
UnitAttr:$temporary_lhs);

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,62 @@ llvm::LogicalResult hlfir::AssignOp::verify() {
9090
return mlir::success();
9191
}
9292

93+
void hlfir::AssignOp::getEffects(
94+
llvm::SmallVectorImpl<
95+
mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
96+
&effects) {
97+
mlir::OpOperand &rhs = getRhsMutable();
98+
mlir::OpOperand &lhs = getLhsMutable();
99+
mlir::Type rhsType = getRhs().getType();
100+
mlir::Type lhsType = getLhs().getType();
101+
if (mlir::isa<fir::RecordType>(hlfir::getFortranElementType(lhsType))) {
102+
// For derived type assignments, set unknown read/write effects since it
103+
// is not known here if user defined finalization is needed, and also
104+
// because allocatable components may lead to "deeper" read/write effects
105+
// that cannot be described with this API.
106+
effects.emplace_back(mlir::MemoryEffects::Read::get(),
107+
mlir::SideEffects::DefaultResource::get());
108+
effects.emplace_back(mlir::MemoryEffects::Write::get(),
109+
mlir::SideEffects::DefaultResource::get());
110+
} else {
111+
// Read effect when RHS is a variable.
112+
if (hlfir::isFortranVariableType(rhsType)) {
113+
if (hlfir::isBoxAddressType(rhsType)) {
114+
// Unknown read effect if the RHS is a descriptor since the read effect
115+
// on the data cannot be described.
116+
effects.emplace_back(mlir::MemoryEffects::Read::get(),
117+
mlir::SideEffects::DefaultResource::get());
118+
} else {
119+
effects.emplace_back(mlir::MemoryEffects::Read::get(), &rhs,
120+
mlir::SideEffects::DefaultResource::get());
121+
}
122+
}
123+
124+
// Write effects on LHS.
125+
if (hlfir::isBoxAddressType(lhsType)) {
126+
// If the LHS is a descriptor, the descriptor will be read and the data
127+
// write cannot be described in this API (and the descriptor may be
128+
// written to in case of realloc, which is covered by the unknown write
129+
// effect.
130+
effects.emplace_back(mlir::MemoryEffects::Read::get(), &lhs,
131+
mlir::SideEffects::DefaultResource::get());
132+
effects.emplace_back(mlir::MemoryEffects::Write::get(),
133+
mlir::SideEffects::DefaultResource::get());
134+
} else {
135+
effects.emplace_back(mlir::MemoryEffects::Write::get(), &lhs,
136+
mlir::SideEffects::DefaultResource::get());
137+
}
138+
}
139+
140+
if (getRealloc()) {
141+
// Reallocation of the data cannot be precisely described by this API.
142+
effects.emplace_back(mlir::MemoryEffects::Free::get(),
143+
mlir::SideEffects::DefaultResource::get());
144+
effects.emplace_back(mlir::MemoryEffects::Allocate::get(),
145+
mlir::SideEffects::DefaultResource::get());
146+
}
147+
}
148+
93149
//===----------------------------------------------------------------------===//
94150
// DeclareOp
95151
//===----------------------------------------------------------------------===//
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Test side effects of hlfir.assign op.
2+
// RUN: fir-opt %s --test-side-effects --verify-diagnostics
3+
4+
func.func @test1(%x: !fir.ref<i32>, %i: i32) {
5+
// expected-remark @below {{found an instance of 'write' on a op operand, on resource '<Default>'}}
6+
hlfir.assign %i to %x : i32, !fir.ref<i32>
7+
return
8+
}
9+
10+
func.func @test2(%x: !fir.ref<i32>, %y: !fir.ref<i32>) {
11+
// expected-remark @below {{found an instance of 'write' on a op operand, on resource '<Default>'}}
12+
// expected-remark @below {{found an instance of 'read' on a op operand, on resource '<Default>'}}
13+
hlfir.assign %y to %x : !fir.ref<i32>, !fir.ref<i32>
14+
return
15+
}
16+
17+
func.func @test3(%x: !fir.ref<!fir.type<t>>, %y: !fir.ref<!fir.type<t>>) {
18+
// expected-remark @below {{found an instance of 'write' on resource '<Default>'}}
19+
// expected-remark @below {{found an instance of 'read' on resource '<Default>'}}
20+
hlfir.assign %y to %x : !fir.ref<!fir.type<t>>, !fir.ref<!fir.type<t>>
21+
return
22+
}
23+
24+
func.func @test4(%x: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, %y: !fir.box<!fir.array<?xi32>>) {
25+
// expected-remark @below {{found an instance of 'read' on a op operand, on resource '<Default>'}}
26+
// expected-remark @below {{found an instance of 'write' on resource '<Default>'}}
27+
// expected-remark @below {{found an instance of 'free' on resource '<Default>'}}
28+
// expected-remark @below {{found an instance of 'allocate' on resource '<Default>'}}
29+
hlfir.assign %y to %x realloc : !fir.box<!fir.array<?xi32>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
30+
return
31+
}

0 commit comments

Comments
 (0)