@@ -78,6 +78,11 @@ static cl::opt<unsigned> MaxClones(
78
78
" The maximum number of clones allowed for a single function "
79
79
" specialization" ));
80
80
81
+ static cl::opt<unsigned > MaxIncomingPhiValues (
82
+ " funcspec-max-incoming-phi-values" , cl::init(4 ), cl::Hidden, cl::desc(
83
+ " The maximum number of incoming values a PHI node can have to be "
84
+ " considered during the specialization bonus estimation" ));
85
+
81
86
static cl::opt<unsigned > MinFunctionSize (
82
87
" funcspec-min-function-size" , cl::init(100 ), cl::Hidden, cl::desc(
83
88
" Don't specialize functions that have less than this number of "
@@ -104,6 +109,7 @@ static cl::opt<bool> SpecializeLiteralConstant(
104
109
// the combination of size and latency savings in comparison to the non
105
110
// specialized version of the function.
106
111
static Cost estimateBasicBlocks (SmallVectorImpl<BasicBlock *> &WorkList,
112
+ DenseSet<BasicBlock *> &DeadBlocks,
107
113
ConstMap &KnownConstants, SCCPSolver &Solver,
108
114
BlockFrequencyInfo &BFI,
109
115
TargetTransformInfo &TTI) {
@@ -118,6 +124,12 @@ static Cost estimateBasicBlocks(SmallVectorImpl<BasicBlock *> &WorkList,
118
124
if (!Weight)
119
125
continue ;
120
126
127
+ // These blocks are considered dead as far as the InstCostVisitor is
128
+ // concerned. They haven't been proven dead yet by the Solver, but
129
+ // may become if we propagate the constant specialization arguments.
130
+ if (!DeadBlocks.insert (BB).second )
131
+ continue ;
132
+
121
133
for (Instruction &I : *BB) {
122
134
// Disregard SSA copies.
123
135
if (auto *II = dyn_cast<IntrinsicInst>(&I))
@@ -152,9 +164,19 @@ static Constant *findConstantFor(Value *V, ConstMap &KnownConstants) {
152
164
return nullptr ;
153
165
}
154
166
167
+ Cost InstCostVisitor::getBonusFromPendingPHIs () {
168
+ Cost Bonus = 0 ;
169
+ while (!PendingPHIs.empty ()) {
170
+ Instruction *Phi = PendingPHIs.pop_back_val ();
171
+ Bonus += getUserBonus (Phi);
172
+ }
173
+ return Bonus;
174
+ }
175
+
155
176
Cost InstCostVisitor::getUserBonus (Instruction *User, Value *Use, Constant *C) {
156
177
// Cache the iterator before visiting.
157
- LastVisited = KnownConstants.insert ({Use, C}).first ;
178
+ LastVisited = Use ? KnownConstants.insert ({Use, C}).first
179
+ : KnownConstants.end ();
158
180
159
181
if (auto *I = dyn_cast<SwitchInst>(User))
160
182
return estimateSwitchInst (*I);
@@ -181,13 +203,15 @@ Cost InstCostVisitor::getUserBonus(Instruction *User, Value *Use, Constant *C) {
181
203
182
204
for (auto *U : User->users ())
183
205
if (auto *UI = dyn_cast<Instruction>(U))
184
- if (Solver.isBlockExecutable (UI->getParent ()))
206
+ if (UI != User && Solver.isBlockExecutable (UI->getParent ()))
185
207
Bonus += getUserBonus (UI, User, C);
186
208
187
209
return Bonus;
188
210
}
189
211
190
212
Cost InstCostVisitor::estimateSwitchInst (SwitchInst &I) {
213
+ assert (LastVisited != KnownConstants.end () && " Invalid iterator!" );
214
+
191
215
if (I.getCondition () != LastVisited->first )
192
216
return 0 ;
193
217
@@ -208,10 +232,13 @@ Cost InstCostVisitor::estimateSwitchInst(SwitchInst &I) {
208
232
WorkList.push_back (BB);
209
233
}
210
234
211
- return estimateBasicBlocks (WorkList, KnownConstants, Solver, BFI, TTI);
235
+ return estimateBasicBlocks (WorkList, DeadBlocks, KnownConstants, Solver, BFI,
236
+ TTI);
212
237
}
213
238
214
239
Cost InstCostVisitor::estimateBranchInst (BranchInst &I) {
240
+ assert (LastVisited != KnownConstants.end () && " Invalid iterator!" );
241
+
215
242
if (I.getCondition () != LastVisited->first )
216
243
return 0 ;
217
244
@@ -223,10 +250,39 @@ Cost InstCostVisitor::estimateBranchInst(BranchInst &I) {
223
250
Succ->getUniquePredecessor () == I.getParent ())
224
251
WorkList.push_back (Succ);
225
252
226
- return estimateBasicBlocks (WorkList, KnownConstants, Solver, BFI, TTI);
253
+ return estimateBasicBlocks (WorkList, DeadBlocks, KnownConstants, Solver, BFI,
254
+ TTI);
255
+ }
256
+
257
+ Constant *InstCostVisitor::visitPHINode (PHINode &I) {
258
+ if (I.getNumIncomingValues () > MaxIncomingPhiValues)
259
+ return nullptr ;
260
+
261
+ bool Inserted = VisitedPHIs.insert (&I).second ;
262
+ Constant *Const = nullptr ;
263
+
264
+ for (unsigned Idx = 0 , E = I.getNumIncomingValues (); Idx != E; ++Idx) {
265
+ Value *V = I.getIncomingValue (Idx);
266
+ if (auto *Inst = dyn_cast<Instruction>(V))
267
+ if (Inst == &I || DeadBlocks.contains (I.getIncomingBlock (Idx)))
268
+ continue ;
269
+ Constant *C = findConstantFor (V, KnownConstants);
270
+ if (!C) {
271
+ if (Inserted)
272
+ PendingPHIs.push_back (&I);
273
+ return nullptr ;
274
+ }
275
+ if (!Const)
276
+ Const = C;
277
+ else if (C != Const)
278
+ return nullptr ;
279
+ }
280
+ return Const;
227
281
}
228
282
229
283
Constant *InstCostVisitor::visitFreezeInst (FreezeInst &I) {
284
+ assert (LastVisited != KnownConstants.end () && " Invalid iterator!" );
285
+
230
286
if (isGuaranteedNotToBeUndefOrPoison (LastVisited->second ))
231
287
return LastVisited->second ;
232
288
return nullptr ;
@@ -253,6 +309,8 @@ Constant *InstCostVisitor::visitCallBase(CallBase &I) {
253
309
}
254
310
255
311
Constant *InstCostVisitor::visitLoadInst (LoadInst &I) {
312
+ assert (LastVisited != KnownConstants.end () && " Invalid iterator!" );
313
+
256
314
if (isa<ConstantPointerNull>(LastVisited->second ))
257
315
return nullptr ;
258
316
return ConstantFoldLoadFromConstPtr (LastVisited->second , I.getType (), DL);
@@ -275,6 +333,8 @@ Constant *InstCostVisitor::visitGetElementPtrInst(GetElementPtrInst &I) {
275
333
}
276
334
277
335
Constant *InstCostVisitor::visitSelectInst (SelectInst &I) {
336
+ assert (LastVisited != KnownConstants.end () && " Invalid iterator!" );
337
+
278
338
if (I.getCondition () != LastVisited->first )
279
339
return nullptr ;
280
340
@@ -290,6 +350,8 @@ Constant *InstCostVisitor::visitCastInst(CastInst &I) {
290
350
}
291
351
292
352
Constant *InstCostVisitor::visitCmpInst (CmpInst &I) {
353
+ assert (LastVisited != KnownConstants.end () && " Invalid iterator!" );
354
+
293
355
bool Swap = I.getOperand (1 ) == LastVisited->first ;
294
356
Value *V = Swap ? I.getOperand (0 ) : I.getOperand (1 );
295
357
Constant *Other = findConstantFor (V, KnownConstants);
@@ -303,10 +365,14 @@ Constant *InstCostVisitor::visitCmpInst(CmpInst &I) {
303
365
}
304
366
305
367
Constant *InstCostVisitor::visitUnaryOperator (UnaryOperator &I) {
368
+ assert (LastVisited != KnownConstants.end () && " Invalid iterator!" );
369
+
306
370
return ConstantFoldUnaryOpOperand (I.getOpcode (), LastVisited->second , DL);
307
371
}
308
372
309
373
Constant *InstCostVisitor::visitBinaryOperator (BinaryOperator &I) {
374
+ assert (LastVisited != KnownConstants.end () && " Invalid iterator!" );
375
+
310
376
bool Swap = I.getOperand (1 ) == LastVisited->first ;
311
377
Value *V = Swap ? I.getOperand (0 ) : I.getOperand (1 );
312
378
Constant *Other = findConstantFor (V, KnownConstants);
@@ -713,13 +779,17 @@ bool FunctionSpecializer::findSpecializations(Function *F, Cost SpecCost,
713
779
AllSpecs[Index].CallSites .push_back (&CS);
714
780
} else {
715
781
// Calculate the specialisation gain.
716
- Cost Score = 0 - SpecCost ;
782
+ Cost Score = 0 ;
717
783
InstCostVisitor Visitor = getInstCostVisitorFor (F);
718
784
for (ArgInfo &A : S.Args )
719
785
Score += getSpecializationBonus (A.Formal , A.Actual , Visitor);
786
+ Score += Visitor.getBonusFromPendingPHIs ();
787
+
788
+ LLVM_DEBUG (dbgs () << " FnSpecialization: Specialization score = "
789
+ << Score << " \n " );
720
790
721
791
// Discard unprofitable specialisations.
722
- if (!ForceSpecialization && Score <= 0 )
792
+ if (!ForceSpecialization && Score <= SpecCost )
723
793
continue ;
724
794
725
795
// Create a new specialisation entry.
0 commit comments