Skip to content

Commit d9a1483

Browse files
committed
Add a simple AccessUseDefChainCloner.
1 parent c2b13cd commit d9a1483

File tree

2 files changed

+83
-10
lines changed

2 files changed

+83
-10
lines changed

include/swift/SIL/MemAccessUtils.h

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1368,7 +1368,7 @@ class AccessUseDefChainVisitor {
13681368
// Result visitNonAccess(SILValue base);
13691369
// Result visitPhi(SILPhiArgument *phi);
13701370
// Result visitStorageCast(SingleValueInstruction *cast, Operand *sourceOper);
1371-
// Result visitAccessProjection(SingleValueInstruction *cast,
1371+
// Result visitAccessProjection(SingleValueInstruction *projectedAddr,
13721372
// Operand *sourceOper);
13731373

13741374
Result visit(SILValue sourceAddr);
@@ -1479,6 +1479,82 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
14791479

14801480
} // end namespace swift
14811481

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+
14821558
//===----------------------------------------------------------------------===//
14831559
// MARK: Verification
14841560
//===----------------------------------------------------------------------===//

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,13 @@ class AccessPhiVisitor
122122
phiArg->getIncomingPhiValues(pointerWorklist);
123123
}
124124

125-
void visitStorageCast(SingleValueInstruction *projectedAddr,
126-
Operand *sourceOper) {
125+
void visitStorageCast(SingleValueInstruction *cast, Operand *sourceOper) {
127126
// Allow conversions to/from pointers and addresses on disjoint phi paths
128127
// only if the underlying useDefVisitor allows it.
129128
if (storageCastTy == IgnoreStorageCast)
130129
pointerWorklist.push_back(sourceOper->get());
131130
else
132-
visitNonAccess(projectedAddr);
131+
visitNonAccess(cast);
133132
}
134133

135134
void visitAccessProjection(SingleValueInstruction *projectedAddr,
@@ -207,8 +206,7 @@ class FindAccessVisitorImpl : public AccessUseDefChainVisitor<Impl, SILValue> {
207206
return this->asImpl().visitNonAccess(phiArg);
208207
}
209208

210-
SILValue visitStorageCast(SingleValueInstruction *projectedAddr,
211-
Operand *sourceAddr) {
209+
SILValue visitStorageCast(SingleValueInstruction *, Operand *sourceAddr) {
212210
assert(storageCastTy == IgnoreStorageCast);
213211
return sourceAddr->get();
214212
}
@@ -303,12 +301,11 @@ class FindAccessBaseVisitor
303301
}
304302

305303
// Override visitStorageCast to avoid seeing through arbitrary address casts.
306-
SILValue visitStorageCast(SingleValueInstruction *projectedAddr,
307-
Operand *sourceAddr) {
304+
SILValue visitStorageCast(SingleValueInstruction *cast, Operand *sourceAddr) {
308305
if (storageCastTy == StopAtStorageCast)
309-
return visitNonAccess(projectedAddr);
306+
return visitNonAccess(cast);
310307

311-
return SuperTy::visitStorageCast(projectedAddr, sourceAddr);
308+
return SuperTy::visitStorageCast(cast, sourceAddr);
312309
}
313310
};
314311

0 commit comments

Comments
 (0)