@@ -102,73 +102,86 @@ class ArrayCopyAnalysis {
102
102
} // namespace
103
103
104
104
namespace {
105
-
106
105
// / Helper class to collect all array operations that produced an array value.
107
106
class ReachCollector {
108
107
public:
109
108
ReachCollector (llvm::SmallVectorImpl<mlir::Operation *> &reach,
110
109
mlir::Region *loopRegion)
111
110
: reach{reach}, loopRegion{loopRegion} {}
112
111
113
- // Recursively trace operands to find all array operations relating to the
114
- // values merged.
115
- void collectArrayAccessFrom (mlir::Value val) {
116
- if (!val || visited.contains (val))
112
+ void collectArrayAccessFrom (mlir::Operation *op, mlir::ValueRange range) {
113
+ if (range.empty ()) {
114
+ collectArrayAccessFrom (op, mlir::Value{});
117
115
return ;
118
- visited.insert (val);
119
-
120
- if (auto *op = val.getDefiningOp ()) {
121
- // `val` is defined by an Op, process the defining Op.
122
- // If `val` is defined by a region containing Op, we want to drill down
123
- // and through that Op's region(s).
124
- LLVM_DEBUG (llvm::dbgs () << " popset: " << val << ' \n ' );
125
- auto popFn = [&](auto rop) {
126
- auto resNum = val.cast <mlir::OpResult>().getResultNumber ();
127
- llvm::SmallVector<mlir::Value> results;
128
- rop.resultToSourceOps (results, resNum);
129
- for (auto u : results)
130
- collectArrayAccessFrom (u);
131
- };
132
- if (auto rop = mlir::dyn_cast<DoLoopOp>(op)) {
133
- popFn (rop);
134
- return ;
135
- }
136
- if (auto rop = mlir::dyn_cast<IterWhileOp>(op)) {
137
- popFn (rop);
138
- return ;
139
- }
140
- if (auto rop = mlir::dyn_cast<fir::IfOp>(op)) {
141
- popFn (rop);
142
- return ;
143
- }
144
-
145
- if (mlir::isa<fir::AllocaOp, fir::AllocMemOp>(op))
146
- // Look for any stores inside the loops, and collect an array operation
147
- // that produced the value being stored to it.
148
- for (auto user : op->getUsers ())
149
- if (auto store = mlir::dyn_cast<fir::StoreOp>(user))
150
- if (opIsInsideLoops (store))
151
- collectArrayAccessFrom (store.value ());
152
-
153
- // Otherwise, Op does not contain a region so just chase its operands.
154
- if (mlir::isa<ArrayLoadOp, ArrayUpdateOp, ArrayModifyOp, ArrayFetchOp>(
155
- op)) {
156
- LLVM_DEBUG (llvm::dbgs () << " add " << *op << " to reachable set\n " );
157
- reach.emplace_back (op);
158
- }
159
- // Array modify assignment is performed on the result. So the analysis
160
- // must look at the what is done with the result.
161
- if (mlir::isa<ArrayModifyOp>(op))
162
- for (auto user : op->getResult (0 ).getUsers ())
163
- followUsers (user);
116
+ }
117
+ for (auto v : range)
118
+ collectArrayAccessFrom (v);
119
+ }
164
120
165
- for (auto u : op->getOperands ())
121
+ void collectArrayAccessFrom (mlir::Operation *op, mlir::Value val) {
122
+ // `val` is defined by an Op, process the defining Op.
123
+ // If `val` is defined by a region containing Op, we want to drill down
124
+ // and through that Op's region(s).
125
+ LLVM_DEBUG (llvm::dbgs () << " popset: " << *op << ' \n ' );
126
+ auto popFn = [&](auto rop) {
127
+ assert (val && " op must have a result value" );
128
+ auto resNum = val.cast <mlir::OpResult>().getResultNumber ();
129
+ llvm::SmallVector<mlir::Value> results;
130
+ rop.resultToSourceOps (results, resNum);
131
+ for (auto u : results)
166
132
collectArrayAccessFrom (u);
133
+ };
134
+ if (auto rop = mlir::dyn_cast<DoLoopOp>(op)) {
135
+ popFn (rop);
136
+ return ;
137
+ }
138
+ if (auto rop = mlir::dyn_cast<IterWhileOp>(op)) {
139
+ popFn (rop);
140
+ return ;
141
+ }
142
+ if (auto rop = mlir::dyn_cast<fir::IfOp>(op)) {
143
+ popFn (rop);
144
+ return ;
145
+ }
146
+ if (auto box = mlir::dyn_cast<EmboxOp>(op)) {
147
+ for (auto *user : box.memref ().getUsers ())
148
+ if (user != op)
149
+ collectArrayAccessFrom (user, user->getResults ());
150
+ return ;
151
+ }
152
+ if (auto mergeStore = mlir::dyn_cast<ArrayMergeStoreOp>(op)) {
153
+ if (opIsInsideLoops (mergeStore))
154
+ collectArrayAccessFrom (mergeStore.sequence ());
167
155
return ;
168
156
}
169
157
170
- // Process a block argument.
171
- auto ba = val.cast <mlir::BlockArgument>();
158
+ if (mlir::isa<AllocaOp, AllocMemOp>(op)) {
159
+ // Look for any stores inside the loops, and collect an array operation
160
+ // that produced the value being stored to it.
161
+ for (auto *user : op->getUsers ())
162
+ if (auto store = mlir::dyn_cast<fir::StoreOp>(user))
163
+ if (opIsInsideLoops (store))
164
+ collectArrayAccessFrom (store.value ());
165
+ return ;
166
+ }
167
+
168
+ // Otherwise, Op does not contain a region so just chase its operands.
169
+ if (mlir::isa<ArrayLoadOp, ArrayUpdateOp, ArrayModifyOp, ArrayFetchOp>(
170
+ op)) {
171
+ LLVM_DEBUG (llvm::dbgs () << " add " << *op << " to reachable set\n " );
172
+ reach.emplace_back (op);
173
+ }
174
+ // Array modify assignment is performed on the result. So the analysis
175
+ // must look at the what is done with the result.
176
+ if (mlir::isa<ArrayModifyOp>(op))
177
+ for (auto *user : op->getResult (0 ).getUsers ())
178
+ followUsers (user);
179
+
180
+ for (auto u : op->getOperands ())
181
+ collectArrayAccessFrom (u);
182
+ }
183
+
184
+ void collectArrayAccessFrom (mlir::BlockArgument ba) {
172
185
auto *parent = ba.getOwner ()->getParentOp ();
173
186
// If inside an Op holding a region, the block argument corresponds to an
174
187
// argument passed to the containing Op.
@@ -190,8 +203,44 @@ class ReachCollector {
190
203
}
191
204
}
192
205
206
+ // Recursively trace operands to find all array operations relating to the
207
+ // values merged.
208
+ void collectArrayAccessFrom (mlir::Value val) {
209
+ if (!val || visited.contains (val))
210
+ return ;
211
+ visited.insert (val);
212
+
213
+ // Process a block argument.
214
+ if (auto ba = val.dyn_cast <mlir::BlockArgument>()) {
215
+ collectArrayAccessFrom (ba);
216
+ return ;
217
+ }
218
+
219
+ // Process an Op.
220
+ if (auto *op = val.getDefiningOp ()) {
221
+ collectArrayAccessFrom (op, val);
222
+ return ;
223
+ }
224
+
225
+ fir::emitFatalError (val.getLoc (), " unhandled value" );
226
+ }
227
+
228
+ // / Return all ops that produce the array value that is stored into the
229
+ // / `array_merge_store`.
230
+ static void reachingValues (llvm::SmallVectorImpl<mlir::Operation *> &reach,
231
+ mlir::Value seq) {
232
+ reach.clear ();
233
+ mlir::Region *loopRegion = nullptr ;
234
+ if (auto doLoop =
235
+ mlir::dyn_cast_or_null<fir::DoLoopOp>(seq.getDefiningOp ()))
236
+ loopRegion = &doLoop->getRegion (0 );
237
+ ReachCollector collector (reach, loopRegion);
238
+ collector.collectArrayAccessFrom (seq);
239
+ }
240
+
193
241
private:
194
242
// / Is \op inside the loop nest region ?
243
+ // / FIXME: replace this structural dependence with graph properties.
195
244
bool opIsInsideLoops (mlir::Operation *op) const {
196
245
auto *region = op->getParentRegion ();
197
246
while (region) {
@@ -219,18 +268,6 @@ class ReachCollector {
219
268
};
220
269
} // namespace
221
270
222
- // / Return all ops that produce the array value that is stored into the
223
- // / `array_merge_store`.
224
- static void reachingValues (llvm::SmallVectorImpl<mlir::Operation *> &reach,
225
- mlir::Value seq) {
226
- reach.clear ();
227
- mlir::Region *loopRegion = nullptr ;
228
- if (auto doLoop = mlir::dyn_cast_or_null<fir::DoLoopOp>(seq.getDefiningOp ()))
229
- loopRegion = &doLoop->getRegion (0 );
230
- ReachCollector collector (reach, loopRegion);
231
- collector.collectArrayAccessFrom (seq);
232
- }
233
-
234
271
// / Find all the array operations that access the array value that is loaded by
235
272
// / the array load operation, `load`.
236
273
void ArrayCopyAnalysis::arrayAccesses (
@@ -406,7 +443,7 @@ void ArrayCopyAnalysis::construct(mlir::MutableArrayRef<mlir::Region> regions) {
406
443
construct (op.getRegions ());
407
444
if (auto st = mlir::dyn_cast<fir::ArrayMergeStoreOp>(op)) {
408
445
llvm::SmallVector<Operation *> values;
409
- reachingValues (values, st.sequence ());
446
+ ReachCollector:: reachingValues (values, st.sequence ());
410
447
llvm::SmallVector<Operation *> accesses;
411
448
arrayAccesses (accesses,
412
449
mlir::cast<ArrayLoadOp>(st.original ().getDefiningOp ()));
@@ -728,9 +765,9 @@ class ArrayUpdateConversion : public ArrayUpdateConversionBase<ArrayUpdateOp> {
728
765
if (!update.typeparams ().empty ()) {
729
766
auto boxTy = fir::BoxType::get (inEleTy);
730
767
mlir::Value emptyShape, emptySlice;
731
- auto lhs = rewriter.create <fir:: EmboxOp>(
768
+ auto lhs = rewriter.create <EmboxOp>(
732
769
loc, boxTy, coor, emptyShape, emptySlice, update.typeparams ());
733
- auto rhs = rewriter.create <fir:: EmboxOp>(
770
+ auto rhs = rewriter.create <EmboxOp>(
734
771
loc, boxTy, input, emptyShape, emptySlice, update.typeparams ());
735
772
fir::factory::genRecordAssignment (builder, loc, fir::BoxValue (lhs),
736
773
fir::BoxValue (rhs));
0 commit comments