Add some comments, simplify some code, and fix a bug that caused rewriting
to rewrite with the wrong value. llvm-svn: 26311
This commit is contained in:
parent
9e252e3bcf
commit
8a5a324dac
|
@ -88,7 +88,7 @@ namespace {
|
||||||
bool UnswitchIfProfitable(Value *LoopCond, Constant *Val,Loop *L);
|
bool UnswitchIfProfitable(Value *LoopCond, Constant *Val,Loop *L);
|
||||||
unsigned getLoopUnswitchCost(Loop *L, Value *LIC);
|
unsigned getLoopUnswitchCost(Loop *L, Value *LIC);
|
||||||
void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val,
|
void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val,
|
||||||
bool EntersWhenTrue, BasicBlock *ExitBlock);
|
BasicBlock *ExitBlock);
|
||||||
void UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L);
|
void UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L);
|
||||||
BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To);
|
BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To);
|
||||||
BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt);
|
BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt);
|
||||||
|
@ -282,12 +282,13 @@ static BasicBlock *isTrivialLoopExitBlock(Loop *L, BasicBlock *BB) {
|
||||||
/// code duplications (equivalently, it produces a simpler loop and a new empty
|
/// code duplications (equivalently, it produces a simpler loop and a new empty
|
||||||
/// loop, which gets deleted).
|
/// loop, which gets deleted).
|
||||||
///
|
///
|
||||||
/// If this is a trivial condition, return ConstantBool::True if the loop body
|
/// If this is a trivial condition, return true, otherwise return false. When
|
||||||
/// runs when the condition is true, False if the loop body executes when the
|
/// returning true, this sets Cond and Val to the condition that controls the
|
||||||
/// condition is false. Otherwise, return null to indicate a complex condition.
|
/// trivial condition: when Cond dynamically equals Val, the loop is known to
|
||||||
static bool IsTrivialUnswitchCondition(Loop *L, Value *Cond,
|
/// exit. Finally, this sets LoopExit to the BB that the loop exits to when
|
||||||
Constant **Val = 0,
|
/// Cond == Val.
|
||||||
bool *EntersWhenTrue = 0,
|
///
|
||||||
|
static bool IsTrivialUnswitchCondition(Loop *L, Value *Cond, Constant **Val = 0,
|
||||||
BasicBlock **LoopExit = 0) {
|
BasicBlock **LoopExit = 0) {
|
||||||
BasicBlock *Header = L->getHeader();
|
BasicBlock *Header = L->getHeader();
|
||||||
TerminatorInst *HeaderTerm = Header->getTerminator();
|
TerminatorInst *HeaderTerm = Header->getTerminator();
|
||||||
|
@ -304,9 +305,9 @@ static bool IsTrivialUnswitchCondition(Loop *L, Value *Cond,
|
||||||
// side-effects. If so, determine the value of Cond that causes it to do
|
// side-effects. If so, determine the value of Cond that causes it to do
|
||||||
// this.
|
// this.
|
||||||
if ((LoopExitBB = isTrivialLoopExitBlock(L, BI->getSuccessor(0)))) {
|
if ((LoopExitBB = isTrivialLoopExitBlock(L, BI->getSuccessor(0)))) {
|
||||||
if (Val) *Val = ConstantBool::False;
|
|
||||||
} else if ((LoopExitBB = isTrivialLoopExitBlock(L, BI->getSuccessor(1)))) {
|
|
||||||
if (Val) *Val = ConstantBool::True;
|
if (Val) *Val = ConstantBool::True;
|
||||||
|
} else if ((LoopExitBB = isTrivialLoopExitBlock(L, BI->getSuccessor(1)))) {
|
||||||
|
if (Val) *Val = ConstantBool::False;
|
||||||
}
|
}
|
||||||
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(HeaderTerm)) {
|
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(HeaderTerm)) {
|
||||||
// If this isn't a switch on Cond, we can't handle it.
|
// If this isn't a switch on Cond, we can't handle it.
|
||||||
|
@ -320,7 +321,6 @@ static bool IsTrivialUnswitchCondition(Loop *L, Value *Cond,
|
||||||
if ((LoopExitBB = isTrivialLoopExitBlock(L, SI->getSuccessor(i)))) {
|
if ((LoopExitBB = isTrivialLoopExitBlock(L, SI->getSuccessor(i)))) {
|
||||||
// Okay, we found a trivial case, remember the value that is trivial.
|
// Okay, we found a trivial case, remember the value that is trivial.
|
||||||
if (Val) *Val = SI->getCaseValue(i);
|
if (Val) *Val = SI->getCaseValue(i);
|
||||||
if (EntersWhenTrue) *EntersWhenTrue = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -395,11 +395,9 @@ bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val,Loop *L){
|
||||||
// If this is a trivial condition to unswitch (which results in no code
|
// If this is a trivial condition to unswitch (which results in no code
|
||||||
// duplication), do it now.
|
// duplication), do it now.
|
||||||
Constant *CondVal;
|
Constant *CondVal;
|
||||||
bool EntersWhenTrue = true;
|
|
||||||
BasicBlock *ExitBlock;
|
BasicBlock *ExitBlock;
|
||||||
if (IsTrivialUnswitchCondition(L, LoopCond, &CondVal,
|
if (IsTrivialUnswitchCondition(L, LoopCond, &CondVal, &ExitBlock)) {
|
||||||
&EntersWhenTrue, &ExitBlock)) {
|
UnswitchTrivialCondition(L, LoopCond, CondVal, ExitBlock);
|
||||||
UnswitchTrivialCondition(L, LoopCond, CondVal, EntersWhenTrue, ExitBlock);
|
|
||||||
} else {
|
} else {
|
||||||
UnswitchNontrivialCondition(LoopCond, Val, L);
|
UnswitchNontrivialCondition(LoopCond, Val, L);
|
||||||
}
|
}
|
||||||
|
@ -525,13 +523,12 @@ static void EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
|
||||||
/// side-effects), unswitch it. This doesn't involve any code duplication, just
|
/// side-effects), unswitch it. This doesn't involve any code duplication, just
|
||||||
/// moving the conditional branch outside of the loop and updating loop info.
|
/// moving the conditional branch outside of the loop and updating loop info.
|
||||||
void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond,
|
void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond,
|
||||||
Constant *Val, bool EntersWhenTrue,
|
Constant *Val,
|
||||||
BasicBlock *ExitBlock) {
|
BasicBlock *ExitBlock) {
|
||||||
DEBUG(std::cerr << "loop-unswitch: Trivial-Unswitch loop %"
|
DEBUG(std::cerr << "loop-unswitch: Trivial-Unswitch loop %"
|
||||||
<< L->getHeader()->getName() << " [" << L->getBlocks().size()
|
<< L->getHeader()->getName() << " [" << L->getBlocks().size()
|
||||||
<< " blocks] in Function " << L->getHeader()->getParent()->getName()
|
<< " blocks] in Function " << L->getHeader()->getParent()->getName()
|
||||||
<< " on cond: " << *Val << (EntersWhenTrue ? " == " : " != ") <<
|
<< " on cond: " << *Val << " == " << *Cond << "\n");
|
||||||
*Cond << "\n");
|
|
||||||
|
|
||||||
// First step, split the preheader, so that we know that there is a safe place
|
// First step, split the preheader, so that we know that there is a safe place
|
||||||
// to insert the conditional branch. We will change 'OrigPH' to have a
|
// to insert the conditional branch. We will change 'OrigPH' to have a
|
||||||
|
@ -552,12 +549,8 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond,
|
||||||
|
|
||||||
// Okay, now we have a position to branch from and a position to branch to,
|
// Okay, now we have a position to branch from and a position to branch to,
|
||||||
// insert the new conditional branch.
|
// insert the new conditional branch.
|
||||||
{
|
EmitPreheaderBranchOnCondition(Cond, Val, NewExit, NewPH,
|
||||||
BasicBlock *TrueDest = NewPH, *FalseDest = NewExit;
|
|
||||||
if (!EntersWhenTrue) std::swap(TrueDest, FalseDest);
|
|
||||||
EmitPreheaderBranchOnCondition(Cond, Val, TrueDest, FalseDest,
|
|
||||||
OrigPH->getTerminator());
|
OrigPH->getTerminator());
|
||||||
}
|
|
||||||
OrigPH->getTerminator()->eraseFromParent();
|
OrigPH->getTerminator()->eraseFromParent();
|
||||||
|
|
||||||
// We need to reprocess this loop, it could be unswitched again.
|
// We need to reprocess this loop, it could be unswitched again.
|
||||||
|
@ -566,7 +559,7 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond,
|
||||||
// Now that we know that the loop is never entered when this condition is a
|
// Now that we know that the loop is never entered when this condition is a
|
||||||
// particular value, rewrite the loop with this info. We know that this will
|
// particular value, rewrite the loop with this info. We know that this will
|
||||||
// at least eliminate the old branch.
|
// at least eliminate the old branch.
|
||||||
RewriteLoopBodyWithConditionConstant(L, Cond, Val, EntersWhenTrue);
|
RewriteLoopBodyWithConditionConstant(L, Cond, Val, false);
|
||||||
++NumTrivial;
|
++NumTrivial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,11 +906,6 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
|
||||||
// if (li1 > li2)
|
// if (li1 > li2)
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
// NotVal - If Val is a bool, this contains its inverse.
|
|
||||||
Constant *NotVal = 0;
|
|
||||||
if (ConstantBool *CB = dyn_cast<ConstantBool>(Val))
|
|
||||||
NotVal = ConstantBool::get(!CB->getValue());
|
|
||||||
|
|
||||||
// FOLD boolean conditions (X|LIC), (X&LIC). Fold conditional branches,
|
// FOLD boolean conditions (X|LIC), (X&LIC). Fold conditional branches,
|
||||||
// selects, switches.
|
// selects, switches.
|
||||||
std::vector<User*> Users(LIC->use_begin(), LIC->use_end());
|
std::vector<User*> Users(LIC->use_begin(), LIC->use_end());
|
||||||
|
@ -925,8 +913,12 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
|
||||||
|
|
||||||
// If we know that LIC == Val, or that LIC == NotVal, just replace uses of LIC
|
// If we know that LIC == Val, or that LIC == NotVal, just replace uses of LIC
|
||||||
// in the loop with the appropriate one directly.
|
// in the loop with the appropriate one directly.
|
||||||
if (IsEqual || NotVal) {
|
if (IsEqual || isa<ConstantBool>(Val)) {
|
||||||
Value *Replacement = NotVal ? NotVal : Val;
|
Value *Replacement;
|
||||||
|
if (IsEqual)
|
||||||
|
Replacement = Val;
|
||||||
|
else
|
||||||
|
Replacement = ConstantBool::get(!cast<ConstantBool>(Val)->getValue());
|
||||||
|
|
||||||
for (unsigned i = 0, e = Users.size(); i != e; ++i)
|
for (unsigned i = 0, e = Users.size(); i != e; ++i)
|
||||||
if (Instruction *U = cast<Instruction>(Users[i])) {
|
if (Instruction *U = cast<Instruction>(Users[i])) {
|
||||||
|
@ -978,7 +970,6 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
|
||||||
/// pass.
|
/// pass.
|
||||||
///
|
///
|
||||||
void LoopUnswitch::SimplifyCode(std::vector<Instruction*> &Worklist) {
|
void LoopUnswitch::SimplifyCode(std::vector<Instruction*> &Worklist) {
|
||||||
Worklist.back()->getParent()->getParent()->viewCFG();
|
|
||||||
while (!Worklist.empty()) {
|
while (!Worklist.empty()) {
|
||||||
Instruction *I = Worklist.back();
|
Instruction *I = Worklist.back();
|
||||||
Worklist.pop_back();
|
Worklist.pop_back();
|
||||||
|
@ -1066,9 +1057,10 @@ void LoopUnswitch::SimplifyCode(std::vector<Instruction*> &Worklist) {
|
||||||
Succ->eraseFromParent();
|
Succ->eraseFromParent();
|
||||||
++NumSimplify;
|
++NumSimplify;
|
||||||
} else if (ConstantBool *CB = dyn_cast<ConstantBool>(BI->getCondition())){
|
} else if (ConstantBool *CB = dyn_cast<ConstantBool>(BI->getCondition())){
|
||||||
break; // FIXME: Enable.
|
|
||||||
// Conditional branch. Turn it into an unconditional branch, then
|
// Conditional branch. Turn it into an unconditional branch, then
|
||||||
// remove dead blocks.
|
// remove dead blocks.
|
||||||
|
break; // FIXME: Enable.
|
||||||
|
|
||||||
DEBUG(std::cerr << "Folded branch: " << *BI);
|
DEBUG(std::cerr << "Folded branch: " << *BI);
|
||||||
BasicBlock *DeadSucc = BI->getSuccessor(CB->getValue());
|
BasicBlock *DeadSucc = BI->getSuccessor(CB->getValue());
|
||||||
BasicBlock *LiveSucc = BI->getSuccessor(!CB->getValue());
|
BasicBlock *LiveSucc = BI->getSuccessor(!CB->getValue());
|
||||||
|
|
Loading…
Reference in New Issue