@@ -100,13 +100,50 @@ void CopyPropagation::run() {
100
100
}
101
101
}
102
102
}
103
+ // Push copy_value instructions above their struct_extract operands by
104
+ // inserting destructures.
105
+ //
106
+ // copiedDefs be be modified, but it never shrinks
107
+ for (unsigned idx = 0 ; idx < copiedDefs.size (); ++idx) {
108
+ SILValue def = copiedDefs[idx];
109
+ auto *copy = dyn_cast<CopyValueInst>(def);
110
+ if (!copy)
111
+ continue ;
112
+
113
+ auto *extract = dyn_cast<StructExtractInst>(copy->getOperand ());
114
+ if (!extract
115
+ || SILValue (extract).getOwnershipKind () != OwnershipKind::Guaranteed)
116
+ continue ;
117
+
118
+ if (SILValue destructuredResult = convertExtractToDestructure (extract)) {
119
+ // Remove to-be-deleted instructions from copiedDeds. The extract cannot
120
+ // be in the copiedDefs set since getCanonicalCopiedDef does not allow a
121
+ // guaranteed projection to be a canonical def.
122
+ copiedDefs.remove (copy);
123
+ --idx; // point back to the current element, which was erased.
124
+
125
+ // TODO: unfortunately SetVector has no element replacement.
126
+ copiedDefs.insert (destructuredResult);
127
+
128
+ auto *destructure = cast<DestructureStructInst>(
129
+ destructuredResult.getDefiningInstruction ());
130
+ auto *newCopy = cast<CopyValueInst>(destructure->getOperand ());
131
+ copiedDefs.insert (
132
+ CanonicalizeOSSALifetime::getCanonicalCopiedDef (newCopy));
133
+
134
+ LLVM_DEBUG (llvm::dbgs () << " Destructure Conversion:\n "
135
+ << *extract << " to " << *destructure);
136
+ // Delete both the copy and the extract.
137
+ InstructionDeleter ().recursivelyDeleteUsersIfDead (extract);
138
+ }
139
+ }
103
140
// Perform copy propgation for each copied value.
104
141
CanonicalizeOSSALifetime canonicalizer (pruneDebug, poisonRefs,
105
142
accessBlockAnalysis,
106
143
dominanceAnalysis,
107
144
deBlocksAnalysis->get (f));
108
145
// Cleanup dead copies. If getCanonicalCopiedDef returns a copy (because the
109
- // copy's source operand is unrecgonized), then the copy is itself treated
146
+ // copy's source operand is unrecgonized), then thecan copy is itself treated
110
147
// like a def and may be dead after canonicalization.
111
148
llvm::SmallVector<CopyValueInst *, 4 > deadCopies;
112
149
for (auto &def : copiedDefs) {
0 commit comments