diff options
author | Chris Lattner <sabre@nondot.org> | 2005-09-26 04:57:38 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-09-26 04:57:38 +0000 |
commit | cdf98bed968ff76b8f310a2adae5811f5ba88ec4 (patch) | |
tree | fa6ec06de0cf0601e29762642358358251c6255b /lib/Transforms | |
parent | 44b19f2bcb58c4e737ae79dfa4e54cee41d44215 (diff) | |
download | external_llvm-cdf98bed968ff76b8f310a2adae5811f5ba88ec4.zip external_llvm-cdf98bed968ff76b8f310a2adae5811f5ba88ec4.tar.gz external_llvm-cdf98bed968ff76b8f310a2adae5811f5ba88ec4.tar.bz2 |
Add support for br/brcond/switch and phi
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23439 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index b9625fe..abef0db 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -1274,8 +1274,14 @@ static bool EvaluateStaticConstructor(Function *F) { /// this state is committed to the process. std::map<Constant*, Constant*> MutatedMemory; + /// ExecutedBlocks - We only handle non-looping, non-recursive code. As such, + /// we can only evaluate any one basic block at most once. This set keeps + /// track of what we have executed so we can detect recursive cases etc. + std::set<BasicBlock*> ExecutedBlocks; + // CurInst - The current instruction we're evaluating. BasicBlock::iterator CurInst = F->begin()->begin(); + ExecutedBlocks.insert(F->begin()); // This is the main evaluation loop. while (1) { @@ -1303,9 +1309,47 @@ static bool EvaluateStaticConstructor(Function *F) { InstResult = ConstantExpr::getSelect(getVal(Values, SI->getOperand(0)), getVal(Values, SI->getOperand(1)), getVal(Values, SI->getOperand(2))); - } else if (ReturnInst *RI = dyn_cast<ReturnInst>(CurInst)) { - assert(RI->getNumOperands() == 0); - break; // We succeeded at evaluating this ctor! + } else if (TerminatorInst *TI = dyn_cast<TerminatorInst>(CurInst)) { + BasicBlock *NewBB = 0; + if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) { + if (BI->isUnconditional()) { + NewBB = BI->getSuccessor(0); + } else { + ConstantBool *Cond = + dyn_cast<ConstantBool>(getVal(Values, BI->getCondition())); + if (!Cond) return false; // Cannot determine. + NewBB = BI->getSuccessor(!Cond->getValue()); + } + } else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) { + ConstantInt *Val = + dyn_cast<ConstantInt>(getVal(Values, SI->getCondition())); + if (!Val) return false; // Cannot determine. + NewBB = SI->getSuccessor(SI->findCaseValue(Val)); + } else if (ReturnInst *RI = dyn_cast<ReturnInst>(CurInst)) { + assert(RI->getNumOperands() == 0); + break; // We succeeded at evaluating this ctor! + } else { + // unwind, unreachable. + return false; // Cannot handle this terminator. + } + + // Okay, we succeeded in evaluating this control flow. See if we have + // executed the new block before. If so, we have a looping or recursive + // function, which we cannot evaluate in reasonable time. + if (!ExecutedBlocks.insert(NewBB).second) + return false; // Recursed! + + // Okay, we have never been in this block before. Check to see if there + // are any PHI nodes. If so, evaluate them with information about where + // we came from. + BasicBlock *OldBB = CurInst->getParent(); + CurInst = NewBB->begin(); + PHINode *PN; + for (; (PN = dyn_cast<PHINode>(CurInst)); ++CurInst) + Values[PN] = getVal(Values, PN->getIncomingValueForBlock(OldBB)); + + // Do NOT increment CurInst. We know that the terminator had no value. + continue; } else { // TODO: use ConstantFoldCall for function calls. |