mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-06 20:37:05 +00:00
Restore LoopUnswitch's block-oriented threshold. LoopUnswitch now checks both
the estimated code size and the number of blocks when deciding whether to do a non-trivial unswitch. This protects it from some very undesirable worst-case behavior on large numbers of loop-unswitchable conditions, such as in the testcase in PR5259. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84661 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
480c529e02
commit
cd53f64367
@ -138,7 +138,6 @@ namespace {
|
||||
void SplitExitEdges(Loop *L, const SmallVector<BasicBlock *, 8> &ExitBlocks);
|
||||
|
||||
bool UnswitchIfProfitable(Value *LoopCond, Constant *Val);
|
||||
unsigned getLoopUnswitchCost(Value *LIC);
|
||||
void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val,
|
||||
BasicBlock *ExitBlock);
|
||||
void UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L);
|
||||
@ -400,25 +399,6 @@ bool LoopUnswitch::IsTrivialUnswitchCondition(Value *Cond, Constant **Val,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// getLoopUnswitchCost - Return the cost (code size growth) that will happen if
|
||||
/// we choose to unswitch current loop on the specified value.
|
||||
///
|
||||
unsigned LoopUnswitch::getLoopUnswitchCost(Value *LIC) {
|
||||
// If the condition is trivial, always unswitch. There is no code growth for
|
||||
// this case.
|
||||
if (IsTrivialUnswitchCondition(LIC))
|
||||
return 0;
|
||||
|
||||
// FIXME: This is overly conservative because it does not take into
|
||||
// consideration code simplification opportunities.
|
||||
CodeMetrics Metrics;
|
||||
for (Loop::block_iterator I = currentLoop->block_begin(),
|
||||
E = currentLoop->block_end();
|
||||
I != E; ++I)
|
||||
Metrics.analyzeBasicBlock(*I);
|
||||
return Metrics.NumInsts;
|
||||
}
|
||||
|
||||
/// UnswitchIfProfitable - We have found that we can unswitch currentLoop when
|
||||
/// LoopCond == Val to simplify the loop. If we decide that this is profitable,
|
||||
/// unswitch the loop, reprocess the pieces, then return true.
|
||||
@ -427,24 +407,35 @@ bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val){
|
||||
initLoopData();
|
||||
Function *F = loopHeader->getParent();
|
||||
|
||||
// If the condition is trivial, always unswitch. There is no code growth for
|
||||
// this case.
|
||||
if (!IsTrivialUnswitchCondition(LoopCond)) {
|
||||
// Check to see if it would be profitable to unswitch current loop.
|
||||
|
||||
// Check to see if it would be profitable to unswitch current loop.
|
||||
unsigned Cost = getLoopUnswitchCost(LoopCond);
|
||||
// Do not do non-trivial unswitch while optimizing for size.
|
||||
if (OptimizeForSize || F->hasFnAttr(Attribute::OptimizeForSize))
|
||||
return false;
|
||||
|
||||
// Do not do non-trivial unswitch while optimizing for size.
|
||||
if (Cost && OptimizeForSize)
|
||||
return false;
|
||||
if (Cost && !F->isDeclaration() && F->hasFnAttr(Attribute::OptimizeForSize))
|
||||
return false;
|
||||
// FIXME: This is overly conservative because it does not take into
|
||||
// consideration code simplification opportunities and code that can
|
||||
// be shared by the resultant unswitched loops.
|
||||
CodeMetrics Metrics;
|
||||
for (Loop::block_iterator I = currentLoop->block_begin(),
|
||||
E = currentLoop->block_end();
|
||||
I != E; ++I)
|
||||
Metrics.analyzeBasicBlock(*I);
|
||||
|
||||
if (Cost > Threshold) {
|
||||
// FIXME: this should estimate growth by the amount of code shared by the
|
||||
// resultant unswitched loops.
|
||||
//
|
||||
DEBUG(errs() << "NOT unswitching loop %"
|
||||
<< currentLoop->getHeader()->getName() << ", cost too high: "
|
||||
<< currentLoop->getBlocks().size() << "\n");
|
||||
return false;
|
||||
// Limit the number of instructions to avoid causing significant code
|
||||
// expansion, and the number of basic blocks, to avoid loops with
|
||||
// large numbers of branches which cause loop unswitching to go crazy.
|
||||
// This is a very ad-hoc heuristic.
|
||||
if (Metrics.NumInsts > Threshold ||
|
||||
Metrics.NumBlocks * 5 > Threshold) {
|
||||
DEBUG(errs() << "NOT unswitching loop %"
|
||||
<< currentLoop->getHeader()->getName() << ", cost too high: "
|
||||
<< currentLoop->getBlocks().size() << "\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Constant *CondVal;
|
||||
|
Loading…
x
Reference in New Issue
Block a user