@@ -49,43 +49,59 @@ class GenericSpecializer : public SILFunctionTransform {
49
49
50
50
bool GenericSpecializer::specializeAppliesInFunction (SILFunction &F) {
51
51
DeadInstructionSet DeadApplies;
52
+ llvm::SmallSetVector<SILInstruction *, 8 > Applies;
52
53
54
+ bool Changed = false ;
53
55
for (auto &BB : F) {
54
- for (auto It = BB.begin (), End = BB.end (); It != End;) {
55
- auto &I = *It++;
56
+ // Collect the applies for this block in reverse order so that we
57
+ // can pop them off the end of our vector and process them in
58
+ // forward order.
59
+ for (auto It = BB.rbegin (), End = BB.rend (); It != End; ++It) {
60
+ auto *I = &*It;
56
61
57
62
// Skip non-apply instructions, apply instructions with no
58
63
// substitutions, apply instructions where we do not statically
59
64
// know the called function, and apply instructions where we do
60
65
// not have the body of the called function.
61
-
62
- ApplySite Apply = ApplySite::isa (&I);
66
+ ApplySite Apply = ApplySite::isa (I);
63
67
if (!Apply || !Apply.hasSubstitutions ())
64
68
continue ;
65
69
66
70
auto *Callee = Apply.getReferencedFunction ();
67
71
if (!Callee || !Callee->isDefinition ())
68
72
continue ;
69
73
70
- // Do not attempt to specialize known dead instructions. Doing
71
- // so would be a waste of time (since they are unused), and can
72
- // also lead to verification errors on the newly created
73
- // apply. This can happen in the case of a partial application
74
- // of a reabstraction thunk where we have done an RAUW on the
75
- // reabstracted function (which is an argument of the partial
76
- // apply). In this case we add the partial apply of the
77
- // reabstraction thunk to the set of dead applies, but its
78
- // arguments types do not match the expected types of the
79
- // argument that has been RAUWed into it.
80
- if (DeadApplies.count (Apply.getInstruction ()))
81
- continue ;
74
+ Applies.insert (Apply.getInstruction ());
75
+ }
76
+
77
+ // Attempt to specialize each apply we collected, deleting any
78
+ // that we do specialize (along with other instructions we clone
79
+ // in the process of doing so). We pop from the end of the list to
80
+ // avoid tricky iterator invalidation issues.
81
+ while (!Applies.empty ()) {
82
+ auto *I = Applies.pop_back_val ();
83
+ auto Apply = ApplySite::isa (I);
84
+ assert (Apply && " Expected an apply!" );
82
85
83
86
// We have a call that can potentially be specialized, so
84
87
// attempt to do so.
85
-
86
88
llvm::SmallVector<SILFunction *, 2 > NewFunctions;
87
89
trySpecializeApplyOfGeneric (Apply, DeadApplies, NewFunctions);
88
90
91
+ // Remove all the now-dead applies. We must do this immediately
92
+ // rather than defer it in order to avoid problems with cloning
93
+ // dead instructions when doing recursive specialization.
94
+ while (!DeadApplies.empty ()) {
95
+ auto *AI = DeadApplies.pop_back_val ();
96
+
97
+ // Remove any applies we are deleting so that we don't attempt
98
+ // to specialize them.
99
+ Applies.remove (AI);
100
+
101
+ recursivelyDeleteTriviallyDeadInstructions (AI, true );
102
+ Changed = true ;
103
+ }
104
+
89
105
// If calling the specialization utility resulted in new functions
90
106
// (as opposed to returning a previous specialization), we need to notify
91
107
// the pass manager so that the new functions get optimized.
@@ -95,14 +111,6 @@ bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) {
95
111
}
96
112
}
97
113
98
- // Remove all the now-dead applies.
99
- bool Changed = false ;
100
- while (!DeadApplies.empty ()) {
101
- auto *AI = DeadApplies.pop_back_val ();
102
- recursivelyDeleteTriviallyDeadInstructions (AI, true );
103
- Changed = true ;
104
- }
105
-
106
114
return Changed;
107
115
}
108
116
0 commit comments