aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Utils/CodeExtractor.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-03-14 23:05:49 +0000
committerChris Lattner <sabre@nondot.org>2004-03-14 23:05:49 +0000
commit12f390e9c03d5439fd84c26d7cbd451cda80601a (patch)
tree27fed1f7032b874b867d7bb4eb5b5cf7de301a84 /lib/Transforms/Utils/CodeExtractor.cpp
parent0e06674287b15696f66a65f20f2ba99137b29213 (diff)
Simplify code a bit, and fix bug CodeExtractor/2004-03-14-NoSwitchSupport.ll
This also implements a two minor improvements: * Don't insert live-out stores IN the region, insert them on the code path that exits the region * If the region is exited to the same block from multiple paths, share the switch statement entry, live-out store code, and the basic block. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12401 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils/CodeExtractor.cpp')
-rw-r--r--lib/Transforms/Utils/CodeExtractor.cpp96
1 files changed, 34 insertions, 62 deletions
diff --git a/lib/Transforms/Utils/CodeExtractor.cpp b/lib/Transforms/Utils/CodeExtractor.cpp
index 68cf7310c7..82538d7fbc 100644
--- a/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/lib/Transforms/Utils/CodeExtractor.cpp
@@ -336,11 +336,10 @@ Function *CodeExtractor::constructFunction(const Values &inputs,
return newFunction;
}
-void CodeExtractor::moveCodeToFunction(Function *newFunction)
-{
+void CodeExtractor::moveCodeToFunction(Function *newFunction) {
Function *oldFunc = (*BlocksToExtract.begin())->getParent();
Function::BasicBlockListType &oldBlocks = oldFunc->getBasicBlockList();
- Function::BasicBlockListType &newBlocks = newFunction->getBasicBlockList();
+ Function::BasicBlockListType &newBlocks = newFunction->getBasicBlockList();
for (std::set<BasicBlock*>::const_iterator i = BlocksToExtract.begin(),
e = BlocksToExtract.end(); i != e; ++i) {
@@ -390,6 +389,7 @@ CodeExtractor::emitCallAndSwitchStatement(Function *newFunction,
params.push_back(*i);
}
}
+
CallInst *call = new CallInst(newFunction, params, "targetBlock");
codeReplacer->getInstList().push_back(call);
codeReplacer->getInstList().push_back(new BranchInst(codeReplacerTail));
@@ -405,70 +405,42 @@ CodeExtractor::emitCallAndSwitchStatement(Function *newFunction,
codeReplacerTail);
// Since there may be multiple exits from the original region, make the new
- // function return an unsigned, switch on that number
+ // function return an unsigned, switch on that number. This loop iterates
+ // over all of the blocks in the extracted region, updating any terminator
+ // instructions in the to-be-extracted region that branch to blocks that are
+ // not in the region to be extracted.
+ std::map<BasicBlock*, BasicBlock*> ExitBlockMap;
+
unsigned switchVal = 0;
for (std::set<BasicBlock*>::const_iterator i = BlocksToExtract.begin(),
e = BlocksToExtract.end(); i != e; ++i) {
- BasicBlock *BB = *i;
-
- // rewrite the terminator of the original BasicBlock
- Instruction *term = BB->getTerminator();
- if (BranchInst *brInst = dyn_cast<BranchInst>(term)) {
-
- // Restore values just before we exit
- // FIXME: Use a GetElementPtr to bunch the outputs in a struct
- for (unsigned outIdx = 0, outE = outputs.size(); outIdx != outE; ++outIdx)
- new StoreInst(outputs[outIdx],
- getFunctionArg(newFunction, outIdx),
- brInst);
-
- // Rewrite branches into exits which return a value based on which
- // exit we take from this function
- if (brInst->isUnconditional()) {
- if (!BlocksToExtract.count(brInst->getSuccessor(0))) {
- ConstantUInt *brVal = ConstantUInt::get(Type::UShortTy, switchVal);
- ReturnInst *newRet = new ReturnInst(brVal);
- // add a new target to the switch
- switchInst->addCase(brVal, brInst->getSuccessor(0));
- ++switchVal;
- // rewrite the branch with a return
- BasicBlock::iterator ii(brInst);
- ReplaceInstWithInst(BB->getInstList(), ii, newRet);
- delete brInst;
- }
- } else {
- // Replace the conditional branch to branch
- // to two new blocks, each of which returns a different code.
- for (unsigned idx = 0; idx < 2; ++idx) {
- BasicBlock *oldTarget = brInst->getSuccessor(idx);
- if (!BlocksToExtract.count(oldTarget)) {
- // add a new basic block which returns the appropriate value
- BasicBlock *newTarget = new BasicBlock("newTarget", newFunction);
- ConstantUInt *brVal = ConstantUInt::get(Type::UShortTy, switchVal);
- ReturnInst *newRet = new ReturnInst(brVal);
- newTarget->getInstList().push_back(newRet);
- // rewrite the original branch instruction with this new target
- brInst->setSuccessor(idx, newTarget);
- // the switch statement knows what to do with this value
- switchInst->addCase(brVal, oldTarget);
- ++switchVal;
- }
+ TerminatorInst *TI = (*i)->getTerminator();
+ for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
+ if (!BlocksToExtract.count(TI->getSuccessor(i))) {
+ BasicBlock *OldTarget = TI->getSuccessor(i);
+ // add a new basic block which returns the appropriate value
+ BasicBlock *&NewTarget = ExitBlockMap[OldTarget];
+ if (!NewTarget) {
+ // If we don't already have an exit stub for this non-extracted
+ // destination, create one now!
+ NewTarget = new BasicBlock(OldTarget->getName() + ".exitStub",
+ newFunction);
+
+ ConstantUInt *brVal = ConstantUInt::get(Type::UShortTy, switchVal++);
+ ReturnInst *NTRet = new ReturnInst(brVal, NewTarget);
+
+ // Update the switch instruction.
+ switchInst->addCase(brVal, OldTarget);
+
+ // Restore values just before we exit
+ // FIXME: Use a GetElementPtr to bunch the outputs in a struct
+ for (unsigned out = 0, e = outputs.size(); out != e; ++out)
+ new StoreInst(outputs[out], getFunctionArg(newFunction, out),NTRet);
}
- }
- } else if (SwitchInst *swTerm = dyn_cast<SwitchInst>(term)) {
-
- assert(0 && "Cannot handle switch instructions just yet.");
- } else if (ReturnInst *retTerm = dyn_cast<ReturnInst>(term)) {
- assert(0 && "Cannot handle return instructions just yet.");
- // FIXME: what if the terminator is a return!??!
- // Need to rewrite: add new basic block, move the return there
- // treat the original as an unconditional branch to that basicblock
- } else if (InvokeInst *invInst = dyn_cast<InvokeInst>(term)) {
- assert(0 && "Cannot handle invoke instructions just yet.");
- } else {
- assert(0 && "Unrecognized terminator, or badly-formed BasicBlock.");
- }
+ // rewrite the original branch instruction with this new target
+ TI->setSuccessor(i, NewTarget);
+ }
}
}