@@ -1291,45 +1291,59 @@ Operation *transform::TrackingListener::getCommonDefiningOp(ValueRange values) {
1291
1291
return defOp;
1292
1292
}
1293
1293
1294
- FailureOr<Operation *>
1295
- transform::TrackingListener::findReplacementOp (Operation *op,
1296
- ValueRange newValues) const {
1294
+ DiagnosedSilenceableFailure transform::TrackingListener::findReplacementOp (
1295
+ Operation *&result, Operation *op, ValueRange newValues) const {
1297
1296
assert (op->getNumResults () == newValues.size () &&
1298
1297
" invalid number of replacement values" );
1299
1298
SmallVector<Value> values (newValues.begin (), newValues.end ());
1300
1299
1300
+ DiagnosedSilenceableFailure diag = emitSilenceableFailure (
1301
+ getTransformOp (), " tracking listener failed to find replacement op "
1302
+ " during application of this transform op" );
1303
+
1301
1304
do {
1302
1305
// If the replacement values belong to different ops, drop the mapping.
1303
1306
Operation *defOp = getCommonDefiningOp (values);
1304
- if (!defOp)
1305
- return failure ();
1307
+ if (!defOp) {
1308
+ diag.attachNote () << " replacement values belong to different ops" ;
1309
+ return diag;
1310
+ }
1306
1311
1307
1312
// If the defining op has the same type, we take it as a replacement.
1308
- if (op->getName () == defOp->getName ())
1309
- return defOp;
1313
+ if (op->getName () == defOp->getName ()) {
1314
+ result = defOp;
1315
+ return DiagnosedSilenceableFailure::success ();
1316
+ }
1310
1317
1311
1318
// Replacing an op with a constant-like equivalent is a common
1312
1319
// canonicalization.
1313
- if (defOp->hasTrait <OpTrait::ConstantLike>())
1314
- return defOp;
1320
+ if (defOp->hasTrait <OpTrait::ConstantLike>()) {
1321
+ result = defOp;
1322
+ return DiagnosedSilenceableFailure::success ();
1323
+ }
1315
1324
1316
1325
values.clear ();
1317
1326
1318
1327
// Skip through ops that implement FindPayloadReplacementOpInterface.
1319
1328
if (auto findReplacementOpInterface =
1320
1329
dyn_cast<FindPayloadReplacementOpInterface>(defOp)) {
1321
1330
values.assign (findReplacementOpInterface.getNextOperands ());
1331
+ diag.attachNote (defOp->getLoc ()) << " using operands provided by "
1332
+ " 'FindPayloadReplacementOpInterface'" ;
1322
1333
continue ;
1323
1334
}
1324
1335
1325
1336
// Skip through ops that implement CastOpInterface.
1326
1337
if (isa<CastOpInterface>(defOp)) {
1327
1338
values.assign (defOp->getOperands ().begin (), defOp->getOperands ().end ());
1339
+ diag.attachNote (defOp->getLoc ())
1340
+ << " using output of 'CastOpInterface' op" ;
1328
1341
continue ;
1329
1342
}
1330
1343
} while (!values.empty ());
1331
1344
1332
- return failure ();
1345
+ diag.attachNote () << " ran out of suitable replacement values" ;
1346
+ return diag;
1333
1347
}
1334
1348
1335
1349
LogicalResult transform::TrackingListener::notifyMatchFailure (
@@ -1398,32 +1412,39 @@ void transform::TrackingListener::notifyOperationReplaced(
1398
1412
};
1399
1413
1400
1414
// Helper function to check if the handle is alive.
1401
- auto hasAliveUser = [&]() {
1415
+ auto firstAliveUser = [&]() -> std::optional<OpOperand *> {
1402
1416
for (Value v : opHandles) {
1403
- for (Operation *user : v.getUsers ())
1404
- if (user != transformOp && !happensBefore (user, transformOp))
1405
- return true ;
1417
+ for (OpOperand &use : v.getUses ())
1418
+ if (use.getOwner () != transformOp &&
1419
+ !happensBefore (use.getOwner (), transformOp))
1420
+ return &use;
1406
1421
}
1407
- return false ;
1408
- };
1422
+ return std::nullopt ;
1423
+ }() ;
1409
1424
1410
- if (!hasAliveUser () || handleWasConsumed ()) {
1425
+ if (!firstAliveUser. has_value () || handleWasConsumed ()) {
1411
1426
// The op is tracked but the corresponding handles are dead or were
1412
1427
// consumed. Drop the op form the mapping.
1413
1428
(void )replacePayloadOp (op, nullptr );
1414
1429
return ;
1415
1430
}
1416
1431
1417
- FailureOr<Operation *> replacement = findReplacementOp (op, newValues);
1432
+ Operation *replacement;
1433
+ DiagnosedSilenceableFailure diag =
1434
+ findReplacementOp (replacement, op, newValues);
1418
1435
// If the op is tracked but no replacement op was found, send a
1419
1436
// notification.
1420
- if (failed (replacement)) {
1421
- notifyPayloadReplacementNotFound (op, newValues);
1437
+ if (!diag.succeeded ()) {
1438
+ diag.attachNote ((*firstAliveUser)->getOwner ()->getLoc ())
1439
+ << " replacement is required because alive handle(s) exist "
1440
+ << " (first use in this op as operand number "
1441
+ << (*firstAliveUser)->getOperandNumber () << " )" ;
1442
+ notifyPayloadReplacementNotFound (op, newValues, std::move (diag));
1422
1443
(void )replacePayloadOp (op, nullptr );
1423
1444
return ;
1424
1445
}
1425
1446
1426
- (void )replacePayloadOp (op, * replacement);
1447
+ (void )replacePayloadOp (op, replacement);
1427
1448
}
1428
1449
1429
1450
transform::ErrorCheckingTrackingListener::~ErrorCheckingTrackingListener () {
@@ -1446,17 +1467,20 @@ bool transform::ErrorCheckingTrackingListener::failed() const {
1446
1467
}
1447
1468
1448
1469
void transform::ErrorCheckingTrackingListener::notifyPayloadReplacementNotFound (
1449
- Operation *op, ValueRange values) {
1450
- if (status.succeeded ()) {
1451
- status = emitSilenceableFailure (
1452
- getTransformOp (), " tracking listener failed to find replacement op" );
1453
- }
1470
+ Operation *op, ValueRange values, DiagnosedSilenceableFailure &&diag) {
1471
+
1472
+ // Merge potentially existing diags and store the result in the listener.
1473
+ SmallVector<Diagnostic> diags;
1474
+ diag.takeDiagnostics (diags);
1475
+ if (!status.succeeded ())
1476
+ status.takeDiagnostics (diags);
1477
+ status = DiagnosedSilenceableFailure::silenceableFailure (std::move (diags));
1454
1478
1479
+ // Report more details.
1455
1480
status.attachNote (op->getLoc ()) << " [" << errorCounter << " ] replaced op" ;
1456
1481
for (auto &&[index, value] : llvm::enumerate (values))
1457
1482
status.attachNote (value.getLoc ())
1458
1483
<< " [" << errorCounter << " ] replacement value " << index;
1459
-
1460
1484
++errorCounter;
1461
1485
}
1462
1486
0 commit comments