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