[llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Mar 14 17:06:02 PST 2004
Changes in directory llvm/lib/Transforms/Utils:
CodeExtractor.cpp updated: 1.6 -> 1.7
---
Log message:
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.
---
Diffs of the changes: (+34 -62)
Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp
diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.6 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.7
--- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.6 Sun Mar 14 16:34:55 2004
+++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Sun Mar 14 17:05:49 2004
@@ -336,11 +336,10 @@
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 @@
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 @@
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);
+ }
}
}
More information about the llvm-commits
mailing list