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.

llvm-svn: 53941
This commit is contained in:
Dan Gohman 2008-07-23 00:34:11 +00:00
parent a2b4b4ad99
commit fa1211f69b
29 changed files with 167 additions and 558 deletions

View File

@ -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

View File

@ -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]

View File

@ -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);
}

View File

@ -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)

View File

@ -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

View File

@ -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))

View File

@ -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); }

View File

@ -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

View File

@ -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())

View File

@ -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)

View File

@ -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:
{

View File

@ -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.

View File

@ -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));

View File

@ -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();

View File

@ -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)) {

View File

@ -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) {

View File

@ -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

View File

@ -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));
}

View File

@ -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,

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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();
}
}
}
}

View File

@ -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";

View File

@ -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); }

View File

@ -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))) {

View File

@ -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