@@ -1174,7 +1174,7 @@ IRVar* emitIndexedLocalVar(
1174
1174
SourceLoc location)
1175
1175
{
1176
1176
// Cannot store pointers. Case should have been handled by now.
1177
- SLANG_RELEASE_ASSERT (!as<IRPtrTypeBase> (baseType));
1177
+ SLANG_RELEASE_ASSERT (!asRelevantPtrType (baseType));
1178
1178
1179
1179
// Cannot store types. Case should have been handled by now.
1180
1180
SLANG_RELEASE_ASSERT (!as<IRTypeType>(baseType));
@@ -1326,7 +1326,11 @@ static int getInstRegionNestLevel(
1326
1326
1327
1327
struct UseChain
1328
1328
{
1329
+ // The chain of uses from the base use to the relevant use.
1330
+ // However, this is stored in reverse order (so that the last use is the 'base use')
1331
+ //
1329
1332
List<IRUse*> chain;
1333
+
1330
1334
static List<UseChain> from (
1331
1335
IRUse* baseUse,
1332
1336
Func<bool , IRUse*> isRelevantUse,
@@ -1366,41 +1370,20 @@ struct UseChain
1366
1370
return result;
1367
1371
}
1368
1372
1369
- void replace (IROutOfOrderCloneContext* ctx, IRBuilder* builder, IRInst* inst)
1373
+ // This function only replaces the inner links, not the base use.
1374
+ void replaceInnerLinks (IROutOfOrderCloneContext* ctx, IRBuilder* builder)
1370
1375
{
1371
1376
SLANG_ASSERT (chain.getCount () > 0 );
1372
1377
1373
- // Simple case: if there is only one use, then we can just replace it.
1374
- if (chain.getCount () == 1 )
1375
- {
1376
- builder->replaceOperand (chain.getLast (), inst);
1377
- chain.clear ();
1378
- return ;
1379
- }
1380
-
1381
- // Pop the last use, which is the base use that needs to be replaced.
1382
- auto baseUse = chain.getLast ();
1383
- chain.removeLast ();
1378
+ const UIndex count = chain.getCount ();
1384
1379
1385
- // Ensure that replacement inst is set as mapping for the baseUse.
1386
- ctx->cloneEnv .mapOldValToNew [baseUse->get ()] = inst;
1387
-
1388
- IRBuilder chainBuilder (builder->getModule ());
1389
- setInsertAfterOrdinaryInst (&chainBuilder, inst);
1390
-
1391
- chain.reverse ();
1392
- chain.removeLast ();
1393
-
1394
- // Clone the rest of the chain.
1395
- for (auto & use : chain)
1380
+ // Process the chain in reverse order (excluding the first and last elements).
1381
+ // That is, iterate from count - 2 down to 1 (inclusive).
1382
+ for (int i = ((int )count) - 2 ; i >= 1 ; i--)
1396
1383
{
1397
- ctx->cloneInstOutOfOrder (&chainBuilder, use->get ());
1384
+ IRUse* use = chain[i];
1385
+ ctx->cloneInstOutOfOrder (builder, use->get ());
1398
1386
}
1399
-
1400
- // We won't actually replace the final use, because if there are multiple chains
1401
- // it can cause problems. The parent UseGraph will handle that.
1402
-
1403
- chain.clear ();
1404
1387
}
1405
1388
1406
1389
IRInst* getUser () const
@@ -1417,6 +1400,14 @@ struct UseGraph
1417
1400
//
1418
1401
OrderedDictionary<IRUse*, List<UseChain>> chainSets;
1419
1402
1403
+ // Create a UseGraph from a base inst.
1404
+ //
1405
+ // `isRelevantUse` is a predicate that determines if a use is relevant. Traversal will stop at
1406
+ // this use, and all chains to this use will be grouped together.
1407
+ //
1408
+ // `passthroughInst` is a predicate that determines if an inst should be looked through
1409
+ // for uses.
1410
+ //
1420
1411
static UseGraph from (
1421
1412
IRInst* baseInst,
1422
1413
Func<bool , IRUse*> isRelevantUse,
@@ -1445,36 +1436,33 @@ struct UseGraph
1445
1436
return result;
1446
1437
}
1447
1438
1448
- void replace (IRBuilder* builder, IRUse* use , IRInst* inst)
1439
+ void replace (IRBuilder* builder, IRUse* relevantUse , IRInst* inst)
1449
1440
{
1450
1441
// Since we may have common nodes, we will use an out-of-order cloning context
1451
1442
// that can retroactively correct the uses as needed.
1452
1443
//
1453
1444
IROutOfOrderCloneContext ctx;
1454
- List<UseChain> chains = chainSets[use];
1455
- for (auto chain : chains)
1456
- {
1457
- chain.replace (&ctx, builder, inst);
1458
- }
1445
+ List<UseChain> chains = chainSets[relevantUse];
1459
1446
1460
- if (!isTrivial ())
1447
+ // Link the first use of each chain to inst.
1448
+ for (auto & chain : chains)
1449
+ ctx.cloneEnv .mapOldValToNew [chain.chain .getLast ()->get ()] = inst;
1450
+
1451
+ // Process the inner links of each chain using the replacement.
1452
+ for (auto & chain : chains)
1461
1453
{
1462
- builder->setInsertBefore (use-> getUser ());
1463
- auto lastInstInChain = ctx. cloneInstOutOfOrder (builder, use-> get () );
1454
+ IRBuilder chainBuilder ( builder->getModule ());
1455
+ setInsertAfterOrdinaryInst (&chainBuilder, inst );
1464
1456
1465
- // Replace the base use.
1466
- builder->replaceOperand (use, lastInstInChain);
1457
+ chain.replaceInnerLinks (&ctx, builder);
1467
1458
}
1468
- }
1469
1459
1470
- bool isTrivial ()
1471
- {
1472
- // We're trivial if there's only one chain, and it has only one use.
1473
- if (chainSets.getCount () != 1 )
1474
- return false ;
1460
+ // Finally, replace the relevant use (i.e, "final use") with the new replacement inst.
1461
+ builder->setInsertBefore (relevantUse->getUser ());
1462
+ auto lastInstInChain = ctx.cloneInstOutOfOrder (builder, relevantUse->get ());
1475
1463
1476
- auto & chain = chainSets. getFirst (). value ;
1477
- return chain. getCount () == 1 ;
1464
+ // Replace the base use.
1465
+ builder-> replaceOperand (relevantUse, lastInstInChain) ;
1478
1466
}
1479
1467
1480
1468
List<IRUse*> getUniqueUses () const
@@ -1668,7 +1656,7 @@ RefPtr<HoistedPrimalsInfo> ensurePrimalAvailability(
1668
1656
return true ;
1669
1657
}
1670
1658
else if (
1671
- as<IRPtrTypeBase> (instToStore->getDataType ()) &&
1659
+ asRelevantPtrType (instToStore->getDataType ()) &&
1672
1660
!isDifferentialOrRecomputeBlock (defBlock))
1673
1661
{
1674
1662
return true ;
0 commit comments