summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/AutoUpgrade.h6
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h1
-rw-r--r--include/llvm/InstrTypes.h1
-rw-r--r--include/llvm/Instruction.def10
-rw-r--r--include/llvm/Instructions.h70
-rw-r--r--include/llvm/Support/IRBuilder.h15
-rw-r--r--include/llvm/Support/InstVisitor.h1
-rw-r--r--lib/AsmParser/LLLexer.cpp2
-rw-r--r--lib/AsmParser/llvmAsmParser.y31
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp40
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp5
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp20
-rw-r--r--lib/Target/CBackend/CBackend.cpp13
-rw-r--r--lib/Transforms/IPO/IPConstantPropagation.cpp4
-rw-r--r--lib/Transforms/IPO/StructRetPromotion.cpp24
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp4
-rw-r--r--lib/Transforms/Scalar/JumpThreading.cpp15
-rw-r--r--lib/Transforms/Scalar/LoopRotation.cpp34
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp41
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp74
-rw-r--r--lib/Transforms/Utils/LCSSA.cpp22
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp77
-rw-r--r--lib/Transforms/Utils/UnifyFunctionExitNodes.cpp34
-rw-r--r--lib/VMCore/AsmWriter.cpp3
-rw-r--r--lib/VMCore/AutoUpgrade.cpp28
-rw-r--r--lib/VMCore/Instruction.cpp1
-rw-r--r--lib/VMCore/Instructions.cpp103
-rw-r--r--lib/VMCore/Verifier.cpp41
-rw-r--r--test/Transforms/SCCP/2008-03-10-sret.ll7
29 files changed, 168 insertions, 559 deletions
diff --git a/include/llvm/AutoUpgrade.h b/include/llvm/AutoUpgrade.h
index 023587790f..3a97353ac9 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 ef7f870c1a..50af9d5dd6 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 0a3fbed804..c8dd4e6ef1 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 2189c86cfb..dcc22e51c2 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 d6252932fa..41daca3233 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 95d9c5a060..b025d4c657 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 9606187508..932e7fbb7f 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 42fb3b2d32..1da2e383ab 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 6f483fa92d..b9d561633c 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 3e2af4f172..f7796a6f9f 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 f4d73598b9..2c585b1370 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 12c54c1eef..fdc3d25bd5 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 34511e8a3a..cda81e428d 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 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);
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 9e010051a5..98c6fefad7 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 fd7d6dcd4c..a48fbd2c90 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 e8738d2ba7..97334b3e24 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 36c3de72ce..3906c521c2 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 79c24f334c..0aef414a68 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 f5bc00de50..dd196c70b9 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