From 56b8526083c5ab6f0b370211ee8408f5e7604ebd Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 13 Oct 2003 00:57:16 +0000 Subject: [PATCH] Checkin an improvement contributed by Bill: Only transform call sites in a setjmp'ing function which are reachable from the setjmp. If the call dominates the setjmp (for example), the called function cannot longjmp to the setjmp. This dramatically reduces the number of invoke instructions created in some large testcases. llvm-svn: 9066 --- llvm/lib/Transforms/IPO/LowerSetJmp.cpp | 36 ++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/IPO/LowerSetJmp.cpp b/llvm/lib/Transforms/IPO/LowerSetJmp.cpp index fb3cd16c750e..2f0444a5d512 100644 --- a/llvm/lib/Transforms/IPO/LowerSetJmp.cpp +++ b/llvm/lib/Transforms/IPO/LowerSetJmp.cpp @@ -32,14 +32,13 @@ #include "llvm/Intrinsics.h" #include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/Support/InstIterator.h" +#include "llvm/Support/CFG.h" #include "llvm/Support/InstVisitor.h" +#include "Support/DepthFirstIterator.h" #include "Support/Statistic.h" #include "Support/StringExtras.h" #include "Support/VectorExtras.h" -#include - namespace { Statistic<> LongJmpsTransformed("lowersetjmp", "Number of longjmps transformed"); @@ -64,6 +63,11 @@ namespace { typedef std::pair SwitchValuePair; + // Keep track of those basic blocks reachable via a depth-first search of + // the CFG from a setjmp call. We only need to transform those "call" and + // "invoke" instructions that are reachable from the setjmp call site. + std::set DFSBlocks; + // The setjmp map is going to hold information about which setjmps // were called (each setjmp gets its own number) and with which // buffer it was called. @@ -127,13 +131,24 @@ bool LowerSetJmp::run(Module& M) // setjmp/longjmp functions. doInitialization(M); - if (SetJmp) + if (SetJmp) { + std::set BBSet; + + for (Value::use_iterator B = SetJmp->use_begin(), E = SetJmp->use_end(); + B != E; ++B) { + Instruction* I = cast(*B); + BasicBlock* BB = I->getParent(); + Function* Func = BB->getParent(); + DFSBlocks.insert(df_begin(BB), df_end(BB)); + } + while (!SetJmp->use_empty()) { assert(isa(SetJmp->use_back()) && "User of setjmp intrinsic not a call?"); TransformSetJmpCall(cast(SetJmp->use_back())); Changed = true; } + } if (LongJmp) while (!LongJmp->use_empty()) { @@ -156,6 +171,7 @@ bool LowerSetJmp::run(Module& M) } } + DFSBlocks.clear(); SJMap.clear(); RethrowBBMap.clear(); PrelimBBMap.clear(); @@ -398,12 +414,16 @@ void LowerSetJmp::visitCallInst(CallInst& CI) CI.getCalledFunction()->isIntrinsic()) return; BasicBlock* OldBB = CI.getParent(); + Function* Func = OldBB->getParent(); + + // If not reachable from a setjmp call, don't transform. + if (!DFSBlocks.count(OldBB)) return; + BasicBlock* NewBB = OldBB->splitBasicBlock(CI); assert(NewBB && "Couldn't split BB of \"call\" instruction!!"); NewBB->setName("Call2Invoke"); // Reposition the split BB in the BB list to make things tidier. - Function* Func = OldBB->getParent(); Func->getBasicBlockList().remove(NewBB); Func->getBasicBlockList().insert(++Function::iterator(OldBB), NewBB); @@ -432,7 +452,11 @@ void LowerSetJmp::visitInvokeInst(InvokeInst& II) if (!IsTransformableFunction(II.getCalledFunction()->getName()) || II.getCalledFunction()->isIntrinsic()) return; - Function* Func = II.getParent()->getParent(); + BasicBlock* BB = II.getParent(); + Function* Func = BB->getParent(); + + // If not reachable from a setjmp call, don't transform. + if (!DFSBlocks.count(BB)) return; BasicBlock* NormalBB = II.getNormalDest(); BasicBlock* ExceptBB = II.getExceptionalDest();