mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
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
This commit is contained in:
parent
5e6ebaf4d1
commit
fc74abfba5
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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); }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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); }
|
||||
|
@ -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))) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user