diff options
author | Devang Patel <dpatel@apple.com> | 2008-03-05 21:50:24 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2008-03-05 21:50:24 +0000 |
commit | 40a92a12a48a2ead0fb7b5f988a83e63d87672af (patch) | |
tree | 5b00eea8538e78fab56a27ee19a7b4a00ad90f4d /lib/Transforms/Utils | |
parent | 0f6746e5ad759a7769e3d9ce73f1743ed39af2c9 (diff) | |
download | external_llvm-40a92a12a48a2ead0fb7b5f988a83e63d87672af.tar.gz external_llvm-40a92a12a48a2ead0fb7b5f988a83e63d87672af.tar.bz2 external_llvm-40a92a12a48a2ead0fb7b5f988a83e63d87672af.zip |
Handle 'ret' with multiple values.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47965 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils')
-rw-r--r-- | lib/Transforms/Utils/UnifyFunctionExitNodes.cpp | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp index 5d151ed70a..7639d3f967 100644 --- a/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +++ b/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -20,6 +20,7 @@ #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Type.h" +#include "llvm/ADT/SmallVector.h" using namespace llvm; char UnifyFunctionExitNodes::ID = 0; @@ -50,11 +51,6 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) { // Loop over all of the blocks in a function, tracking all of the blocks that // return. // - - // PHINode can not handle aggregates returned by multiple value ret - // instructions. TODO: Handle each return value independently. - if (isa<StructType>(F.getReturnType())) - return false; std::vector<BasicBlock*> ReturningBlocks; std::vector<BasicBlock*> UnwindingBlocks; std::vector<BasicBlock*> UnreachableBlocks; @@ -110,18 +106,30 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) { } // Otherwise, we need to insert a new basic block into the function, add a PHI - // node (if the function returns a value), and convert all of the return + // nodes (if the function returns values), and convert all of the return // instructions into unconditional branches. // BasicBlock *NewRetBlock = new BasicBlock("UnifiedReturnBlock", &F); - PHINode *PN = 0; - if (F.getReturnType() != Type::VoidTy) { + SmallVector<Value *, 4> Phis; + unsigned NumRetVals = ReturningBlocks[0]->getTerminator()->getNumOperands(); + if (NumRetVals == 0) + new ReturnInst(NULL, NewRetBlock); + else if (const StructType *STy = dyn_cast<StructType>(F.getReturnType())) { + for (unsigned i = 0; i < NumRetVals; ++i) { + PHINode *PN = new PHINode(STy->getElementType(i), "UnifiedRetVal"); + NewRetBlock->getInstList().push_back(PN); + Phis.push_back(PN); + } + new ReturnInst(&Phis[0], NumRetVals); + } + else { // If the function doesn't return void... add a PHI node to the block... - PN = new PHINode(F.getReturnType(), "UnifiedRetVal"); + PHINode *PN = new PHINode(F.getReturnType(), "UnifiedRetVal"); NewRetBlock->getInstList().push_back(PN); + Phis.push_back(PN); + new ReturnInst(PN, NewRetBlock); } - new ReturnInst(PN, NewRetBlock); // Loop over all of the blocks, replacing the return instruction with an // unconditional branch. @@ -132,7 +140,11 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) { // Add an incoming element to the PHI node for every return instruction that // is merging into this new block... - if (PN) PN->addIncoming(BB->getTerminator()->getOperand(0), BB); + if (!Phis.empty()) { + for (unsigned i = 0; i < NumRetVals; ++i) + cast<PHINode>(Phis[i])->addIncoming(BB->getTerminator()->getOperand(i), + BB); + } BB->getInstList().pop_back(); // Remove the return insn new BranchInst(NewRetBlock, BB); |