mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-21 12:02:58 +02:00
Use IRBuilder while simplifying switch instruction.
llvm-svn: 131566
This commit is contained in:
parent
3d6c5f4876
commit
fd9b1daf82
@ -57,16 +57,17 @@ class SimplifyCFGOpt {
|
|||||||
BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI,
|
BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI,
|
||||||
std::vector<std::pair<ConstantInt*, BasicBlock*> > &Cases);
|
std::vector<std::pair<ConstantInt*, BasicBlock*> > &Cases);
|
||||||
bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
||||||
BasicBlock *Pred);
|
BasicBlock *Pred,
|
||||||
|
IRBuilder<> &Builder);
|
||||||
bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI);
|
bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI);
|
||||||
|
|
||||||
bool SimplifyReturn(ReturnInst *RI);
|
bool SimplifyReturn(ReturnInst *RI);
|
||||||
bool SimplifyUnwind(UnwindInst *UI, IRBuilder<> &Builder);
|
bool SimplifyUnwind(UnwindInst *UI, IRBuilder<> &Builder);
|
||||||
bool SimplifyUnreachable(UnreachableInst *UI);
|
bool SimplifyUnreachable(UnreachableInst *UI);
|
||||||
bool SimplifySwitch(SwitchInst *SI);
|
bool SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder);
|
||||||
bool SimplifyIndirectBr(IndirectBrInst *IBI);
|
bool SimplifyIndirectBr(IndirectBrInst *IBI);
|
||||||
bool SimplifyUncondBranch(BranchInst *BI, IRBuilder <> &Builder);
|
bool SimplifyUncondBranch(BranchInst *BI, IRBuilder <> &Builder);
|
||||||
bool SimplifyCondBranch(BranchInst *BI);
|
bool SimplifyCondBranch(BranchInst *BI, IRBuilder <>&Builder);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SimplifyCFGOpt(const TargetData *td) : TD(td) {}
|
explicit SimplifyCFGOpt(const TargetData *td) : TD(td) {}
|
||||||
@ -543,7 +544,8 @@ ValuesOverlap(std::vector<std::pair<ConstantInt*, BasicBlock*> > &C1,
|
|||||||
/// form of jump threading.
|
/// form of jump threading.
|
||||||
bool SimplifyCFGOpt::
|
bool SimplifyCFGOpt::
|
||||||
SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
||||||
BasicBlock *Pred) {
|
BasicBlock *Pred,
|
||||||
|
IRBuilder<> &Builder) {
|
||||||
Value *PredVal = isValueEqualityComparison(Pred->getTerminator());
|
Value *PredVal = isValueEqualityComparison(Pred->getTerminator());
|
||||||
if (!PredVal) return false; // Not a value comparison in predecessor.
|
if (!PredVal) return false; // Not a value comparison in predecessor.
|
||||||
|
|
||||||
@ -576,7 +578,7 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
|||||||
// uncond br.
|
// uncond br.
|
||||||
assert(ThisCases.size() == 1 && "Branch can only have one case!");
|
assert(ThisCases.size() == 1 && "Branch can only have one case!");
|
||||||
// Insert the new branch.
|
// Insert the new branch.
|
||||||
Instruction *NI = BranchInst::Create(ThisDef, TI);
|
Instruction *NI = Builder.CreateBr(ThisDef);
|
||||||
(void) NI;
|
(void) NI;
|
||||||
|
|
||||||
// Remove PHI node entries for the dead edge.
|
// Remove PHI node entries for the dead edge.
|
||||||
@ -641,7 +643,7 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
|||||||
CheckEdge = 0;
|
CheckEdge = 0;
|
||||||
|
|
||||||
// Insert the new branch.
|
// Insert the new branch.
|
||||||
Instruction *NI = BranchInst::Create(TheRealDest, TI);
|
Instruction *NI = Builder.CreateBr(TheRealDest);
|
||||||
(void) NI;
|
(void) NI;
|
||||||
|
|
||||||
DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
|
DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
|
||||||
@ -2366,7 +2368,7 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
|
|||||||
|
|
||||||
/// TurnSwitchRangeIntoICmp - Turns a switch with that contains only a
|
/// TurnSwitchRangeIntoICmp - Turns a switch with that contains only a
|
||||||
/// integer range comparison into a sub, an icmp and a branch.
|
/// integer range comparison into a sub, an icmp and a branch.
|
||||||
static bool TurnSwitchRangeIntoICmp(SwitchInst *SI) {
|
static bool TurnSwitchRangeIntoICmp(SwitchInst *SI, IRBuilder<> &Builder) {
|
||||||
assert(SI->getNumCases() > 2 && "Degenerate switch?");
|
assert(SI->getNumCases() > 2 && "Degenerate switch?");
|
||||||
|
|
||||||
// Make sure all cases point to the same destination and gather the values.
|
// Make sure all cases point to the same destination and gather the values.
|
||||||
@ -2393,7 +2395,7 @@ static bool TurnSwitchRangeIntoICmp(SwitchInst *SI) {
|
|||||||
if (!Offset->isNullValue())
|
if (!Offset->isNullValue())
|
||||||
Sub = BinaryOperator::CreateAdd(Sub, Offset, Sub->getName()+".off", SI);
|
Sub = BinaryOperator::CreateAdd(Sub, Offset, Sub->getName()+".off", SI);
|
||||||
Value *Cmp = new ICmpInst(SI, ICmpInst::ICMP_ULT, Sub, NumCases, "switch");
|
Value *Cmp = new ICmpInst(SI, ICmpInst::ICMP_ULT, Sub, NumCases, "switch");
|
||||||
BranchInst::Create(SI->getSuccessor(1), SI->getDefaultDest(), Cmp, SI);
|
Builder.CreateCondBr(Cmp, SI->getSuccessor(1), SI->getDefaultDest());
|
||||||
|
|
||||||
// Prune obsolete incoming values off the successor's PHI nodes.
|
// Prune obsolete incoming values off the successor's PHI nodes.
|
||||||
for (BasicBlock::iterator BBI = SI->getSuccessor(1)->begin();
|
for (BasicBlock::iterator BBI = SI->getSuccessor(1)->begin();
|
||||||
@ -2436,7 +2438,7 @@ static bool EliminateDeadSwitchCases(SwitchInst *SI) {
|
|||||||
return !DeadCases.empty();
|
return !DeadCases.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI) {
|
bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
|
||||||
// If this switch is too complex to want to look at, ignore it.
|
// If this switch is too complex to want to look at, ignore it.
|
||||||
if (!isValueEqualityComparison(SI))
|
if (!isValueEqualityComparison(SI))
|
||||||
return false;
|
return false;
|
||||||
@ -2446,7 +2448,7 @@ bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI) {
|
|||||||
// If we only have one predecessor, and if it is a branch on this value,
|
// If we only have one predecessor, and if it is a branch on this value,
|
||||||
// see if that predecessor totally determines the outcome of this switch.
|
// see if that predecessor totally determines the outcome of this switch.
|
||||||
if (BasicBlock *OnlyPred = BB->getSinglePredecessor())
|
if (BasicBlock *OnlyPred = BB->getSinglePredecessor())
|
||||||
if (SimplifyEqualityComparisonWithOnlyPredecessor(SI, OnlyPred))
|
if (SimplifyEqualityComparisonWithOnlyPredecessor(SI, OnlyPred, Builder))
|
||||||
return SimplifyCFG(BB) | true;
|
return SimplifyCFG(BB) | true;
|
||||||
|
|
||||||
Value *Cond = SI->getCondition();
|
Value *Cond = SI->getCondition();
|
||||||
@ -2465,7 +2467,7 @@ bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI) {
|
|||||||
return SimplifyCFG(BB) | true;
|
return SimplifyCFG(BB) | true;
|
||||||
|
|
||||||
// Try to transform the switch into an icmp and a branch.
|
// Try to transform the switch into an icmp and a branch.
|
||||||
if (TurnSwitchRangeIntoICmp(SI))
|
if (TurnSwitchRangeIntoICmp(SI, Builder))
|
||||||
return SimplifyCFG(BB) | true;
|
return SimplifyCFG(BB) | true;
|
||||||
|
|
||||||
// Remove unreachable cases.
|
// Remove unreachable cases.
|
||||||
@ -2536,7 +2538,7 @@ bool SimplifyCFGOpt::SimplifyUncondBranch(BranchInst *BI, IRBuilder<> &Builder){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SimplifyCFGOpt::SimplifyCondBranch(BranchInst *BI) {
|
bool SimplifyCFGOpt::SimplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
|
||||||
BasicBlock *BB = BI->getParent();
|
BasicBlock *BB = BI->getParent();
|
||||||
|
|
||||||
// Conditional branch
|
// Conditional branch
|
||||||
@ -2545,7 +2547,7 @@ bool SimplifyCFGOpt::SimplifyCondBranch(BranchInst *BI) {
|
|||||||
// see if that predecessor totally determines the outcome of this
|
// see if that predecessor totally determines the outcome of this
|
||||||
// switch.
|
// switch.
|
||||||
if (BasicBlock *OnlyPred = BB->getSinglePredecessor())
|
if (BasicBlock *OnlyPred = BB->getSinglePredecessor())
|
||||||
if (SimplifyEqualityComparisonWithOnlyPredecessor(BI, OnlyPred))
|
if (SimplifyEqualityComparisonWithOnlyPredecessor(BI, OnlyPred, Builder))
|
||||||
return SimplifyCFG(BB) | true;
|
return SimplifyCFG(BB) | true;
|
||||||
|
|
||||||
// This block must be empty, except for the setcond inst, if it exists.
|
// This block must be empty, except for the setcond inst, if it exists.
|
||||||
@ -2659,16 +2661,17 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
|
|||||||
if (PN->getNumIncomingValues() == 2)
|
if (PN->getNumIncomingValues() == 2)
|
||||||
Changed |= FoldTwoEntryPHINode(PN, TD, Builder);
|
Changed |= FoldTwoEntryPHINode(PN, TD, Builder);
|
||||||
|
|
||||||
|
Builder.SetInsertPoint(BB->getTerminator());
|
||||||
if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) {
|
if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) {
|
||||||
if (BI->isUnconditional()) {
|
if (BI->isUnconditional()) {
|
||||||
if (SimplifyUncondBranch(BI, Builder)) return true;
|
if (SimplifyUncondBranch(BI, Builder)) return true;
|
||||||
} else {
|
} else {
|
||||||
if (SimplifyCondBranch(BI)) return true;
|
if (SimplifyCondBranch(BI, Builder)) return true;
|
||||||
}
|
}
|
||||||
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
|
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
|
||||||
if (SimplifyReturn(RI)) return true;
|
if (SimplifyReturn(RI)) return true;
|
||||||
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
|
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
|
||||||
if (SimplifySwitch(SI)) return true;
|
if (SimplifySwitch(SI, Builder)) return true;
|
||||||
} else if (UnreachableInst *UI =
|
} else if (UnreachableInst *UI =
|
||||||
dyn_cast<UnreachableInst>(BB->getTerminator())) {
|
dyn_cast<UnreachableInst>(BB->getTerminator())) {
|
||||||
if (SimplifyUnreachable(UI)) return true;
|
if (SimplifyUnreachable(UI)) return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user