19
19
20
20
using namespace mlir ;
21
21
22
+ // Fuse `foldedLocation` into the Location of `retainedOp`.
23
+ // This will result in `retainedOp` having a FusedLoc with a StringAttr tag
24
+ // "OpFold" to help trace the source of the fusion. If `retainedOp` already had
25
+ // a FusedLoc with the same tag, `foldedLocation` will simply be appended to it.
26
+ // Usage:
27
+ // - When an op is deduplicated, fuse the location of the op to be removed into
28
+ // the op that is retained.
29
+ // - When an op is hoisted to the front/back of a block, fuse the location of
30
+ // the parent region of the block into the hoisted op.
31
+ static void appendFoldedLocation (Operation *retainedOp,
32
+ Location foldedLocation) {
33
+ constexpr std::string_view tag = " OpFold" ;
34
+ // Append into existing fused location if it has the same tag.
35
+ if (auto existingFusedLoc =
36
+ retainedOp->getLoc ().dyn_cast <FusedLocWith<StringAttr>>()) {
37
+ StringAttr existingMetadata = existingFusedLoc.getMetadata ();
38
+ if (existingMetadata.strref ().equals (tag)) {
39
+ SmallVector<Location> locations (existingFusedLoc.getLocations ());
40
+ locations.push_back (foldedLocation);
41
+ Location newFusedLoc =
42
+ FusedLoc::get (retainedOp->getContext (), locations, existingMetadata);
43
+ retainedOp->setLoc (newFusedLoc);
44
+ return ;
45
+ }
46
+ }
47
+ // Create a new fusedloc with retainedOp's loc and foldedLocation.
48
+ Location newFusedLoc = FusedLoc::get (
49
+ retainedOp->getContext (), {retainedOp->getLoc (), foldedLocation},
50
+ StringAttr::get (retainedOp->getContext (), tag));
51
+ retainedOp->setLoc (newFusedLoc);
52
+ }
53
+
22
54
// / Given an operation, find the parent region that folded constants should be
23
55
// / inserted into.
24
56
static Region *
@@ -77,8 +109,10 @@ LogicalResult OperationFolder::tryToFold(Operation *op, bool *inPlaceUpdate) {
77
109
// Check to see if we should rehoist, i.e. if a non-constant operation was
78
110
// inserted before this one.
79
111
Block *opBlock = op->getBlock ();
80
- if (&opBlock->front () != op && !isFolderOwnedConstant (op->getPrevNode ()))
112
+ if (&opBlock->front () != op && !isFolderOwnedConstant (op->getPrevNode ())) {
81
113
op->moveBefore (&opBlock->front ());
114
+ appendFoldedLocation (op, opBlock->getParent ()->getLoc ());
115
+ }
82
116
return failure ();
83
117
}
84
118
@@ -112,8 +146,10 @@ bool OperationFolder::insertKnownConstant(Operation *op, Attribute constValue) {
112
146
// If this is a constant we unique'd, we don't need to insert, but we can
113
147
// check to see if we should rehoist it.
114
148
if (isFolderOwnedConstant (op)) {
115
- if (&opBlock->front () != op && !isFolderOwnedConstant (op->getPrevNode ()))
149
+ if (&opBlock->front () != op && !isFolderOwnedConstant (op->getPrevNode ())) {
116
150
op->moveBefore (&opBlock->front ());
151
+ appendFoldedLocation (op, opBlock->getParent ()->getLoc ());
152
+ }
117
153
return true ;
118
154
}
119
155
@@ -141,6 +177,7 @@ bool OperationFolder::insertKnownConstant(Operation *op, Attribute constValue) {
141
177
// If there is an existing constant, replace `op`.
142
178
if (folderConstOp) {
143
179
notifyRemoval (op);
180
+ appendFoldedLocation (folderConstOp, op->getLoc ());
144
181
rewriter.replaceOp (op, folderConstOp->getResults ());
145
182
return false ;
146
183
}
@@ -151,8 +188,10 @@ bool OperationFolder::insertKnownConstant(Operation *op, Attribute constValue) {
151
188
// anything. Otherwise, we move the constant to the insertion block.
152
189
Block *insertBlock = &insertRegion->front ();
153
190
if (opBlock != insertBlock || (&insertBlock->front () != op &&
154
- !isFolderOwnedConstant (op->getPrevNode ())))
191
+ !isFolderOwnedConstant (op->getPrevNode ()))) {
155
192
op->moveBefore (&insertBlock->front ());
193
+ appendFoldedLocation (op, insertBlock->getParent ()->getLoc ());
194
+ }
156
195
157
196
folderConstOp = op;
158
197
referencedDialects[op].push_back (op->getDialect ());
@@ -264,8 +303,10 @@ OperationFolder::processFoldResults(Operation *op,
264
303
// with. This may not automatically happen if the operation being folded
265
304
// was inserted before the constant within the insertion block.
266
305
Block *opBlock = op->getBlock ();
267
- if (opBlock == constOp->getBlock () && &opBlock->front () != constOp)
306
+ if (opBlock == constOp->getBlock () && &opBlock->front () != constOp) {
268
307
constOp->moveBefore (&opBlock->front ());
308
+ appendFoldedLocation (constOp, opBlock->getParent ()->getLoc ());
309
+ }
269
310
270
311
results.push_back (constOp->getResult (0 ));
271
312
continue ;
@@ -294,8 +335,10 @@ OperationFolder::tryGetOrCreateConstant(ConstantMap &uniquedConstants,
294
335
// Check if an existing mapping already exists.
295
336
auto constKey = std::make_tuple (dialect, value, type);
296
337
Operation *&constOp = uniquedConstants[constKey];
297
- if (constOp)
338
+ if (constOp) {
339
+ appendFoldedLocation (constOp, loc);
298
340
return constOp;
341
+ }
299
342
300
343
// If one doesn't exist, try to materialize one.
301
344
if (!(constOp = materializeConstant (dialect, rewriter, value, type, loc)))
@@ -316,6 +359,7 @@ OperationFolder::tryGetOrCreateConstant(ConstantMap &uniquedConstants,
316
359
// materialized operation in favor of the existing one.
317
360
if (auto *existingOp = uniquedConstants.lookup (newKey)) {
318
361
notifyRemoval (constOp);
362
+ appendFoldedLocation (existingOp, constOp->getLoc ());
319
363
rewriter.eraseOp (constOp);
320
364
referencedDialects[existingOp].push_back (dialect);
321
365
return constOp = existingOp;
0 commit comments