Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lib/Transforms/Utils/SimplifyCFG.cpp
Show First 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | cl::desc("Hoist conditional stores even if an unconditional store does not " | ||||
"precede - hoist multiple conditional stores into a single " | "precede - hoist multiple conditional stores into a single " | ||||
"predicated store")); | "predicated store")); | ||||
static cl::opt<bool> MergeCondStoresAggressively( | static cl::opt<bool> MergeCondStoresAggressively( | ||||
"simplifycfg-merge-cond-stores-aggressively", cl::Hidden, cl::init(false), | "simplifycfg-merge-cond-stores-aggressively", cl::Hidden, cl::init(false), | ||||
cl::desc("When merging conditional stores, do so even if the resultant " | cl::desc("When merging conditional stores, do so even if the resultant " | ||||
"basic blocks are unlikely to be if-converted as a result")); | "basic blocks are unlikely to be if-converted as a result")); | ||||
static cl::opt<bool> SpeculateOneExpensiveInst( | |||||
"speculate-one-expensive-inst", cl::Hidden, cl::init(true), | |||||
cl::desc("Allow exactly one expensive instruction to be speculatively " | |||||
"executed")); | |||||
STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps"); | STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps"); | ||||
STATISTIC(NumLinearMaps, "Number of switch instructions turned into linear mapping"); | STATISTIC(NumLinearMaps, "Number of switch instructions turned into linear mapping"); | ||||
STATISTIC(NumLookupTables, "Number of switch instructions turned into lookup tables"); | STATISTIC(NumLookupTables, "Number of switch instructions turned into lookup tables"); | ||||
STATISTIC(NumLookupTablesHoles, "Number of switch instructions turned into lookup tables (holes checked)"); | STATISTIC(NumLookupTablesHoles, "Number of switch instructions turned into lookup tables (holes checked)"); | ||||
STATISTIC(NumTableCmpReuses, "Number of reused switch table lookup compares"); | STATISTIC(NumTableCmpReuses, "Number of reused switch table lookup compares"); | ||||
STATISTIC(NumSinkCommons, "Number of common instructions sunk down to the end block"); | STATISTIC(NumSinkCommons, "Number of common instructions sunk down to the end block"); | ||||
STATISTIC(NumSpeculations, "Number of speculative executed instructions"); | STATISTIC(NumSpeculations, "Number of speculative executed instructions"); | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | |||||
/// Select whose cost is 2. | /// Select whose cost is 2. | ||||
/// | /// | ||||
/// After this function returns, CostRemaining is decreased by the cost of | /// After this function returns, CostRemaining is decreased by the cost of | ||||
/// V plus its non-dominating operands. If that cost is greater than | /// V plus its non-dominating operands. If that cost is greater than | ||||
/// CostRemaining, false is returned and CostRemaining is undefined. | /// CostRemaining, false is returned and CostRemaining is undefined. | ||||
static bool DominatesMergePoint(Value *V, BasicBlock *BB, | static bool DominatesMergePoint(Value *V, BasicBlock *BB, | ||||
SmallPtrSetImpl<Instruction*> *AggressiveInsts, | SmallPtrSetImpl<Instruction*> *AggressiveInsts, | ||||
unsigned &CostRemaining, | unsigned &CostRemaining, | ||||
const TargetTransformInfo &TTI) { | const TargetTransformInfo &TTI, | ||||
unsigned Depth = 0) { | |||||
Instruction *I = dyn_cast<Instruction>(V); | Instruction *I = dyn_cast<Instruction>(V); | ||||
if (!I) { | if (!I) { | ||||
// Non-instructions all dominate instructions, but not all constantexprs | // Non-instructions all dominate instructions, but not all constantexprs | ||||
// can be executed unconditionally. | // can be executed unconditionally. | ||||
if (ConstantExpr *C = dyn_cast<ConstantExpr>(V)) | if (ConstantExpr *C = dyn_cast<ConstantExpr>(V)) | ||||
if (C->canTrap()) | if (C->canTrap()) | ||||
return false; | return false; | ||||
return true; | return true; | ||||
Show All 21 Lines | static bool DominatesMergePoint(Value *V, BasicBlock *BB, | ||||
// Okay, it looks like the instruction IS in the "condition". Check to | // Okay, it looks like the instruction IS in the "condition". Check to | ||||
// see if it's a cheap instruction to unconditionally compute, and if it | // see if it's a cheap instruction to unconditionally compute, and if it | ||||
// only uses stuff defined outside of the condition. If so, hoist it out. | // only uses stuff defined outside of the condition. If so, hoist it out. | ||||
if (!isSafeToSpeculativelyExecute(I)) | if (!isSafeToSpeculativelyExecute(I)) | ||||
return false; | return false; | ||||
unsigned Cost = ComputeSpeculationCost(I, TTI); | unsigned Cost = ComputeSpeculationCost(I, TTI); | ||||
if (Cost > CostRemaining) | // Allow exactly one instruction to be speculated regardless of its cost | ||||
// (as long as it is safe to do so). | |||||
// This is intended to flatten the CFG even if the instruction is a division | |||||
// or other expensive operation. The speculation of an expensive instruction | |||||
// is expected to be undone in CodeGenPrepare if the speculation has not | |||||
// enabled further IR optimizations. | |||||
if (!SpeculateOneExpensiveInst || | |||||
jmolloy: I think !empty() is a quicker predicate than size(). I also think as Depth is an integer and… | |||||
(Cost > CostRemaining && (!AggressiveInsts->empty() || Depth > 0))) | |||||
return false; | return false; | ||||
CostRemaining -= Cost; | // Avoid unsigned wrap. | ||||
CostRemaining = (Cost > CostRemaining) ? 0 : CostRemaining - Cost; | |||||
// Okay, we can only really hoist these out if their operands do | // Okay, we can only really hoist these out if their operands do | ||||
// not take us over the cost threshold. | // not take us over the cost threshold. | ||||
for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) | for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) | ||||
if (!DominatesMergePoint(*i, BB, AggressiveInsts, CostRemaining, TTI)) | if (!DominatesMergePoint(*i, BB, AggressiveInsts, CostRemaining, TTI, | ||||
Depth + 1)) | |||||
return false; | return false; | ||||
// Okay, it's safe to do this! Remember this instruction. | // Okay, it's safe to do this! Remember this instruction. | ||||
AggressiveInsts->insert(I); | AggressiveInsts->insert(I); | ||||
return true; | return true; | ||||
} | } | ||||
/// Extract ConstantInt from value, looking through IntToPtr | /// Extract ConstantInt from value, looking through IntToPtr | ||||
/// and PointerNullValue. Return NULL if value is not a constant int. | /// and PointerNullValue. Return NULL if value is not a constant int. | ||||
▲ Show 20 Lines • Show All 4,829 Lines • Show Last 20 Lines |
I think !empty() is a quicker predicate than size(). I also think as Depth is an integer and you're using it in integer context, "Depth > 0" would be more explanatory.
I think this is the sort of heuristic that it would be good to get as a cl::opt.