mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 05:24:01 +00:00
[unwind removal] We no longer have 'unwind' instructions being generated, so
remove the code that handles them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149901 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -386,8 +386,8 @@ void BallLarusDag::buildNode(BLBlockNodeMap& inDag, BLNodeStack& dfsStack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TerminatorInst* terminator = currentNode->getBlock()->getTerminator();
|
TerminatorInst* terminator = currentNode->getBlock()->getTerminator();
|
||||||
if(isa<ReturnInst>(terminator) || isa<UnreachableInst>(terminator)
|
if(isa<ReturnInst>(terminator) || isa<UnreachableInst>(terminator) ||
|
||||||
|| isa<ResumeInst>(terminator) || isa<UnwindInst>(terminator))
|
isa<ResumeInst>(terminator))
|
||||||
addEdge(currentNode, getExit(),0);
|
addEdge(currentNode, getExit(),0);
|
||||||
|
|
||||||
currentNode->setColor(BallLarusNode::GRAY);
|
currentNode->setColor(BallLarusNode::GRAY);
|
||||||
|
@ -116,8 +116,7 @@ namespace {
|
|||||||
// Branches and invokes do not escape, only unwind, resume, and return
|
// Branches and invokes do not escape, only unwind, resume, and return
|
||||||
// do.
|
// do.
|
||||||
TerminatorInst *TI = CurBB->getTerminator();
|
TerminatorInst *TI = CurBB->getTerminator();
|
||||||
if (!isa<UnwindInst>(TI) && !isa<ReturnInst>(TI) &&
|
if (!isa<ReturnInst>(TI) && !isa<ResumeInst>(TI))
|
||||||
!isa<ResumeInst>(TI))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Builder.SetInsertPoint(TI->getParent(), TI);
|
Builder.SetInsertPoint(TI->getParent(), TI);
|
||||||
|
@ -625,24 +625,6 @@ void Interpreter::visitReturnInst(ReturnInst &I) {
|
|||||||
popStackAndReturnValueToCaller(RetTy, Result);
|
popStackAndReturnValueToCaller(RetTy, Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::visitUnwindInst(UnwindInst &I) {
|
|
||||||
// Unwind stack
|
|
||||||
Instruction *Inst;
|
|
||||||
do {
|
|
||||||
ECStack.pop_back();
|
|
||||||
if (ECStack.empty())
|
|
||||||
report_fatal_error("Empty stack during unwind!");
|
|
||||||
Inst = ECStack.back().Caller.getInstruction();
|
|
||||||
} while (!(Inst && isa<InvokeInst>(Inst)));
|
|
||||||
|
|
||||||
// Return from invoke
|
|
||||||
ExecutionContext &InvokingSF = ECStack.back();
|
|
||||||
InvokingSF.Caller = CallSite();
|
|
||||||
|
|
||||||
// Go to exceptional destination BB of invoke instruction
|
|
||||||
SwitchToNewBasicBlock(cast<InvokeInst>(Inst)->getUnwindDest(), InvokingSF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Interpreter::visitUnreachableInst(UnreachableInst &I) {
|
void Interpreter::visitUnreachableInst(UnreachableInst &I) {
|
||||||
report_fatal_error("Program executed an 'unreachable' instruction!");
|
report_fatal_error("Program executed an 'unreachable' instruction!");
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,6 @@ public:
|
|||||||
void visitCallSite(CallSite CS);
|
void visitCallSite(CallSite CS);
|
||||||
void visitCallInst(CallInst &I) { visitCallSite (CallSite (&I)); }
|
void visitCallInst(CallInst &I) { visitCallSite (CallSite (&I)); }
|
||||||
void visitInvokeInst(InvokeInst &I) { visitCallSite (CallSite (&I)); }
|
void visitInvokeInst(InvokeInst &I) { visitCallSite (CallSite (&I)); }
|
||||||
void visitUnwindInst(UnwindInst &I);
|
|
||||||
void visitUnreachableInst(UnreachableInst &I);
|
void visitUnreachableInst(UnreachableInst &I);
|
||||||
|
|
||||||
void visitShl(BinaryOperator &I);
|
void visitShl(BinaryOperator &I);
|
||||||
|
@ -290,9 +290,6 @@ namespace {
|
|||||||
void visitInvokeInst(InvokeInst &I) {
|
void visitInvokeInst(InvokeInst &I) {
|
||||||
llvm_unreachable("Lowerinvoke pass didn't work!");
|
llvm_unreachable("Lowerinvoke pass didn't work!");
|
||||||
}
|
}
|
||||||
void visitUnwindInst(UnwindInst &I) {
|
|
||||||
llvm_unreachable("Lowerinvoke pass didn't work!");
|
|
||||||
}
|
|
||||||
void visitResumeInst(ResumeInst &I) {
|
void visitResumeInst(ResumeInst &I) {
|
||||||
llvm_unreachable("DwarfEHPrepare pass didn't work!");
|
llvm_unreachable("DwarfEHPrepare pass didn't work!");
|
||||||
}
|
}
|
||||||
|
@ -1142,11 +1142,6 @@ void CppWriter::printInstruction(const Instruction *I,
|
|||||||
nl(Out);
|
nl(Out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instruction::Unwind: {
|
|
||||||
Out << "new UnwindInst("
|
|
||||||
<< bbname << ");";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::Unreachable: {
|
case Instruction::Unreachable: {
|
||||||
Out << "new UnreachableInst("
|
Out << "new UnreachableInst("
|
||||||
<< "mod->getContext(), "
|
<< "mod->getContext(), "
|
||||||
|
@ -101,8 +101,7 @@ bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
|
|||||||
// Check to see if this function performs an unwind or calls an
|
// Check to see if this function performs an unwind or calls an
|
||||||
// unwinding function.
|
// unwinding function.
|
||||||
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
||||||
if (CheckUnwind && (isa<UnwindInst>(BB->getTerminator()) ||
|
if (CheckUnwind && isa<ResumeInst>(BB->getTerminator())) {
|
||||||
isa<ResumeInst>(BB->getTerminator()))) {
|
|
||||||
// Uses unwind / resume!
|
// Uses unwind / resume!
|
||||||
SCCMightUnwind = true;
|
SCCMightUnwind = true;
|
||||||
} else if (CheckReturn && isa<ReturnInst>(BB->getTerminator())) {
|
} else if (CheckReturn && isa<ReturnInst>(BB->getTerminator())) {
|
||||||
|
@ -737,8 +737,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
|||||||
// If the stack restore is in a return, resume, or unwind block and if there
|
// If the stack restore is in a return, resume, or unwind block and if there
|
||||||
// are no allocas or calls between the restore and the return, nuke the
|
// are no allocas or calls between the restore and the return, nuke the
|
||||||
// restore.
|
// restore.
|
||||||
if (!CannotRemove && (isa<ReturnInst>(TI) || isa<ResumeInst>(TI) ||
|
if (!CannotRemove && (isa<ReturnInst>(TI) || isa<ResumeInst>(TI)))
|
||||||
isa<UnwindInst>(TI)))
|
|
||||||
return EraseInstFromFunction(CI);
|
return EraseInstFromFunction(CI);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,6 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
STATISTIC(NumInvokes, "Number of invokes replaced");
|
STATISTIC(NumInvokes, "Number of invokes replaced");
|
||||||
STATISTIC(NumUnwinds, "Number of unwinds replaced");
|
|
||||||
STATISTIC(NumSpilled, "Number of registers live across unwind edges");
|
STATISTIC(NumSpilled, "Number of registers live across unwind edges");
|
||||||
|
|
||||||
static cl::opt<bool> ExpensiveEHSupport("enable-correct-eh-support",
|
static cl::opt<bool> ExpensiveEHSupport("enable-correct-eh-support",
|
||||||
@ -193,20 +192,6 @@ bool LowerInvoke::insertCheapEHSupport(Function &F) {
|
|||||||
BB->getInstList().erase(II);
|
BB->getInstList().erase(II);
|
||||||
|
|
||||||
++NumInvokes; Changed = true;
|
++NumInvokes; Changed = true;
|
||||||
} else if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
|
|
||||||
// Insert a call to abort()
|
|
||||||
CallInst::Create(AbortFn, "", UI)->setTailCall();
|
|
||||||
|
|
||||||
// Insert a return instruction. This really should be a "barrier", as it
|
|
||||||
// is unreachable.
|
|
||||||
ReturnInst::Create(F.getContext(),
|
|
||||||
F.getReturnType()->isVoidTy() ?
|
|
||||||
0 : Constant::getNullValue(F.getReturnType()), UI);
|
|
||||||
|
|
||||||
// Remove the unwind instruction now.
|
|
||||||
BB->getInstList().erase(UI);
|
|
||||||
|
|
||||||
++NumUnwinds; Changed = true;
|
|
||||||
}
|
}
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
@ -404,7 +389,6 @@ splitLiveRangesLiveAcrossInvokes(SmallVectorImpl<InvokeInst*> &Invokes) {
|
|||||||
|
|
||||||
bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
|
bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
|
||||||
SmallVector<ReturnInst*,16> Returns;
|
SmallVector<ReturnInst*,16> Returns;
|
||||||
SmallVector<UnwindInst*,16> Unwinds;
|
|
||||||
SmallVector<InvokeInst*,16> Invokes;
|
SmallVector<InvokeInst*,16> Invokes;
|
||||||
UnreachableInst* UnreachablePlaceholder = 0;
|
UnreachableInst* UnreachablePlaceholder = 0;
|
||||||
|
|
||||||
@ -415,14 +399,11 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
|
|||||||
Returns.push_back(RI);
|
Returns.push_back(RI);
|
||||||
} else if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
|
} else if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
|
||||||
Invokes.push_back(II);
|
Invokes.push_back(II);
|
||||||
} else if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
|
|
||||||
Unwinds.push_back(UI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Unwinds.empty() && Invokes.empty()) return false;
|
if (Invokes.empty()) return false;
|
||||||
|
|
||||||
NumInvokes += Invokes.size();
|
NumInvokes += Invokes.size();
|
||||||
NumUnwinds += Unwinds.size();
|
|
||||||
|
|
||||||
// TODO: This is not an optimal way to do this. In particular, this always
|
// TODO: This is not an optimal way to do this. In particular, this always
|
||||||
// inserts setjmp calls into the entries of functions with invoke instructions
|
// inserts setjmp calls into the entries of functions with invoke instructions
|
||||||
@ -572,13 +553,6 @@ bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
|
|||||||
CallInst::Create(AbortFn, "",
|
CallInst::Create(AbortFn, "",
|
||||||
TermBlock->getTerminator())->setTailCall();
|
TermBlock->getTerminator())->setTailCall();
|
||||||
|
|
||||||
|
|
||||||
// Replace all unwinds with a branch to the unwind handler.
|
|
||||||
for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) {
|
|
||||||
BranchInst::Create(UnwindHandler, Unwinds[i]);
|
|
||||||
Unwinds[i]->eraseFromParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace the inserted unreachable with a branch to the unwind handler.
|
// Replace the inserted unreachable with a branch to the unwind handler.
|
||||||
if (UnreachablePlaceholder) {
|
if (UnreachablePlaceholder) {
|
||||||
BranchInst::Create(UnwindHandler, UnreachablePlaceholder);
|
BranchInst::Create(UnwindHandler, UnreachablePlaceholder);
|
||||||
|
@ -67,9 +67,8 @@ class SimplifyCFGOpt {
|
|||||||
bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI,
|
bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI,
|
||||||
IRBuilder<> &Builder);
|
IRBuilder<> &Builder);
|
||||||
|
|
||||||
bool SimplifyResume(ResumeInst *RI, IRBuilder<> &Builder);
|
|
||||||
bool SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder);
|
bool SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder);
|
||||||
bool SimplifyUnwind(UnwindInst *UI, IRBuilder<> &Builder);
|
bool SimplifyResume(ResumeInst *RI, IRBuilder<> &Builder);
|
||||||
bool SimplifyUnreachable(UnreachableInst *UI);
|
bool SimplifyUnreachable(UnreachableInst *UI);
|
||||||
bool SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder);
|
bool SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder);
|
||||||
bool SimplifyIndirectBr(IndirectBrInst *IBI);
|
bool SimplifyIndirectBr(IndirectBrInst *IBI);
|
||||||
@ -2353,52 +2352,6 @@ bool SimplifyCFGOpt::SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SimplifyCFGOpt::SimplifyUnwind(UnwindInst *UI, IRBuilder<> &Builder) {
|
|
||||||
// Check to see if the first instruction in this block is just an unwind.
|
|
||||||
// If so, replace any invoke instructions which use this as an exception
|
|
||||||
// destination with call instructions.
|
|
||||||
BasicBlock *BB = UI->getParent();
|
|
||||||
if (!BB->getFirstNonPHIOrDbg()->isTerminator()) return false;
|
|
||||||
|
|
||||||
bool Changed = false;
|
|
||||||
SmallVector<BasicBlock*, 8> Preds(pred_begin(BB), pred_end(BB));
|
|
||||||
while (!Preds.empty()) {
|
|
||||||
BasicBlock *Pred = Preds.back();
|
|
||||||
InvokeInst *II = dyn_cast<InvokeInst>(Pred->getTerminator());
|
|
||||||
if (II && II->getUnwindDest() == BB) {
|
|
||||||
// Insert a new branch instruction before the invoke, because this
|
|
||||||
// is now a fall through.
|
|
||||||
Builder.SetInsertPoint(II);
|
|
||||||
BranchInst *BI = Builder.CreateBr(II->getNormalDest());
|
|
||||||
Pred->getInstList().remove(II); // Take out of symbol table
|
|
||||||
|
|
||||||
// Insert the call now.
|
|
||||||
SmallVector<Value*,8> Args(II->op_begin(), II->op_end()-3);
|
|
||||||
Builder.SetInsertPoint(BI);
|
|
||||||
CallInst *CI = Builder.CreateCall(II->getCalledValue(),
|
|
||||||
Args, II->getName());
|
|
||||||
CI->setCallingConv(II->getCallingConv());
|
|
||||||
CI->setAttributes(II->getAttributes());
|
|
||||||
// If the invoke produced a value, the Call now does instead.
|
|
||||||
II->replaceAllUsesWith(CI);
|
|
||||||
delete II;
|
|
||||||
Changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Preds.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this block is now dead (and isn't the entry block), remove it.
|
|
||||||
if (pred_begin(BB) == pred_end(BB) &&
|
|
||||||
BB != &BB->getParent()->getEntryBlock()) {
|
|
||||||
// We know there are no successors, so just nuke the block.
|
|
||||||
BB->eraseFromParent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
|
bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
|
||||||
BasicBlock *BB = UI->getParent();
|
BasicBlock *BB = UI->getParent();
|
||||||
|
|
||||||
@ -3003,17 +2956,15 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
|
|||||||
} else {
|
} else {
|
||||||
if (SimplifyCondBranch(BI, Builder)) return true;
|
if (SimplifyCondBranch(BI, Builder)) return true;
|
||||||
}
|
}
|
||||||
} else if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator())) {
|
|
||||||
if (SimplifyResume(RI, Builder)) return true;
|
|
||||||
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
|
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
|
||||||
if (SimplifyReturn(RI, Builder)) return true;
|
if (SimplifyReturn(RI, Builder)) return true;
|
||||||
|
} else if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator())) {
|
||||||
|
if (SimplifyResume(RI, Builder)) return true;
|
||||||
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
|
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
|
||||||
if (SimplifySwitch(SI, Builder)) return true;
|
if (SimplifySwitch(SI, Builder)) return true;
|
||||||
} else if (UnreachableInst *UI =
|
} else if (UnreachableInst *UI =
|
||||||
dyn_cast<UnreachableInst>(BB->getTerminator())) {
|
dyn_cast<UnreachableInst>(BB->getTerminator())) {
|
||||||
if (SimplifyUnreachable(UI)) return true;
|
if (SimplifyUnreachable(UI)) return true;
|
||||||
} else if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
|
|
||||||
if (SimplifyUnwind(UI, Builder)) return true;
|
|
||||||
} else if (IndirectBrInst *IBI =
|
} else if (IndirectBrInst *IBI =
|
||||||
dyn_cast<IndirectBrInst>(BB->getTerminator())) {
|
dyn_cast<IndirectBrInst>(BB->getTerminator())) {
|
||||||
if (SimplifyIndirectBr(IBI)) return true;
|
if (SimplifyIndirectBr(IBI)) return true;
|
||||||
|
@ -50,33 +50,13 @@ bool UnifyFunctionExitNodes::runOnFunction(Function &F) {
|
|||||||
// return.
|
// return.
|
||||||
//
|
//
|
||||||
std::vector<BasicBlock*> ReturningBlocks;
|
std::vector<BasicBlock*> ReturningBlocks;
|
||||||
std::vector<BasicBlock*> UnwindingBlocks;
|
|
||||||
std::vector<BasicBlock*> UnreachableBlocks;
|
std::vector<BasicBlock*> UnreachableBlocks;
|
||||||
for(Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
|
for(Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
|
||||||
if (isa<ReturnInst>(I->getTerminator()))
|
if (isa<ReturnInst>(I->getTerminator()))
|
||||||
ReturningBlocks.push_back(I);
|
ReturningBlocks.push_back(I);
|
||||||
else if (isa<UnwindInst>(I->getTerminator()))
|
|
||||||
UnwindingBlocks.push_back(I);
|
|
||||||
else if (isa<UnreachableInst>(I->getTerminator()))
|
else if (isa<UnreachableInst>(I->getTerminator()))
|
||||||
UnreachableBlocks.push_back(I);
|
UnreachableBlocks.push_back(I);
|
||||||
|
|
||||||
// Handle unwinding blocks first.
|
|
||||||
if (UnwindingBlocks.empty()) {
|
|
||||||
UnwindBlock = 0;
|
|
||||||
} else if (UnwindingBlocks.size() == 1) {
|
|
||||||
UnwindBlock = UnwindingBlocks.front();
|
|
||||||
} else {
|
|
||||||
UnwindBlock = BasicBlock::Create(F.getContext(), "UnifiedUnwindBlock", &F);
|
|
||||||
new UnwindInst(F.getContext(), UnwindBlock);
|
|
||||||
|
|
||||||
for (std::vector<BasicBlock*>::iterator I = UnwindingBlocks.begin(),
|
|
||||||
E = UnwindingBlocks.end(); I != E; ++I) {
|
|
||||||
BasicBlock *BB = *I;
|
|
||||||
BB->getInstList().pop_back(); // Remove the unwind insn
|
|
||||||
BranchInst::Create(UnwindBlock, BB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then unreachable blocks.
|
// Then unreachable blocks.
|
||||||
if (UnreachableBlocks.empty()) {
|
if (UnreachableBlocks.empty()) {
|
||||||
UnreachableBlock = 0;
|
UnreachableBlock = 0;
|
||||||
|
Reference in New Issue
Block a user