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 | c5eb380b60689c0993e07025872a9038be967b40 (patch) | |
tree | 5b00eea8538e78fab56a27ee19a7b4a00ad90f4d /lib/Transforms/Utils/UnifyFunctionExitNodes.cpp | |
parent | f697ec3e53cde5ddad967a714d5fd6b83fa5b406 (diff) |
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/UnifyFunctionExitNodes.cpp')
-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); |