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 | |
parent | 5e6ebaf4d1d3043d3428b65ee8054c71c24af930 (diff) | |
download | external_llvm-fc74abfba5128544a750fce22fdf13eb0403e3ce.zip external_llvm-fc74abfba5128544a750fce22fdf13eb0403e3ce.tar.gz external_llvm-fc74abfba5128544a750fce22fdf13eb0403e3ce.tar.bz2 |
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
29 files changed, 168 insertions, 559 deletions
diff --git a/include/llvm/AutoUpgrade.h b/include/llvm/AutoUpgrade.h index 0235877..3a97353 100644 --- a/include/llvm/AutoUpgrade.h +++ b/include/llvm/AutoUpgrade.h @@ -35,12 +35,6 @@ namespace llvm { /// so that it can update all calls to the old function. void UpgradeCallsToIntrinsic(Function* F); - /// This is an auto-upgrade hook for mutiple-value return statements. - /// This function auto-upgrades all such return statements in the given - /// function to use aggregate return values built with insertvalue - /// instructions. - void UpgradeMultipleReturnValues(Function *F); - } // End llvm namespace #endif diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index ef7f870..50af9d5 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -202,6 +202,7 @@ namespace bitc { // this is so information only available in the pointer type (e.g. address // spaces) is retained. FUNC_CODE_INST_STORE2 = 24, // STORE: [ptrty,ptr,val, align, vol] + // FIXME: Remove GETRESULT in favor of EXTRACTVAL in LLVM 3.0 FUNC_CODE_INST_GETRESULT = 25, // GETRESULT: [ty, opval, n] FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands] FUNC_CODE_INST_INSERTVAL = 27 // INSERTVAL: [n x operands] diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h index 0a3fbed..c8dd4e6 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/InstrTypes.h @@ -117,7 +117,6 @@ public: I->getOpcode() == Instruction::Free || I->getOpcode() == Instruction::Load || I->getOpcode() == Instruction::VAArg || - I->getOpcode() == Instruction::GetResult || I->getOpcode() == Instruction::ExtractValue || (I->getOpcode() >= CastOpsBegin && I->getOpcode() < CastOpsEnd); } diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def index 2189c86..dcc22e5 100644 --- a/include/llvm/Instruction.def +++ b/include/llvm/Instruction.def @@ -164,12 +164,10 @@ HANDLE_OTHER_INST(47, VAArg , VAArgInst ) // vaarg instruction HANDLE_OTHER_INST(48, ExtractElement, ExtractElementInst)// extract from vector HANDLE_OTHER_INST(49, InsertElement, InsertElementInst) // insert into vector HANDLE_OTHER_INST(50, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(51, GetResult, GetResultInst) // Extract individual value - //from aggregate result -HANDLE_OTHER_INST(52, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(53, InsertValue, InsertValueInst) // insert into aggregate -HANDLE_OTHER_INST(54, VICmp , VICmpInst ) // Vec Int comparison instruction. -HANDLE_OTHER_INST(55, VFCmp , VFCmpInst ) // Vec FP point comparison instr. +HANDLE_OTHER_INST(51, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(52, InsertValue, InsertValueInst) // insert into aggregate +HANDLE_OTHER_INST(53, VICmp , VICmpInst ) // Vec Int comparison instruction. +HANDLE_OTHER_INST(54, VFCmp , VFCmpInst ) // Vec FP point comparison instr. LAST_OTHER_INST(55) diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index d625293..41daca3 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -2000,7 +2000,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value) /// class ReturnInst : public TerminatorInst { ReturnInst(const ReturnInst &RI); - void init(Value * const* retVals, unsigned N); private: // ReturnInst constructors: @@ -2011,16 +2010,11 @@ private: // ReturnInst(Value* X, Inst *I) - 'ret X' instruction, insert before I // ReturnInst( null, BB *B) - 'ret void' instruction, insert @ end of B // ReturnInst(Value* X, BB *B) - 'ret X' instruction, insert @ end of B - // ReturnInst(Value* X, N) - 'ret X,X+1...X+N-1' instruction - // ReturnInst(Value* X, N, Inst *I) - 'ret X,X+1...X+N-1', insert before I - // ReturnInst(Value* X, N, BB *B) - 'ret X,X+1...X+N-1', insert @ end of B // // NOTE: If the Value* passed is of type void then the constructor behaves as // if it was passed NULL. explicit ReturnInst(Value *retVal = 0, Instruction *InsertBefore = 0); ReturnInst(Value *retVal, BasicBlock *InsertAtEnd); - ReturnInst(Value * const* retVals, unsigned N, Instruction *InsertBefore = 0); - ReturnInst(Value * const* retVals, unsigned N, BasicBlock *InsertAtEnd); explicit ReturnInst(BasicBlock *InsertAtEnd); public: static ReturnInst* Create(Value *retVal = 0, Instruction *InsertBefore = 0) { @@ -2029,19 +2023,10 @@ public: static ReturnInst* Create(Value *retVal, BasicBlock *InsertAtEnd) { return new(!!retVal) ReturnInst(retVal, InsertAtEnd); } - static ReturnInst* Create(Value * const* retVals, unsigned N, - Instruction *InsertBefore = 0) { - return new(N) ReturnInst(retVals, N, InsertBefore); - } - static ReturnInst* Create(Value * const* retVals, unsigned N, - BasicBlock *InsertAtEnd) { - return new(N) ReturnInst(retVals, N, InsertAtEnd); - } static ReturnInst* Create(BasicBlock *InsertAtEnd) { return new(0) ReturnInst(InsertAtEnd); } virtual ~ReturnInst(); - inline void operator delete(void*); virtual ReturnInst *clone() const; @@ -2072,16 +2057,10 @@ public: }; template <> -struct OperandTraits<ReturnInst> : VariadicOperandTraits<> { +struct OperandTraits<ReturnInst> : OptionalOperandTraits<> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value) -void ReturnInst::operator delete(void *it) { - ReturnInst* me(static_cast<ReturnInst*>(it)); - Use::zap(OperandTraits<ReturnInst>::op_begin(me), - OperandTraits<ReturnInst>::op_end(me), - true); -} //===----------------------------------------------------------------------===// // BranchInst Class @@ -3126,53 +3105,6 @@ public: } }; -//===----------------------------------------------------------------------===// -// GetResultInst Class -//===----------------------------------------------------------------------===// - -/// GetResultInst - This instruction extracts individual result value from -/// aggregate value, where aggregate value is returned by CallInst. -/// -class GetResultInst : public UnaryInstruction { - unsigned Idx; - GetResultInst(const GetResultInst &GRI) : - UnaryInstruction(GRI.getType(), Instruction::GetResult, GRI.getOperand(0)), - Idx(GRI.Idx) { - } - -public: - GetResultInst(Value *Aggr, unsigned index, - const std::string &Name = "", - Instruction *InsertBefore = 0); - - /// isValidOperands - Return true if an getresult instruction can be - /// formed with the specified operands. - static bool isValidOperands(const Value *Aggr, unsigned index); - - virtual GetResultInst *clone() const; - - Value *getAggregateValue() { - return getOperand(0); - } - - const Value *getAggregateValue() const { - return getOperand(0); - } - - unsigned getIndex() const { - return Idx; - } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const GetResultInst *) { return true; } - static inline bool classof(const Instruction *I) { - return (I->getOpcode() == Instruction::GetResult); - } - static inline bool classof(const Value *V) { - return isa<Instruction>(V) && classof(cast<Instruction>(V)); - } -}; - } // End llvm namespace #endif diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 95d9c5a..b025d4c 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -102,7 +102,15 @@ public: } ReturnInst *CreateRet(Value * const* retVals, unsigned N) { - return Insert(ReturnInst::Create(retVals, N)); + const Type *RetType = BB->getParent()->getReturnType(); + if (N == 0 && RetType == Type::VoidTy) + return CreateRetVoid(); + if (N == 1 && retVals[0]->getType() == RetType) + return Insert(ReturnInst::Create(retVals[0])); + Value *V = UndefValue::get(RetType); + for (unsigned i = 0; i != N; ++i) + V = CreateInsertValue(V, retVals[i], i, "mrv"); + return Insert(ReturnInst::Create(V)); } /// CreateBr - Create an unconditional 'br label X' instruction. @@ -568,11 +576,6 @@ public: return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } - GetResultInst *CreateGetResult(Value *V, unsigned Index, - const char *Name = "") { - return Insert(new GetResultInst(V, Index), Name); - } - Value *CreateExtractValue(Value *Agg, unsigned Idx, const char *Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h index 9606187..932e7fb 100644 --- a/include/llvm/Support/InstVisitor.h +++ b/include/llvm/Support/InstVisitor.h @@ -196,7 +196,6 @@ public: RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} RetTy visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction); } RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction); } - RetTy visitGetResultInst(GetResultInst &I) { DELEGATE(Instruction); } RetTy visitExtractValueInst(ExtractValueInst &I) { DELEGATE(Instruction);} RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 42fb3b2..1da2e38 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -604,7 +604,7 @@ int LLLexer::LexIdentifier() { INSTKEYWORD("extractelement", OtherOpVal, ExtractElement, EXTRACTELEMENT); INSTKEYWORD("insertelement", OtherOpVal, InsertElement, INSERTELEMENT); INSTKEYWORD("shufflevector", OtherOpVal, ShuffleVector, SHUFFLEVECTOR); - INSTKEYWORD("getresult", OtherOpVal, GetResult, GETRESULT); + INSTKEYWORD("getresult", OtherOpVal, ExtractValue, GETRESULT); INSTKEYWORD("extractvalue", OtherOpVal, ExtractValue, EXTRACTVALUE); INSTKEYWORD("insertvalue", OtherOpVal, InsertValue, INSERTVALUE); #undef INSTKEYWORD diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 6f483fa..b9d5616 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -2704,7 +2704,20 @@ BBTerminatorInst : RET ReturnedVal { // Return with a result... ValueList &VL = *$2; assert(!VL.empty() && "Invalid ret operands!"); - $$ = ReturnInst::Create(&VL[0], VL.size()); + const Type *ReturnType = CurFun.CurrentFunction->getReturnType(); + if (VL.size() > 1 || + (isa<StructType>(ReturnType) && + (VL.empty() || VL[0]->getType() != ReturnType))) { + Value *RV = UndefValue::get(ReturnType); + for (unsigned i = 0, e = VL.size(); i != e; ++i) { + Instruction *I = InsertValueInst::Create(RV, VL[i], i, "mrv"); + ($<BasicBlockVal>-1)->getInstList().push_back(I); + RV = I; + } + $$ = ReturnInst::Create(RV); + } else { + $$ = ReturnInst::Create(VL[0]); + } delete $2; CHECK_FOR_ERROR } @@ -3309,12 +3322,18 @@ MemoryInst : MALLOC Types OptCAlign { delete $5; } | GETRESULT Types ValueRef ',' EUINT64VAL { - Value *TmpVal = getVal($2->get(), $3); - if (!GetResultInst::isValidOperands(TmpVal, $5)) - GEN_ERROR("Invalid getresult operands"); - $$ = new GetResultInst(TmpVal, $5); - delete $2; + if (!UpRefs.empty()) + GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription()); + if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get())) + GEN_ERROR("getresult insn requires an aggregate operand"); + if (!ExtractValueInst::getIndexedType(*$2, $5)) + GEN_ERROR("Invalid getresult index for type '" + + (*$2)->getDescription()+ "'"); + + Value *tmpVal = getVal(*$2, $3); CHECK_FOR_ERROR + $$ = ExtractValueInst::Create(tmpVal, $5); + delete $2; } | GETELEMENTPTR Types ValueRef IndexList { if (!UpRefs.empty()) diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 3e2af4f..f7796a6 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1472,7 +1472,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { Value *Op; getValueTypePair(Record, OpNum, NextValueNo, Op); unsigned Index = Record[1]; - I = new GetResultInst(Op, Index); + I = ExtractValueInst::Create(Op, Index); break; } @@ -1482,20 +1482,34 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { if (Size == 0) { I = ReturnInst::Create(); break; - } else { - unsigned OpNum = 0; - SmallVector<Value *,4> Vs; - do { - Value *Op = NULL; - if (getValueTypePair(Record, OpNum, NextValueNo, Op)) - return Error("Invalid RET record"); - Vs.push_back(Op); - } while(OpNum != Record.size()); - - // SmallVector Vs has at least one element. - I = ReturnInst::Create(&Vs[0], Vs.size()); + } + + unsigned OpNum = 0; + SmallVector<Value *,4> Vs; + do { + Value *Op = NULL; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid RET record"); + Vs.push_back(Op); + } while(OpNum != Record.size()); + + const Type *ReturnType = F->getReturnType(); + if (Vs.size() > 1 || + (isa<StructType>(ReturnType) && + (Vs.empty() || Vs[0]->getType() != ReturnType))) { + Value *RV = UndefValue::get(ReturnType); + for (unsigned i = 0, e = Vs.size(); i != e; ++i) { + I = InsertValueInst::Create(RV, Vs[i], i, "mrv"); + CurBB->getInstList().push_back(I); + ValueList.AssignValue(I, NextValueNo++); + RV = I; + } + I = ReturnInst::Create(RV); break; } + + I = ReturnInst::Create(Vs[0]); + break; } case bitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#] if (Record.size() != 1 && Record.size() != 3) diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index f4d7359..2c585b1 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -768,11 +768,6 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, Vals.push_back(VE.getValueID(I.getOperand(1))); Vals.push_back(cast<CmpInst>(I).getPredicate()); break; - case Instruction::GetResult: - Code = bitc::FUNC_CODE_INST_GETRESULT; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - Vals.push_back(cast<GetResultInst>(I).getIndex()); - break; case Instruction::Ret: { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 12c54c1..fdc3d25 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -806,8 +806,6 @@ public: void visitVAEnd(CallInst &I); void visitVACopy(CallInst &I); - void visitGetResult(GetResultInst &I); - void visitUserOp1(Instruction &I) { assert(0 && "UserOp1 should not exist at instruction selection time!"); abort(); @@ -3688,24 +3686,6 @@ void SelectionDAGLowering::visitCall(CallInst &I) { } -void SelectionDAGLowering::visitGetResult(GetResultInst &I) { - if (isa<UndefValue>(I.getOperand(0))) { - SDOperand Undef = DAG.getNode(ISD::UNDEF, TLI.getValueType(I.getType())); - setValue(&I, Undef); - return; - } - - // To add support for individual return values with aggregate types, - // we'd need a way to take a getresult index and determine which - // values of the Call SDNode are associated with it. - assert(TLI.getValueType(I.getType(), true) != MVT::Other && - "Individual return values must not be aggregates!"); - - SDOperand Call = getValue(I.getOperand(0)); - setValue(&I, SDOperand(Call.Val, I.getIndex())); -} - - /// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from /// this value and returns the result as a ValueVT value. This uses /// Chain/Flag as the input and updates them for the output Chain/Flag. diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 34511e8..cda81e4 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -285,7 +285,6 @@ namespace { void visitInsertElementInst(InsertElementInst &I); void visitExtractElementInst(ExtractElementInst &I); void visitShuffleVectorInst(ShuffleVectorInst &SVI); - void visitGetResultInst(GetResultInst &GRI); void visitInsertValueInst(InsertValueInst &I); void visitExtractValueInst(ExtractValueInst &I); @@ -3325,18 +3324,6 @@ void CWriter::visitShuffleVectorInst(ShuffleVectorInst &SVI) { Out << "}"; } -void CWriter::visitGetResultInst(GetResultInst &GRI) { - Out << "("; - if (isa<UndefValue>(GRI.getOperand(0))) { - Out << "("; - printType(Out, GRI.getType()); - Out << ") 0/*UNDEF*/"; - } else { - Out << GetValueName(GRI.getOperand(0)) << ".field" << GRI.getIndex(); - } - Out << ")"; -} - void CWriter::visitInsertValueInst(InsertValueInst &IVI) { // Start by copying the entire aggregate value into the result variable. writeOperand(IVI.getOperand(0)); diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp index fa004fd..42c02e6 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 94bf4c6..aa74944 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 861badf..da98d0a 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 4e57f0e..1d3bfbf 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 38364c1..f0dd40b 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 ff88137..d52cef6 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 22dab69..a198356 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 d94cd59..55d7a48 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 2fc859e..d04fce6 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 c024d32..ba58fbd 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); diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 9e01005..98c6fef 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1299,9 +1299,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(op ), false); Out << ','; writeOperand(I.getOperand(op+1), false); Out << " ]"; } - } else if (const GetResultInst *GRI = dyn_cast<GetResultInst>(&I)) { - writeOperand(I.getOperand(0), true); - Out << ", " << GRI->getIndex(); } else if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(&I)) { writeOperand(I.getOperand(0), true); for (const unsigned *i = EVI->idx_begin(), *e = EVI->idx_end(); i != e; ++i) diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index fd7d6dc..a48fbd2 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -414,31 +414,3 @@ void llvm::UpgradeCallsToIntrinsic(Function* F) { } } } - -/// This is an auto-upgrade hook for mutiple-value return statements. -/// This function auto-upgrades all such return statements in the given -/// function to use aggregate return values built with insertvalue -/// instructions. -void llvm::UpgradeMultipleReturnValues(Function *CurrentFunction) { - const Type *ReturnType = CurrentFunction->getReturnType(); - for (Function::iterator I = CurrentFunction->begin(), - E = CurrentFunction->end(); I != E; ++I) { - BasicBlock *BB = I; - if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { - unsigned NumVals = RI->getNumOperands(); - if (NumVals > 1 || - (isa<StructType>(ReturnType) && - (NumVals == 0 || RI->getOperand(0)->getType() != ReturnType))) { - std::vector<const Type *> Types(NumVals); - for (unsigned i = 0; i != NumVals; ++i) - Types[i] = RI->getOperand(i)->getType(); - const Type *ReturnType = StructType::get(Types); - Value *RV = UndefValue::get(ReturnType); - for (unsigned i = 0; i != NumVals; ++i) - RV = InsertValueInst::Create(RV, RI->getOperand(i), i, "mrv", RI); - ReturnInst::Create(RV, RI); - RI->eraseFromParent(); - } - } - } -} diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index e8738d2..97334b3 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -146,7 +146,6 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case ExtractElement: return "extractelement"; case InsertElement: return "insertelement"; case ShuffleVector: return "shufflevector"; - case GetResult: return "getresult"; case ExtractValue: return "extractvalue"; case InsertValue: return "insertvalue"; diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 36c3de7..3906c52 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -500,75 +500,30 @@ void InvokeInst::removeParamAttr(unsigned i, ParameterAttributes attr) { ReturnInst::ReturnInst(const ReturnInst &RI) : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this) - - RI.getNumOperands(), + OperandTraits<ReturnInst>::op_end(this) - + RI.getNumOperands(), RI.getNumOperands()) { - unsigned N = RI.getNumOperands(); - if (N == 1) + if (RI.getNumOperands()) Op<0>() = RI.Op<0>(); - else if (N) { - Use *OL = OperandList; - for (unsigned i = 0; i < N; ++i) - OL[i] = RI.getOperand(i); - } } ReturnInst::ReturnInst(Value *retVal, Instruction *InsertBefore) : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this) - (retVal != 0), - retVal != 0, InsertBefore) { + OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal, + InsertBefore) { if (retVal) - init(&retVal, 1); + Op<0>() = retVal; } ReturnInst::ReturnInst(Value *retVal, BasicBlock *InsertAtEnd) : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this) - (retVal != 0), - retVal != 0, InsertAtEnd) { + OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal, + InsertAtEnd) { if (retVal) - init(&retVal, 1); + Op<0>() = retVal; } ReturnInst::ReturnInst(BasicBlock *InsertAtEnd) : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this), - 0, InsertAtEnd) { -} - -ReturnInst::ReturnInst(Value * const* retVals, unsigned N, - Instruction *InsertBefore) - : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this) - N, - N, InsertBefore) { - if (N != 0) - init(retVals, N); -} -ReturnInst::ReturnInst(Value * const* retVals, unsigned N, - BasicBlock *InsertAtEnd) - : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this) - N, - N, InsertAtEnd) { - if (N != 0) - init(retVals, N); -} - -void ReturnInst::init(Value * const* retVals, unsigned N) { - assert (N > 0 && "Invalid operands numbers in ReturnInst init"); - - NumOperands = N; - if (NumOperands == 1) { - Value *V = *retVals; - if (V->getType() == Type::VoidTy) - return; - Op<0>() = V; - return; - } - - Use *OL = OperandList; - for (unsigned i = 0; i < NumOperands; ++i) { - Value *V = *retVals++; - assert(!isa<BasicBlock>(V) && - "Cannot return basic block. Probably using the incorrect ctor"); - OL[i] = V; - } + OperandTraits<ReturnInst>::op_end(this), 0, InsertAtEnd) { } unsigned ReturnInst::getNumSuccessorsV() const { @@ -2855,43 +2810,6 @@ void SwitchInst::setSuccessorV(unsigned idx, BasicBlock *B) { setSuccessor(idx, B); } -//===----------------------------------------------------------------------===// -// GetResultInst Implementation -//===----------------------------------------------------------------------===// - -GetResultInst::GetResultInst(Value *Aggregate, unsigned Index, - const std::string &Name, - Instruction *InsertBef) - : UnaryInstruction(cast<StructType>(Aggregate->getType()) - ->getElementType(Index), - GetResult, Aggregate, InsertBef), - Idx(Index) { - assert(isValidOperands(Aggregate, Index) - && "Invalid GetResultInst operands!"); - setName(Name); -} - -bool GetResultInst::isValidOperands(const Value *Aggregate, unsigned Index) { - if (!Aggregate) - return false; - - if (const StructType *STy = dyn_cast<StructType>(Aggregate->getType())) { - unsigned NumElements = STy->getNumElements(); - if (Index >= NumElements || NumElements == 0) - return false; - - // getresult aggregate value's element types are restricted to - // avoid nested aggregates. - for (unsigned i = 0; i < NumElements; ++i) - if (!STy->getElementType(i)->isFirstClassType()) - return false; - - // Otherwise, Aggregate is valid. - return true; - } - return false; -} - // Define these methods here so vtables don't get emitted into every translation // unit that uses these classes. @@ -2972,4 +2890,3 @@ InvokeInst *InvokeInst::clone() const { } UnwindInst *UnwindInst::clone() const { return new UnwindInst(); } UnreachableInst *UnreachableInst::clone() const { return new UnreachableInst();} -GetResultInst *GetResultInst::clone() const { return new GetResultInst(*this); } diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 79c24f3..0aef414 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -259,7 +259,8 @@ namespace { void visitUserOp2(Instruction &I) { visitUserOp1(I); } void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI); void visitAllocationInst(AllocationInst &AI); - void visitGetResultInst(GetResultInst &GRI); + void visitExtractValueInst(ExtractValueInst &EVI); + void visitInsertValueInst(InsertValueInst &IVI); void VerifyCallSite(CallSite CS); void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, @@ -1090,18 +1091,23 @@ void Verifier::visitAllocationInst(AllocationInst &AI) { visitInstruction(AI); } -void Verifier::visitGetResultInst(GetResultInst &GRI) { - Assert1(GetResultInst::isValidOperands(GRI.getAggregateValue(), - GRI.getIndex()), - "Invalid GetResultInst operands!", &GRI); - Assert1(isa<CallInst>(GRI.getAggregateValue()) || - isa<InvokeInst>(GRI.getAggregateValue()) || - isa<UndefValue>(GRI.getAggregateValue()), - "GetResultInst operand must be a call/invoke/undef!", &GRI); +void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { + Assert1(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(), + EVI.idx_begin(), EVI.idx_end()) == + EVI.getType(), + "Invalid ExtractValueInst operands!", &EVI); - visitInstruction(GRI); + visitInstruction(EVI); } +void Verifier::visitInsertValueInst(InsertValueInst &IVI) { + Assert1(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(), + IVI.idx_begin(), IVI.idx_end()) == + IVI.getOperand(1)->getType(), + "Invalid InsertValueInst operands!", &IVI); + + visitInstruction(IVI); +} /// verifyInstruction - Verify that an instruction is well formed. /// @@ -1151,20 +1157,7 @@ void Verifier::visitInstruction(Instruction &I) { // Check to make sure that only first-class-values are operands to // instructions. if (!I.getOperand(i)->getType()->isFirstClassType()) { - if (isa<ReturnInst>(I) || isa<GetResultInst>(I)) - Assert1(isa<StructType>(I.getOperand(i)->getType()), - "Invalid ReturnInst operands!", &I); - else if (isa<CallInst>(I) || isa<InvokeInst>(I)) { - if (const PointerType *PT = dyn_cast<PointerType> - (I.getOperand(i)->getType())) { - const Type *ETy = PT->getElementType(); - Assert1(isa<StructType>(ETy), "Invalid CallInst operands!", &I); - } - else - Assert1(0, "Invalid CallInst operands!", &I); - } - else - Assert1(0, "Instruction operands must be first-class values!", &I); + Assert1(0, "Instruction operands must be first-class values!", &I); } if (Function *F = dyn_cast<Function>(I.getOperand(i))) { diff --git a/test/Transforms/SCCP/2008-03-10-sret.ll b/test/Transforms/SCCP/2008-03-10-sret.ll index f5bc00d..dd196c7 100644 --- a/test/Transforms/SCCP/2008-03-10-sret.ll +++ b/test/Transforms/SCCP/2008-03-10-sret.ll @@ -1,5 +1,8 @@ -; RUN: llvm-as < %s | opt -ipsccp | llvm-dis | grep {ret i32 36} -; RUN: llvm-as < %s | opt -ipsccp | llvm-dis | grep {ret i32 18, i32 17} +; RUN: llvm-as < %s | opt -ipsccp | llvm-dis > %t +; RUN: grep {ret i32 36} %t +; RUN: grep {%mrv = insertvalue \{ i32, i32 \} undef, i32 18, 0} %t +; RUN: grep {%mrv1 = insertvalue \{ i32, i32 \} %mrv, i32 17, 1} %t +; RUN: grep {ret \{ i32, i32 \} %mrv1} %t define internal {i32, i32} @bar(i32 %A) { %X = add i32 1, %A |