@@ -65,49 +65,67 @@ hasLoopInvariantOperands(SILInstruction *inst, SILLoop *loop,
65
65
static bool
66
66
canDuplicateOrMoveToPreheader (SILLoop *loop, SILBasicBlock *preheader,
67
67
SILBasicBlock *bb,
68
- SmallVectorImpl<SILInstruction *> &moves) {
68
+ SmallVectorImpl<SILInstruction *> &moves,
69
+ SinkAddressProjections &sinkProj) {
69
70
llvm::DenseSet<SILInstruction *> invariants;
70
71
int cost = 0 ;
71
72
for (auto &instRef : *bb) {
72
- OwnershipForwardingMixin *ofm = nullptr ;
73
73
auto *inst = &instRef;
74
- if (auto *MI = dyn_cast<MethodInst>(inst)) {
75
- if (MI->getMember ().isForeign )
76
- return false ;
77
- if (!hasLoopInvariantOperands (inst, loop, invariants))
78
- continue ;
79
- moves.push_back (inst);
80
- invariants.insert (inst);
81
- } else if (!inst->isTriviallyDuplicatable ())
74
+ if (!inst->isTriviallyDuplicatable ()) {
82
75
return false ;
76
+ }
83
77
// It wouldn't make sense to rotate dealloc_stack without also rotating the
84
78
// alloc_stack, which is covered by isTriviallyDuplicatable.
85
- else if (isa<DeallocStackInst>(inst))
79
+ if (isa<DeallocStackInst>(inst)) {
80
+ return false ;
81
+ }
82
+ OwnershipForwardingMixin *ofm = nullptr ;
83
+ if ((ofm = OwnershipForwardingMixin::get (inst)) &&
84
+ ofm->getForwardingOwnershipKind () == OwnershipKind::Guaranteed) {
86
85
return false ;
87
- else if (isa<FunctionRefInst>(inst)) {
86
+ }
87
+ if (isa<FunctionRefInst>(inst)) {
88
88
moves.push_back (inst);
89
89
invariants.insert (inst);
90
- } else if (isa<DynamicFunctionRefInst>(inst)) {
90
+ continue ;
91
+ }
92
+ if (isa<DynamicFunctionRefInst>(inst)) {
91
93
moves.push_back (inst);
92
94
invariants.insert (inst);
93
- } else if (isa<PreviousDynamicFunctionRefInst>(inst)) {
95
+ continue ;
96
+ }
97
+ if (isa<PreviousDynamicFunctionRefInst>(inst)) {
94
98
moves.push_back (inst);
95
99
invariants.insert (inst);
96
- } else if (isa<IntegerLiteralInst>(inst)) {
100
+ continue ;
101
+ }
102
+ if (isa<IntegerLiteralInst>(inst)) {
97
103
moves.push_back (inst);
98
104
invariants.insert (inst);
99
- } else if ((ofm = OwnershipForwardingMixin::get (inst)) &&
100
- ofm->getForwardingOwnershipKind () == OwnershipKind::Guaranteed) {
101
- return false ;
102
- } else if (!inst->mayHaveSideEffects () && !inst->mayReadFromMemory ()
103
- && !isa<TermInst>(inst) && !isa<AllocationInst>(inst)
104
- && /* not marked mayhavesideffects */
105
- hasLoopInvariantOperands (inst, loop, invariants)) {
105
+ continue ;
106
+ }
107
+ if (auto *MI = dyn_cast<MethodInst>(inst)) {
108
+ if (MI->getMember ().isForeign )
109
+ return false ;
110
+ if (!hasLoopInvariantOperands (inst, loop, invariants))
111
+ continue ;
112
+ moves.push_back (inst);
113
+ invariants.insert (inst);
114
+ continue ;
115
+ }
116
+ if (!inst->mayHaveSideEffects () && !inst->mayReadFromMemory () &&
117
+ !isa<TermInst>(inst) &&
118
+ !isa<AllocationInst>(inst) && /* not marked mayhavesideffects */
119
+ hasLoopInvariantOperands (inst, loop, invariants)) {
106
120
moves.push_back (inst);
107
121
invariants.insert (inst);
108
- } else {
109
- cost += (int )instructionInlineCost (instRef);
122
+ continue ;
123
+ }
124
+ if (!sinkProj.analyzeAddressProjections (inst)) {
125
+ return false ;
110
126
}
127
+
128
+ cost += (int )instructionInlineCost (instRef);
111
129
}
112
130
113
131
return cost < LoopRotateSizeLimit;
@@ -129,9 +147,7 @@ static void mapOperands(SILInstruction *inst,
129
147
static void updateSSAForUseOfValue (
130
148
SILSSAUpdater &updater, SmallVectorImpl<SILPhiArgument *> &insertedPhis,
131
149
const llvm::DenseMap<ValueBase *, SILValue> &valueMap,
132
- SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, SILValue Res,
133
- SmallVectorImpl<std::pair<SILBasicBlock *, unsigned >>
134
- &accumulatedAddressPhis) {
150
+ SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, SILValue Res) {
135
151
// Find the mapped instruction.
136
152
assert (valueMap.count (Res) && " Expected to find value in map!" );
137
153
SILValue MappedValue = valueMap.find (Res)->second ;
@@ -161,14 +177,13 @@ static void updateSSAForUseOfValue(
161
177
if (user->getParent () == Header)
162
178
continue ;
163
179
164
- assert (user->getParent () != EntryCheckBlock
165
- && " The entry check block should dominate the header" );
180
+ assert (user->getParent () != EntryCheckBlock &&
181
+ " The entry check block should dominate the header" );
166
182
updater.rewriteUse (*use);
167
183
}
168
184
169
185
// Canonicalize inserted phis to avoid extra BB Args and if we find an address
170
186
// phi, stash it so we can handle it after we are done rewriting.
171
- bool hasOwnership = Header->getParent ()->hasOwnership ();
172
187
for (SILPhiArgument *arg : insertedPhis) {
173
188
if (SILValue inst = replaceBBArgWithCast (arg)) {
174
189
arg->replaceAllUsesWith (inst);
@@ -177,30 +192,24 @@ static void updateSSAForUseOfValue(
177
192
// SimplifyCFG deletes the dead BB arg.
178
193
continue ;
179
194
}
180
-
181
- // If we didn't simplify and have an address phi, stash the value so we can
182
- // fix it up.
183
- if (hasOwnership && arg->getType ().isAddress ())
184
- accumulatedAddressPhis.emplace_back (arg->getParent (), arg->getIndex ());
185
195
}
186
196
}
187
197
188
- static void updateSSAForUseOfInst (
189
- SILSSAUpdater &updater, SmallVectorImpl<SILPhiArgument *> &insertedPhis ,
190
- const llvm::DenseMap<ValueBase *, SILValue > &valueMap ,
191
- SILBasicBlock *header, SILBasicBlock *entryCheckBlock, SILInstruction *inst ,
192
- SmallVectorImpl<std::pair< SILBasicBlock *, unsigned >>
193
- &accumulatedAddressPhis ) {
198
+ static void
199
+ updateSSAForUseOfInst ( SILSSAUpdater &updater,
200
+ SmallVectorImpl<SILPhiArgument * > &insertedPhis ,
201
+ const llvm::DenseMap<ValueBase *, SILValue> &valueMap ,
202
+ SILBasicBlock *header, SILBasicBlock *entryCheckBlock,
203
+ SILInstruction *inst ) {
194
204
for (auto result : inst->getResults ())
195
205
updateSSAForUseOfValue (updater, insertedPhis, valueMap, header,
196
- entryCheckBlock, result, accumulatedAddressPhis );
206
+ entryCheckBlock, result);
197
207
}
198
208
199
209
// / Rewrite the code we just created in the preheader and update SSA form.
200
210
static void rewriteNewLoopEntryCheckBlock (
201
211
SILBasicBlock *header, SILBasicBlock *entryCheckBlock,
202
212
const llvm::DenseMap<ValueBase *, SILValue> &valueMap) {
203
- SmallVector<std::pair<SILBasicBlock *, unsigned >, 8 > accumulatedAddressPhis;
204
213
SmallVector<SILPhiArgument *, 8 > insertedPhis;
205
214
SILSSAUpdater updater (&insertedPhis);
206
215
@@ -209,7 +218,7 @@ static void rewriteNewLoopEntryCheckBlock(
209
218
for (unsigned i : range (header->getNumArguments ())) {
210
219
auto *arg = header->getArguments ()[i];
211
220
updateSSAForUseOfValue (updater, insertedPhis, valueMap, header,
212
- entryCheckBlock, arg, accumulatedAddressPhis );
221
+ entryCheckBlock, arg);
213
222
}
214
223
215
224
auto instIter = header->begin ();
@@ -218,43 +227,9 @@ static void rewriteNewLoopEntryCheckBlock(
218
227
while (instIter != header->end ()) {
219
228
auto &inst = *instIter;
220
229
updateSSAForUseOfInst (updater, insertedPhis, valueMap, header,
221
- entryCheckBlock, &inst, accumulatedAddressPhis );
230
+ entryCheckBlock, &inst);
222
231
++instIter;
223
232
}
224
-
225
- // Then see if any of our phis were address phis. In such a case, rewrite the
226
- // address to be a smuggled through raw pointer. We do this late to
227
- // conservatively not interfere with the previous code's invariants.
228
- //
229
- // We also translate the phis into a BasicBlock, Index form so we are careful
230
- // with invalidation issues around branches/args.
231
- auto rawPointerTy =
232
- SILType::getRawPointerType (header->getParent ()->getASTContext ());
233
- auto rawPointerUndef = SILUndef::get (rawPointerTy, header->getModule ());
234
- auto loc = RegularLocation::getAutoGeneratedLocation ();
235
- while (!accumulatedAddressPhis.empty ()) {
236
- SILBasicBlock *block;
237
- unsigned argIndex;
238
- std::tie (block, argIndex) = accumulatedAddressPhis.pop_back_val ();
239
- auto *arg = cast<SILPhiArgument>(block->getArgument (argIndex));
240
- assert (arg->getType ().isAddress () && " Not an address phi?!" );
241
- for (auto *predBlock : block->getPredecessorBlocks ()) {
242
- Operand *predUse = arg->getIncomingPhiOperand (predBlock);
243
- SILBuilderWithScope builder (predUse->getUser ());
244
- auto *newIncomingValue =
245
- builder.createAddressToPointer (loc, predUse->get (), rawPointerTy);
246
- predUse->set (newIncomingValue);
247
- }
248
- SILBuilderWithScope builder (arg->getNextInstruction ());
249
- SILType oldArgType = arg->getType ();
250
- auto *phiShim = builder.createPointerToAddress (
251
- loc, rawPointerUndef, oldArgType, true /* isStrict*/ ,
252
- false /* is invariant*/ );
253
- arg->replaceAllUsesWith (phiShim);
254
- SILArgument *newArg = block->replacePhiArgument (
255
- argIndex, rawPointerTy, OwnershipKind::None, nullptr );
256
- phiShim->setOperand (newArg);
257
- }
258
233
}
259
234
260
235
// / Update the dominator tree after rotating the loop.
@@ -378,8 +353,9 @@ bool swift::rotateLoop(SILLoop *loop, DominanceInfo *domInfo,
378
353
379
354
// Make sure we can duplicate the header.
380
355
SmallVector<SILInstruction *, 8 > moveToPreheader;
381
- if (!canDuplicateOrMoveToPreheader (loop, preheader, header,
382
- moveToPreheader)) {
356
+ SinkAddressProjections sinkProj;
357
+ if (!canDuplicateOrMoveToPreheader (loop, preheader, header, moveToPreheader,
358
+ sinkProj)) {
383
359
LLVM_DEBUG (llvm::dbgs ()
384
360
<< *loop << " instructions in header preventing rotating\n " );
385
361
return false ;
@@ -425,6 +401,14 @@ bool swift::rotateLoop(SILLoop *loop, DominanceInfo *domInfo,
425
401
426
402
// The other instructions are just cloned to the preheader.
427
403
TermInst *preheaderBranch = preheader->getTerminator ();
404
+
405
+ // sink address projections to avoid address phis.
406
+ for (auto &inst : *header) {
407
+ bool success = sinkProj.analyzeAddressProjections (&inst);
408
+ assert (success);
409
+ sinkProj.cloneProjections ();
410
+ }
411
+
428
412
for (auto &inst : *header) {
429
413
if (SILInstruction *cloned = inst.clone (preheaderBranch)) {
430
414
mapOperands (cloned, valueMap);
@@ -488,16 +472,10 @@ namespace {
488
472
class LoopRotation : public SILFunctionTransform {
489
473
490
474
void run () override {
475
+ SILFunction *f = getFunction ();
491
476
SILLoopAnalysis *loopAnalysis = PM->getAnalysis <SILLoopAnalysis>();
492
- assert (loopAnalysis);
493
477
DominanceAnalysis *domAnalysis = PM->getAnalysis <DominanceAnalysis>();
494
- assert (domAnalysis);
495
-
496
- SILFunction *f = getFunction ();
497
- assert (f);
498
-
499
478
SILLoopInfo *loopInfo = loopAnalysis->get (f);
500
- assert (loopInfo);
501
479
DominanceInfo *domInfo = domAnalysis->get (f);
502
480
503
481
if (loopInfo->empty ()) {
0 commit comments