@@ -1368,7 +1368,7 @@ class AccessUseDefChainVisitor {
1368
1368
// Result visitNonAccess(SILValue base);
1369
1369
// Result visitPhi(SILPhiArgument *phi);
1370
1370
// Result visitStorageCast(SingleValueInstruction *cast, Operand *sourceOper);
1371
- // Result visitAccessProjection(SingleValueInstruction *cast ,
1371
+ // Result visitAccessProjection(SingleValueInstruction *projectedAddr ,
1372
1372
// Operand *sourceOper);
1373
1373
1374
1374
Result visit (SILValue sourceAddr);
@@ -1479,6 +1479,82 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
1479
1479
1480
1480
} // end namespace swift
1481
1481
1482
+ // ===----------------------------------------------------------------------===//
1483
+ // AccessUseDefChainCloner
1484
+ // ===----------------------------------------------------------------------===//
1485
+
1486
+ namespace swift {
1487
+
1488
+ // / Clone all projections and casts on the access use-def chain until either the
1489
+ // / specified predicate is true or the access base is reached.
1490
+ // /
1491
+ // / This will not clone ref_element_addr or ref_tail_addr because those aren't
1492
+ // / part of the access chain.
1493
+ template <typename UnaryPredicate>
1494
+ class AccessUseDefChainCloner
1495
+ : public AccessUseDefChainVisitor<AccessUseDefChainCloner<UnaryPredicate>,
1496
+ SILValue> {
1497
+ UnaryPredicate predicate;
1498
+ SILInstruction *insertionPoint;
1499
+
1500
+ public:
1501
+ AccessUseDefChainCloner (UnaryPredicate predicate,
1502
+ SILInstruction *insertionPoint)
1503
+ : predicate(predicate), insertionPoint(insertionPoint) {}
1504
+
1505
+ // Recursive main entry point
1506
+ SILValue cloneUseDefChain (SILValue addr) {
1507
+ if (!predicate (addr))
1508
+ return addr;
1509
+
1510
+ return this ->visit (addr);
1511
+ }
1512
+
1513
+ // Recursively clone an address on the use-def chain.
1514
+ SingleValueInstruction *cloneProjection (SingleValueInstruction *projectedAddr,
1515
+ Operand *sourceOper) {
1516
+ SILValue projectedSource = cloneUseDefChain (sourceOper->get ());
1517
+ SILInstruction *clone = projectedAddr->clone (insertionPoint);
1518
+ clone->setOperand (sourceOper->getOperandNumber (), projectedSource);
1519
+ return cast<SingleValueInstruction>(clone);
1520
+ }
1521
+
1522
+ // MARK: Visitor implementation
1523
+
1524
+ SILValue visitBase (SILValue base, AccessedStorage::Kind kind) {
1525
+ assert (false && " access base cannot be cloned" );
1526
+ }
1527
+
1528
+ SILValue visitNonAccess (SILValue base) {
1529
+ assert (false && " unknown address root cannot be cloned" );
1530
+ return SILValue ();
1531
+ }
1532
+
1533
+ SILValue visitPhi (SILPhiArgument *phi) {
1534
+ assert (false && " unexpected phi on access path" );
1535
+ return SILValue ();
1536
+ }
1537
+
1538
+ SILValue visitStorageCast (SingleValueInstruction *cast, Operand *sourceOper) {
1539
+ return cloneProjection (cast, sourceOper);
1540
+ }
1541
+
1542
+ SILValue visitAccessProjection (SingleValueInstruction *projectedAddr,
1543
+ Operand *sourceOper) {
1544
+ return cloneProjection (projectedAddr, sourceOper);
1545
+ }
1546
+ };
1547
+
1548
+ template <typename UnaryPredicate>
1549
+ SILValue cloneUseDefChain (SILValue addr, SILInstruction *insertionPoint,
1550
+ UnaryPredicate shouldFollowUse) {
1551
+ return AccessUseDefChainCloner<UnaryPredicate>(shouldFollowUse,
1552
+ insertionPoint)
1553
+ .cloneUseDefChain (addr);
1554
+ }
1555
+
1556
+ } // end namespace swift
1557
+
1482
1558
// ===----------------------------------------------------------------------===//
1483
1559
// MARK: Verification
1484
1560
// ===----------------------------------------------------------------------===//
0 commit comments