@@ -83,6 +83,11 @@ static cl::opt<unsigned> MaxIncomingPhiValues(
83
83
" The maximum number of incoming values a PHI node can have to be "
84
84
" considered during the specialization bonus estimation" ));
85
85
86
+ static cl::opt<unsigned > MaxBlockPredecessors (
87
+ " funcspec-max-block-predecessors" , cl::init(2 ), cl::Hidden, cl::desc(
88
+ " The maximum number of predecessors a basic block can have to be "
89
+ " considered during the estimation of dead code" ));
90
+
86
91
static cl::opt<unsigned > MinFunctionSize (
87
92
" funcspec-min-function-size" , cl::init(100 ), cl::Hidden, cl::desc(
88
93
" Don't specialize functions that have less than this number of "
@@ -101,16 +106,24 @@ static cl::opt<bool> SpecializeLiteralConstant(
101
106
" Enable specialization of functions that take a literal constant as an "
102
107
" argument" ));
103
108
109
+ bool InstCostVisitor::canEliminateSuccessor (BasicBlock *BB, BasicBlock *Succ,
110
+ DenseSet<BasicBlock *> &DeadBlocks) {
111
+ unsigned I = 0 ;
112
+ return all_of (predecessors (Succ),
113
+ [&I, BB, Succ, &DeadBlocks] (BasicBlock *Pred) {
114
+ return I++ < MaxBlockPredecessors &&
115
+ (Pred == BB || Pred == Succ || DeadBlocks.contains (Pred));
116
+ });
117
+ }
118
+
104
119
// Estimates the codesize savings due to dead code after constant propagation.
105
120
// \p WorkList represents the basic blocks of a specialization which will
106
121
// eventually become dead once we replace instructions that are known to be
107
122
// constants. The successors of such blocks are added to the list as long as
108
123
// the \p Solver found they were executable prior to specialization, and only
109
- // if they have a unique predecessor.
110
- static Cost estimateBasicBlocks (SmallVectorImpl<BasicBlock *> &WorkList,
111
- DenseSet<BasicBlock *> &DeadBlocks,
112
- ConstMap &KnownConstants, SCCPSolver &Solver,
113
- TargetTransformInfo &TTI) {
124
+ // if all their predecessors are dead.
125
+ Cost InstCostVisitor::estimateBasicBlocks (
126
+ SmallVectorImpl<BasicBlock *> &WorkList) {
114
127
Cost CodeSize = 0 ;
115
128
// Accumulate the instruction cost of each basic block weighted by frequency.
116
129
while (!WorkList.empty ()) {
@@ -139,10 +152,10 @@ static Cost estimateBasicBlocks(SmallVectorImpl<BasicBlock *> &WorkList,
139
152
}
140
153
141
154
// Keep adding dead successors to the list as long as they are
142
- // executable and they have a unique predecessor .
155
+ // executable and only reachable from dead blocks .
143
156
for (BasicBlock *SuccBB : successors (BB))
144
- if (Solver. isBlockExecutable (SuccBB) &&
145
- SuccBB-> getUniquePredecessor () == BB )
157
+ if (isBlockExecutable (SuccBB) &&
158
+ canEliminateSuccessor (BB, SuccBB, DeadBlocks) )
146
159
WorkList.push_back (SuccBB);
147
160
}
148
161
return CodeSize;
@@ -185,9 +198,13 @@ Bonus InstCostVisitor::getUserBonus(Instruction *User, Value *Use, Constant *C)
185
198
C = visit (*User);
186
199
if (!C)
187
200
return {0 , 0 };
188
- KnownConstants.insert ({User, C});
189
201
}
190
202
203
+ // Even though it doesn't make sense to bind switch and branch instructions
204
+ // with a constant, unlike any other instruction type, it prevents estimating
205
+ // their bonus multiple times.
206
+ KnownConstants.insert ({User, C});
207
+
191
208
CodeSize += TTI.getInstructionCost (User, TargetTransformInfo::TCK_CodeSize);
192
209
193
210
uint64_t Weight = BFI.getBlockFreq (User->getParent ()).getFrequency () /
@@ -226,13 +243,12 @@ Cost InstCostVisitor::estimateSwitchInst(SwitchInst &I) {
226
243
SmallVector<BasicBlock *> WorkList;
227
244
for (const auto &Case : I.cases ()) {
228
245
BasicBlock *BB = Case.getCaseSuccessor ();
229
- if (BB == Succ || !Solver.isBlockExecutable (BB) ||
230
- BB->getUniquePredecessor () != I.getParent ())
231
- continue ;
232
- WorkList.push_back (BB);
246
+ if (BB != Succ && isBlockExecutable (BB) &&
247
+ canEliminateSuccessor (I.getParent (), BB, DeadBlocks))
248
+ WorkList.push_back (BB);
233
249
}
234
250
235
- return estimateBasicBlocks (WorkList, DeadBlocks, KnownConstants, Solver, TTI );
251
+ return estimateBasicBlocks (WorkList);
236
252
}
237
253
238
254
Cost InstCostVisitor::estimateBranchInst (BranchInst &I) {
@@ -245,11 +261,11 @@ Cost InstCostVisitor::estimateBranchInst(BranchInst &I) {
245
261
// Initialize the worklist with the dead successor as long as
246
262
// it is executable and has a unique predecessor.
247
263
SmallVector<BasicBlock *> WorkList;
248
- if (Solver. isBlockExecutable (Succ) &&
249
- Succ-> getUniquePredecessor () == I.getParent ())
264
+ if (isBlockExecutable (Succ) &&
265
+ canEliminateSuccessor ( I.getParent (), Succ, DeadBlocks ))
250
266
WorkList.push_back (Succ);
251
267
252
- return estimateBasicBlocks (WorkList, DeadBlocks, KnownConstants, Solver, TTI );
268
+ return estimateBasicBlocks (WorkList);
253
269
}
254
270
255
271
Constant *InstCostVisitor::visitPHINode (PHINode &I) {
0 commit comments