@@ -65,49 +65,66 @@ 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 ;
106
112
moves.push_back (inst);
107
113
invariants.insert (inst);
108
- } else {
109
- cost += (int )instructionInlineCost (instRef);
114
+ continue ;
110
115
}
116
+ if (!inst->mayHaveSideEffects () && !inst->mayReadFromMemory () &&
117
+ !isa<TermInst>(inst) && /* not marked mayhavesideffects */
118
+ hasLoopInvariantOperands (inst, loop, invariants)) {
119
+ moves.push_back (inst);
120
+ invariants.insert (inst);
121
+ continue ;
122
+ }
123
+ if (!sinkProj.analyzeAddressProjections (inst)) {
124
+ return false ;
125
+ }
126
+
127
+ cost += (int )instructionInlineCost (instRef);
111
128
}
112
129
113
130
return cost < LoopRotateSizeLimit;
@@ -378,8 +395,9 @@ bool swift::rotateLoop(SILLoop *loop, DominanceInfo *domInfo,
378
395
379
396
// Make sure we can duplicate the header.
380
397
SmallVector<SILInstruction *, 8 > moveToPreheader;
381
- if (!canDuplicateOrMoveToPreheader (loop, preheader, header,
382
- moveToPreheader)) {
398
+ SinkAddressProjections sinkProj;
399
+ if (!canDuplicateOrMoveToPreheader (loop, preheader, header, moveToPreheader,
400
+ sinkProj)) {
383
401
LLVM_DEBUG (llvm::dbgs ()
384
402
<< *loop << " instructions in header preventing rotating\n " );
385
403
return false ;
@@ -425,6 +443,14 @@ bool swift::rotateLoop(SILLoop *loop, DominanceInfo *domInfo,
425
443
426
444
// The other instructions are just cloned to the preheader.
427
445
TermInst *preheaderBranch = preheader->getTerminator ();
446
+
447
+ // sink address projections to avoid address phis.
448
+ for (auto &inst : *header) {
449
+ bool success = sinkProj.analyzeAddressProjections (&inst);
450
+ assert (success);
451
+ sinkProj.cloneProjections ();
452
+ }
453
+
428
454
for (auto &inst : *header) {
429
455
if (SILInstruction *cloned = inst.clone (preheaderBranch)) {
430
456
mapOperands (cloned, valueMap);
@@ -488,16 +514,10 @@ namespace {
488
514
class LoopRotation : public SILFunctionTransform {
489
515
490
516
void run () override {
517
+ SILFunction *f = getFunction ();
491
518
SILLoopAnalysis *loopAnalysis = PM->getAnalysis <SILLoopAnalysis>();
492
- assert (loopAnalysis);
493
519
DominanceAnalysis *domAnalysis = PM->getAnalysis <DominanceAnalysis>();
494
- assert (domAnalysis);
495
-
496
- SILFunction *f = getFunction ();
497
- assert (f);
498
-
499
520
SILLoopInfo *loopInfo = loopAnalysis->get (f);
500
- assert (loopInfo);
501
521
DominanceInfo *domInfo = domAnalysis->get (f);
502
522
503
523
if (loopInfo->empty ()) {
0 commit comments