When processing function arguments when splitting live ranges across invokes,

handle structs passed by value via an extract/insert pair, as a bitcast
won't work on a struct. rdar://7742824

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105280 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach
2010-06-01 18:04:09 +00:00
parent 601f9d6c03
commit dc58b25ebc

View File

@ -202,17 +202,34 @@ splitLiveRangesLiveAcrossInvokes(SmallVector<InvokeInst*,16> &Invokes) {
++AfterAllocaInsertPt; ++AfterAllocaInsertPt;
for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end();
AI != E; ++AI) { AI != E; ++AI) {
// This is always a no-op cast because we're casting AI to AI->getType() so const Type *Ty = AI->getType();
// src and destination types are identical. BitCast is the only possibility. // StructType can't be cast, but is a legal argument type, so we have
// to handle them differently. We use an extract/insert pair as a
// lightweight method to achieve the same goal.
if (isa<StructType>(Ty)) {
Instruction *EI = ExtractValueInst::Create(AI, 0, "", AfterAllocaInsertPt);
Instruction *NI = InsertValueInst::Create(AI, EI, 0);
NI->insertAfter(EI);
AI->replaceAllUsesWith(NI);
// Set the struct operand of the instructions back to the AllocaInst.
EI->setOperand(0, AI);
NI->setOperand(0, AI);
} else {
// This is always a no-op cast because we're casting AI to AI->getType()
// so src and destination types are identical. BitCast is the only
// possibility.
CastInst *NC = new BitCastInst( CastInst *NC = new BitCastInst(
AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt);
AI->replaceAllUsesWith(NC); AI->replaceAllUsesWith(NC);
// Normally its is forbidden to replace a CastInst's operand because it // Set the operand of the cast instruction back to the AllocaInst.
// could cause the opcode to reflect an illegal conversion. However, we're // Normally it's forbidden to replace a CastInst's operand because it
// replacing it here with the same value it was constructed with to simply // could cause the opcode to reflect an illegal conversion. However,
// make NC its user. // we're replacing it here with the same value it was constructed with.
// We do this because the above replaceAllUsesWith() clobbered the
// operand, but we want this one to remain.
NC->setOperand(0, AI); NC->setOperand(0, AI);
} }
}
// Finally, scan the code looking for instructions with bad live ranges. // Finally, scan the code looking for instructions with bad live ranges.
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)