diff options
author | Dan Gohman <gohman@apple.com> | 2008-07-23 00:34:11 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2008-07-23 00:34:11 +0000 |
commit | fc74abfba5128544a750fce22fdf13eb0403e3ce (patch) | |
tree | 36ed972103bbbb170370e4e6688787ed5f1f9ac8 /lib/Transforms | |
parent | 5e6ebaf4d1d3043d3428b65ee8054c71c24af930 (diff) |
Enable first-class aggregates support.
Remove the GetResultInst instruction. It is still accepted in LLVM assembly
and bitcode, where it is now auto-upgraded to ExtractValueInst. Also, remove
support for return instructions with multiple values. These are auto-upgraded
to use InsertValueInst instructions.
The IRBuilder still accepts multiple-value returns, and auto-upgrades them
to InsertValueInst instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53941 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/IPO/IPConstantPropagation.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/IPO/StructRetPromotion.cpp | 24 | ||||
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/Scalar/JumpThreading.cpp | 15 | ||||
-rw-r--r-- | lib/Transforms/Scalar/LoopRotation.cpp | 34 | ||||
-rw-r--r-- | lib/Transforms/Scalar/SCCP.cpp | 41 | ||||
-rw-r--r-- | lib/Transforms/Utils/InlineFunction.cpp | 74 | ||||
-rw-r--r-- | lib/Transforms/Utils/LCSSA.cpp | 22 | ||||
-rw-r--r-- | lib/Transforms/Utils/SimplifyCFG.cpp | 77 | ||||
-rw-r--r-- | lib/Transforms/Utils/UnifyFunctionExitNodes.cpp | 34 |
10 files changed, 68 insertions, 261 deletions
diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp index fa004fda1e..42c02e6a45 100644 --- a/lib/Transforms/IPO/IPConstantPropagation.cpp +++ b/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -255,9 +255,7 @@ bool IPCP::PropagateConstantReturn(Function &F) { // Find the index of the retval to replace with int index = -1; - if (GetResultInst *GR = dyn_cast<GetResultInst>(Ins)) - index = GR->getIndex(); - else if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Ins)) + if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Ins)) if (EV->hasIndices()) index = *EV->idx_begin(); diff --git a/lib/Transforms/IPO/StructRetPromotion.cpp b/lib/Transforms/IPO/StructRetPromotion.cpp index 94bf4c6d5f..aa74944850 100644 --- a/lib/Transforms/IPO/StructRetPromotion.cpp +++ b/lib/Transforms/IPO/StructRetPromotion.cpp @@ -97,9 +97,6 @@ bool SRETPromotion::PromoteReturn(CallGraphNode *CGN) { dyn_cast<StructType>(FArgType->getElementType()); assert (STy && "Invalid sret parameter element type"); - if (nestedStructType(STy)) - return false; - // Check if it is ok to perform this promotion. if (isSafeToUpdateAllCallers(F) == false) { NumRejectedSRETUses++; @@ -114,25 +111,13 @@ bool SRETPromotion::PromoteReturn(CallGraphNode *CGN) { NFirstArg->replaceAllUsesWith(TheAlloca); // [2] Find and replace ret instructions - SmallVector<Value *,4> RetVals; for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) for(BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) { Instruction *I = BI; ++BI; if (isa<ReturnInst>(I)) { - RetVals.clear(); - for (unsigned idx = 0; idx < STy->getNumElements(); ++idx) { - SmallVector<Value*, 2> GEPIdx; - GEPIdx.push_back(ConstantInt::get(Type::Int32Ty, 0)); - GEPIdx.push_back(ConstantInt::get(Type::Int32Ty, idx)); - Value *NGEPI = GetElementPtrInst::Create(TheAlloca, GEPIdx.begin(), - GEPIdx.end(), - "mrv.gep", I); - Value *NV = new LoadInst(NGEPI, "mrv.ld", I); - RetVals.push_back(NV); - } - - ReturnInst *NR = ReturnInst::Create(&RetVals[0], RetVals.size(), I); + Value *NV = new LoadInst(TheAlloca, "mrv.ld", I); + ReturnInst *NR = ReturnInst::Create(NV); I->replaceAllUsesWith(NR); I->eraseFromParent(); } @@ -315,7 +300,7 @@ void SRETPromotion::updateCallSites(Function *F, Function *NF) { ArgAttrsVec.clear(); New->takeName(Call); - // Update all users of sret parameter to extract value using getresult. + // Update all users of sret parameter to extract value using extractvalue. for (Value::use_iterator UI = FirstCArg->use_begin(), UE = FirstCArg->use_end(); UI != UE; ) { User *U2 = *UI++; @@ -325,7 +310,8 @@ void SRETPromotion::updateCallSites(Function *F, Function *NF) { else if (GetElementPtrInst *UGEP = dyn_cast<GetElementPtrInst>(U2)) { ConstantInt *Idx = dyn_cast<ConstantInt>(UGEP->getOperand(2)); assert (Idx && "Unexpected getelementptr index!"); - Value *GR = new GetResultInst(New, Idx->getZExtValue(), "gr", UGEP); + Value *GR = ExtractValueInst::Create(New, Idx->getZExtValue(), + "evi", UGEP); for (Value::use_iterator GI = UGEP->use_begin(), GE = UGEP->use_end(); GI != GE; ++GI) { if (LoadInst *L = dyn_cast<LoadInst>(*GI)) { diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 861badf8f0..da98d0a0fc 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -11476,9 +11476,7 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) { } // See if we can trivially sink this instruction to a successor basic block. - // FIXME: Remove GetResultInst test when first class support for aggregates - // is implemented. - if (I->hasOneUse() && !isa<GetResultInst>(I)) { + if (I->hasOneUse()) { BasicBlock *BB = I->getParent(); BasicBlock *UserParent = cast<Instruction>(I->use_back())->getParent(); if (UserParent != BB) { diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index 4e57f0e74c..1d3bfbfe7c 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -440,20 +440,7 @@ void JumpThreading::ThreadEdge(BasicBlock *BB, BasicBlock *PredBB, // We found a use of I outside of BB. Create a new stack slot to // break this inter-block usage pattern. - if (!isa<StructType>(I->getType())) { - DemoteRegToStack(*I); - continue; - } - - // Alternatively, I must be a call or invoke that returns multiple retvals. - // We can't use 'DemoteRegToStack' because that will create loads and - // stores of aggregates which is not valid yet. If I is a call, we can just - // pull all the getresult instructions up to this block. If I is an invoke, - // we are out of luck. - BasicBlock::iterator IP = I; ++IP; - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); - UI != E; ++UI) - cast<GetResultInst>(UI)->moveBefore(IP); + DemoteRegToStack(*I); } // We are going to have to map operands from the original BB block to the new diff --git a/lib/Transforms/Scalar/LoopRotation.cpp b/lib/Transforms/Scalar/LoopRotation.cpp index 38364c1587..f0dd40bd33 100644 --- a/lib/Transforms/Scalar/LoopRotation.cpp +++ b/lib/Transforms/Scalar/LoopRotation.cpp @@ -249,35 +249,11 @@ bool LoopRotate::rotateLoop(Loop *Lp, LPPassManager &LPM) { // create new PHINode for this instruction. Instruction *NewHeaderReplacement = NULL; if (usedOutsideOriginalHeader(In)) { - // FIXME: remove this when we have first-class aggregates. - if (isa<StructType>(In->getType())) { - // Can't create PHI nodes for this type. If there are any getResults - // not defined in this block, move them back to this block. PHI - // nodes will be created for all getResults later. - BasicBlock::iterator InsertPoint; - if (InvokeInst *II = dyn_cast<InvokeInst>(In)) { - InsertPoint = II->getNormalDest()->getFirstNonPHI(); - } else { - InsertPoint = I; // call - ++InsertPoint; - } - for (Value::use_iterator UI = In->use_begin(), UE = In->use_end(); - UI != UE; ++UI) { - GetResultInst *InGR = cast<GetResultInst>(UI); - if (InGR->getParent() != OrigHeader) { - // Move InGR to immediately after the call or in the normal dest of - // the invoke. It will be picked up, cloned and PHI'd on the next - // iteration. - InGR->moveBefore(InsertPoint); - } - } - } else { - PHINode *PN = PHINode::Create(In->getType(), In->getName(), - NewHeader->begin()); - PN->addIncoming(In, OrigHeader); - PN->addIncoming(C, OrigPreHeader); - NewHeaderReplacement = PN; - } + PHINode *PN = PHINode::Create(In->getType(), In->getName(), + NewHeader->begin()); + PN->addIncoming(In, OrigHeader); + PN->addIncoming(C, OrigPreHeader); + NewHeaderReplacement = PN; } LoopHeaderInfo.push_back(RenameData(In, C, NewHeaderReplacement)); } diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index ff88137af8..d52cef607c 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -384,7 +384,6 @@ private: void visitTerminatorInst(TerminatorInst &TI); void visitCastInst(CastInst &I); - void visitGetResultInst(GetResultInst &GRI); void visitSelectInst(SelectInst &I); void visitBinaryOperator(Instruction &I); void visitCmpInst(CmpInst &I); @@ -669,41 +668,6 @@ void SCCPSolver::visitCastInst(CastInst &I) { VState.getConstant(), I.getType())); } -void SCCPSolver::visitGetResultInst(GetResultInst &GRI) { - Value *Aggr = GRI.getOperand(0); - - // If the operand to the getresult is an undef, the result is undef. - if (isa<UndefValue>(Aggr)) - return; - - Function *F; - if (CallInst *CI = dyn_cast<CallInst>(Aggr)) - F = CI->getCalledFunction(); - else - F = cast<InvokeInst>(Aggr)->getCalledFunction(); - - // TODO: If IPSCCP resolves the callee of this function, we could propagate a - // result back! - if (F == 0 || TrackedMultipleRetVals.empty()) { - markOverdefined(&GRI); - return; - } - - // See if we are tracking the result of the callee. - std::map<std::pair<Function*, unsigned>, LatticeVal>::iterator - It = TrackedMultipleRetVals.find(std::make_pair(F, GRI.getIndex())); - - // If not tracking this function (for example, it is a declaration) just move - // to overdefined. - if (It == TrackedMultipleRetVals.end()) { - markOverdefined(&GRI); - return; - } - - // Otherwise, the value will be merged in here as a result of CallSite - // handling. -} - void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) { Value *Aggr = EVI.getAggregateOperand(); @@ -1267,11 +1231,6 @@ CallOverdefined: // currently handled conservatively. for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI) { - if (GetResultInst *GRI = dyn_cast<GetResultInst>(*UI)) { - mergeInValue(GRI, - TrackedMultipleRetVals[std::make_pair(F, GRI->getIndex())]); - continue; - } if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(*UI)) { if (EVI->getNumIndices() == 1) { mergeInValue(EVI, diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 22dab69846..a198356fd2 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -442,17 +442,7 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) { // uses of the returned value. if (!TheCall->use_empty()) { ReturnInst *R = Returns[0]; - if (isa<StructType>(TheCall->getType()) && - TheCall->getType() != R->getOperand(0)->getType()) { - // Multiple-value return statements. - while (!TheCall->use_empty()) { - GetResultInst *GR = cast<GetResultInst>(TheCall->use_back()); - Value *RV = R->getOperand(GR->getIndex()); - GR->replaceAllUsesWith(RV); - GR->eraseFromParent(); - } - } else - TheCall->replaceAllUsesWith(R->getReturnValue()); + TheCall->replaceAllUsesWith(R->getReturnValue()); } // Since we are now done with the Call/Invoke, we can delete it. TheCall->eraseFromParent(); @@ -508,63 +498,27 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) { // Handle all of the return instructions that we just cloned in, and eliminate // any users of the original call/invoke instruction. const Type *RTy = CalledFunc->getReturnType(); - const StructType *STy = dyn_cast<StructType>(RTy); - - // We do special handling for multiple-value return statements. If this is - // a plain aggregate return, don't do the special handling. - if (!Returns.empty() && Returns[0]->getNumOperands() != 0 && - Returns[0]->getOperand(0)->getType() == STy) - STy = 0; - if (Returns.size() > 1 || STy) { + if (Returns.size() > 1) { // The PHI node should go at the front of the new basic block to merge all // possible incoming values. - SmallVector<PHINode *, 4> PHIs; + PHINode *PHI = 0; if (!TheCall->use_empty()) { - if (STy) { - unsigned NumRetVals = STy->getNumElements(); - // Create new phi nodes such that phi node number in the PHIs vector - // match corresponding return value operand number. - Instruction *InsertPt = AfterCallBB->begin(); - for (unsigned i = 0; i < NumRetVals; ++i) { - PHINode *PHI = PHINode::Create(STy->getElementType(i), - TheCall->getName() + "." + utostr(i), - InsertPt); - PHIs.push_back(PHI); - } - // TheCall results are used by GetResult instructions. - while (!TheCall->use_empty()) { - GetResultInst *GR = cast<GetResultInst>(TheCall->use_back()); - GR->replaceAllUsesWith(PHIs[GR->getIndex()]); - GR->eraseFromParent(); - } - } else { - PHINode *PHI = PHINode::Create(RTy, TheCall->getName(), - AfterCallBB->begin()); - PHIs.push_back(PHI); - // Anything that used the result of the function call should now use the - // PHI node as their operand. - TheCall->replaceAllUsesWith(PHI); - } + PHI = PHINode::Create(RTy, TheCall->getName(), + AfterCallBB->begin()); + // Anything that used the result of the function call should now use the + // PHI node as their operand. + TheCall->replaceAllUsesWith(PHI); } // Loop over all of the return instructions adding entries to the PHI node as // appropriate. - if (!PHIs.empty()) { - // There is atleast one return value. - unsigned NumRetVals = 1; - if (STy) - NumRetVals = STy->getNumElements(); - for (unsigned j = 0; j < NumRetVals; ++j) { - PHINode *PHI = PHIs[j]; - // Each PHI node will receive one value from each return instruction. - for(unsigned i = 0, e = Returns.size(); i != e; ++i) { - ReturnInst *RI = Returns[i]; - assert(RI->getReturnValue(j)->getType() == PHI->getType() && - "Ret value not consistent in function!"); - PHI->addIncoming(RI->getReturnValue(j /*PHI number matches operand number*/), - RI->getParent()); - } + if (PHI) { + for (unsigned i = 0, e = Returns.size(); i != e; ++i) { + ReturnInst *RI = Returns[i]; + assert(RI->getReturnValue()->getType() == PHI->getType() && + "Ret value not consistent in function!"); + PHI->addIncoming(RI->getReturnValue(), RI->getParent()); } } diff --git a/lib/Transforms/Utils/LCSSA.cpp b/lib/Transforms/Utils/LCSSA.cpp index d94cd594ba..55d7a48593 100644 --- a/lib/Transforms/Utils/LCSSA.cpp +++ b/lib/Transforms/Utils/LCSSA.cpp @@ -217,27 +217,7 @@ void LCSSA::getLoopValuesUsedOutsideLoop(Loop *L, } if (*BB != UserBB && !inLoop(UserBB)) { - const StructType *STy = dyn_cast<StructType>(I->getType()); - if (STy) { - // I is a call or an invoke that returns multiple values. - // These values are accessible through getresult only. - // If the getresult value is not in the BB then move it - // immediately here. It will be processed in next iteration. - BasicBlock::iterator InsertPoint; - if (InvokeInst *II = dyn_cast<InvokeInst>(I)) { - InsertPoint = II->getNormalDest()->getFirstNonPHI(); - } else { - InsertPoint = I; - InsertPoint++; - } - for (Value::use_iterator TmpI = I->use_begin(), - TmpE = I->use_end(); TmpI != TmpE; ++TmpI) { - GetResultInst *GR = cast<GetResultInst>(TmpI); - if (GR->getParent() != *BB) - GR->moveBefore(InsertPoint); - } - } else - AffectedValues.insert(I); + AffectedValues.insert(I); break; } } diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 2fc859e88d..d04fce6892 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1357,40 +1357,31 @@ static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) { return true; } - // Otherwise, build up the result values for the new return. - SmallVector<Value*, 4> TrueResult; - SmallVector<Value*, 4> FalseResult; + // Otherwise, figure out what the true and false return values are + // so we can insert a new select instruction. + Value *TrueValue = TrueRet->getReturnValue(); + Value *FalseValue = FalseRet->getReturnValue(); + + // Unwrap any PHI nodes in the return blocks. + if (PHINode *TVPN = dyn_cast_or_null<PHINode>(TrueValue)) + if (TVPN->getParent() == TrueSucc) + TrueValue = TVPN->getIncomingValueForBlock(BI->getParent()); + if (PHINode *FVPN = dyn_cast_or_null<PHINode>(FalseValue)) + if (FVPN->getParent() == FalseSucc) + FalseValue = FVPN->getIncomingValueForBlock(BI->getParent()); + + // In order for this transformation to be safe, we must be able to + // unconditionally execute both operands to the return. This is + // normally the case, but we could have a potentially-trapping + // constant expression that prevents this transformation from being + // safe. + if (ConstantExpr *TCV = dyn_cast_or_null<ConstantExpr>(TrueValue)) + if (TCV->canTrap()) + return false; + if (ConstantExpr *FCV = dyn_cast_or_null<ConstantExpr>(FalseValue)) + if (FCV->canTrap()) + return false; - for (unsigned i = 0, e = TrueRet->getNumOperands(); i != e; ++i) { - // Otherwise, figure out what the true and false return values are - // so we can insert a new select instruction. - Value *TrueValue = TrueRet->getOperand(i); - Value *FalseValue = FalseRet->getOperand(i); - - // Unwrap any PHI nodes in the return blocks. - if (PHINode *TVPN = dyn_cast<PHINode>(TrueValue)) - if (TVPN->getParent() == TrueSucc) - TrueValue = TVPN->getIncomingValueForBlock(BI->getParent()); - if (PHINode *FVPN = dyn_cast<PHINode>(FalseValue)) - if (FVPN->getParent() == FalseSucc) - FalseValue = FVPN->getIncomingValueForBlock(BI->getParent()); - - // In order for this transformation to be safe, we must be able to - // unconditionally execute both operands to the return. This is - // normally the case, but we could have a potentially-trapping - // constant expression that prevents this transformation from being - // safe. - if (ConstantExpr *TCV = dyn_cast<ConstantExpr>(TrueValue)) - if (TCV->canTrap()) - return false; - if (ConstantExpr *FCV = dyn_cast<ConstantExpr>(FalseValue)) - if (FCV->canTrap()) - return false; - - TrueResult.push_back(TrueValue); - FalseResult.push_back(FalseValue); - } - // Okay, we collected all the mapped values and checked them for sanity, and // defined to really do this transformation. First, update the CFG. TrueSucc->removePredecessor(BI->getParent()); @@ -1398,20 +1389,20 @@ static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) { // Insert select instructions where needed. Value *BrCond = BI->getCondition(); - for (unsigned i = 0, e = TrueRet->getNumOperands(); i != e; ++i) { + if (TrueValue) { // Insert a select if the results differ. - if (TrueResult[i] == FalseResult[i] || isa<UndefValue>(FalseResult[i])) - continue; - if (isa<UndefValue>(TrueResult[i])) { - TrueResult[i] = FalseResult[i]; - continue; + if (TrueValue == FalseValue || isa<UndefValue>(FalseValue)) { + } else if (isa<UndefValue>(TrueValue)) { + TrueValue = FalseValue; + } else { + TrueValue = SelectInst::Create(BrCond, TrueValue, + FalseValue, "retval", BI); } - - TrueResult[i] = SelectInst::Create(BrCond, TrueResult[i], - FalseResult[i], "retval", BI); } - Value *RI = ReturnInst::Create(&TrueResult[0], TrueResult.size(), BI); + Value *RI = !TrueValue ? + ReturnInst::Create(BI) : + ReturnInst::Create(TrueValue, BI); DOUT << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:" << "\n " << *BI << "NewRet = " << *RI diff --git a/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp index c024d32374..ba58fbd987 100644 --- a/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +++ b/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -110,32 +110,13 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) { // BasicBlock *NewRetBlock = BasicBlock::Create("UnifiedReturnBlock", &F); - SmallVector<Value *, 4> Phis; - unsigned NumRetVals = ReturningBlocks[0]->getTerminator()->getNumOperands(); - if (NumRetVals == 0) + PHINode *PN = 0; + if (F.getReturnType() == Type::VoidTy) { ReturnInst::Create(NULL, NewRetBlock); - else if (const StructType *STy = dyn_cast<StructType>(F.getReturnType())) { - Instruction *InsertPt = NULL; - if (NumRetVals == 0) - InsertPt = NewRetBlock->getFirstNonPHI(); - PHINode *PN = NULL; - for (unsigned i = 0; i < NumRetVals; ++i) { - if (InsertPt) - PN = PHINode::Create(STy->getElementType(i), "UnifiedRetVal." - + utostr(i), InsertPt); - else - PN = PHINode::Create(STy->getElementType(i), "UnifiedRetVal." - + utostr(i), NewRetBlock); - Phis.push_back(PN); - InsertPt = PN; - } - ReturnInst::Create(&Phis[0], NumRetVals, NewRetBlock); - } - else { + } else { // If the function doesn't return void... add a PHI node to the block... - PHINode *PN = PHINode::Create(F.getReturnType(), "UnifiedRetVal"); + PN = PHINode::Create(F.getReturnType(), "UnifiedRetVal"); NewRetBlock->getInstList().push_back(PN); - Phis.push_back(PN); ReturnInst::Create(PN, NewRetBlock); } @@ -148,11 +129,8 @@ 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 (!Phis.empty()) { - for (unsigned i = 0; i < NumRetVals; ++i) - cast<PHINode>(Phis[i])->addIncoming(BB->getTerminator()->getOperand(i), - BB); - } + if (PN) + PN->addIncoming(BB->getTerminator()->getOperand(0), BB); BB->getInstList().pop_back(); // Remove the return insn BranchInst::Create(NewRetBlock, BB); |