@@ -125,7 +125,9 @@ static void mapOperands(SILInstruction *inst,
125
125
static void updateSSAForUseOfValue (
126
126
SILSSAUpdater &updater, SmallVectorImpl<SILPhiArgument *> &insertedPhis,
127
127
const llvm::DenseMap<ValueBase *, SILValue> &valueMap,
128
- SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, SILValue Res) {
128
+ SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, SILValue Res,
129
+ SmallVectorImpl<std::pair<SILBasicBlock *, unsigned >>
130
+ &accumulatedAddressPhis) {
129
131
// Find the mapped instruction.
130
132
assert (valueMap.count (Res) && " Expected to find value in map!" );
131
133
SILValue MappedValue = valueMap.find (Res)->second ;
@@ -159,49 +161,96 @@ static void updateSSAForUseOfValue(
159
161
&& " The entry check block should dominate the header" );
160
162
updater.rewriteUse (*use);
161
163
}
162
- // Canonicalize inserted phis to avoid extra BB Args.
164
+
165
+ // Canonicalize inserted phis to avoid extra BB Args and if we find an address
166
+ // phi, stash it so we can handle it after we are done rewriting.
167
+ bool hasOwnership = Header->getParent ()->hasOwnership ();
163
168
for (SILPhiArgument *arg : insertedPhis) {
164
169
if (SILValue inst = replaceBBArgWithCast (arg)) {
165
170
arg->replaceAllUsesWith (inst);
166
171
// DCE+SimplifyCFG runs as a post-pass cleanup.
167
172
// DCE replaces dead arg values with undef.
168
173
// SimplifyCFG deletes the dead BB arg.
174
+ continue ;
169
175
}
176
+
177
+ // If we didn't simplify and have an address phi, stash the value so we can
178
+ // fix it up.
179
+ if (hasOwnership && arg->getType ().isAddress ())
180
+ accumulatedAddressPhis.emplace_back (arg->getParent (), arg->getIndex ());
170
181
}
171
182
}
172
183
173
- static void
174
- updateSSAForUseOfInst ( SILSSAUpdater &updater,
175
- SmallVectorImpl<SILPhiArgument * > &insertedPhis ,
176
- const llvm::DenseMap<ValueBase *, SILValue> &valueMap ,
177
- SILBasicBlock *header, SILBasicBlock *entryCheckBlock,
178
- SILInstruction *inst ) {
184
+ static void updateSSAForUseOfInst (
185
+ SILSSAUpdater &updater, SmallVectorImpl<SILPhiArgument *> &insertedPhis ,
186
+ const llvm::DenseMap<ValueBase *, SILValue > &valueMap ,
187
+ SILBasicBlock *header, SILBasicBlock *entryCheckBlock, SILInstruction *inst ,
188
+ SmallVectorImpl<std::pair< SILBasicBlock *, unsigned >>
189
+ &accumulatedAddressPhis ) {
179
190
for (auto result : inst->getResults ())
180
191
updateSSAForUseOfValue (updater, insertedPhis, valueMap, header,
181
- entryCheckBlock, result);
192
+ entryCheckBlock, result, accumulatedAddressPhis );
182
193
}
183
194
184
195
// / Rewrite the code we just created in the preheader and update SSA form.
185
196
static void rewriteNewLoopEntryCheckBlock (
186
197
SILBasicBlock *header, SILBasicBlock *entryCheckBlock,
187
198
const llvm::DenseMap<ValueBase *, SILValue> &valueMap) {
188
- SmallVector<SILPhiArgument *, 4 > insertedPhis;
199
+ SmallVector<std::pair<SILBasicBlock *, unsigned >, 8 > accumulatedAddressPhis;
200
+ SmallVector<SILPhiArgument *, 8 > insertedPhis;
189
201
SILSSAUpdater updater (&insertedPhis);
190
202
191
- // Fix PHIs (incoming arguments).
192
- for (auto *arg : header->getArguments ())
203
+ // Fix PHIs (incoming arguments). We iterate by index in case we replace the
204
+ // phi argument so we do not invalidate iterators.
205
+ for (unsigned i : range (header->getNumArguments ())) {
206
+ auto *arg = header->getArguments ()[i];
193
207
updateSSAForUseOfValue (updater, insertedPhis, valueMap, header,
194
- entryCheckBlock, arg);
208
+ entryCheckBlock, arg, accumulatedAddressPhis);
209
+ }
195
210
196
211
auto instIter = header->begin ();
197
212
198
213
// The terminator might change from under us.
199
214
while (instIter != header->end ()) {
200
215
auto &inst = *instIter;
201
216
updateSSAForUseOfInst (updater, insertedPhis, valueMap, header,
202
- entryCheckBlock, &inst);
217
+ entryCheckBlock, &inst, accumulatedAddressPhis );
203
218
++instIter;
204
219
}
220
+
221
+ // Then see if any of our phis were address phis. In such a case, rewrite the
222
+ // address to be a smuggled through raw pointer. We do this late to
223
+ // conservatively not interfere with the previous code's invariants.
224
+ //
225
+ // We also translate the phis into a BasicBlock, Index form so we are careful
226
+ // with invalidation issues around branches/args.
227
+ auto rawPointerTy =
228
+ SILType::getRawPointerType (header->getParent ()->getASTContext ());
229
+ auto rawPointerUndef = SILUndef::get (rawPointerTy, header->getModule ());
230
+ auto loc = RegularLocation::getAutoGeneratedLocation ();
231
+ while (!accumulatedAddressPhis.empty ()) {
232
+ SILBasicBlock *block;
233
+ unsigned argIndex;
234
+ std::tie (block, argIndex) = accumulatedAddressPhis.pop_back_val ();
235
+ auto *arg = cast<SILPhiArgument>(block->getArgument (argIndex));
236
+ assert (arg->getType ().isAddress () && " Not an address phi?!" );
237
+ for (auto *predBlock : block->getPredecessorBlocks ()) {
238
+ Operand *predUse = arg->getIncomingPhiOperand (predBlock);
239
+ SILBuilderWithScope builder (predUse->getUser ());
240
+ auto *newIncomingValue =
241
+ builder.createAddressToPointer (loc, predUse->get (), rawPointerTy);
242
+ predUse->set (newIncomingValue);
243
+ }
244
+ SILBuilderWithScope builder (arg->getNextInstruction ());
245
+ SILType oldArgType = arg->getType ();
246
+ auto *phiShim = builder.createPointerToAddress (
247
+ loc, rawPointerUndef, oldArgType, true /* isStrict*/ ,
248
+ false /* is invariant*/ );
249
+ arg->replaceAllUsesWith (phiShim);
250
+ SILArgument *newArg = block->replacePhiArgument (
251
+ argIndex, rawPointerTy, OwnershipKind::None, nullptr );
252
+ phiShim->setOperand (newArg);
253
+ }
205
254
}
206
255
207
256
// / Update the dominator tree after rotating the loop.
0 commit comments