summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-10-13 00:57:16 +0000
committerChris Lattner <sabre@nondot.org>2003-10-13 00:57:16 +0000
commitbb2d4de409f02d75ba43f64b6d9e446f3a910e70 (patch)
treec2a119bf9260427e80740506a02fc2155f7c54d1
parent2ab6a7358e7788eae43b73a79e066322ef0a55d5 (diff)
downloadllvm-bb2d4de409f02d75ba43f64b6d9e446f3a910e70.tar.gz
llvm-bb2d4de409f02d75ba43f64b6d9e446f3a910e70.tar.bz2
llvm-bb2d4de409f02d75ba43f64b6d9e446f3a910e70.tar.xz
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9066 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/IPO/LowerSetJmp.cpp36
1 files changed, 30 insertions, 6 deletions
diff --git a/lib/Transforms/IPO/LowerSetJmp.cpp b/lib/Transforms/IPO/LowerSetJmp.cpp
index fb3cd16c75..2f0444a5d5 100644
--- a/lib/Transforms/IPO/LowerSetJmp.cpp
+++ b/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 <set>
-
namespace {
Statistic<> LongJmpsTransformed("lowersetjmp",
"Number of longjmps transformed");
@@ -64,6 +63,11 @@ namespace {
typedef std::pair<SwitchInst*, CallInst*> 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<BasicBlock*> 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<BasicBlock*> BBSet;
+
+ for (Value::use_iterator B = SetJmp->use_begin(), E = SetJmp->use_end();
+ B != E; ++B) {
+ Instruction* I = cast<Instruction>(*B);
+ BasicBlock* BB = I->getParent();
+ Function* Func = BB->getParent();
+ DFSBlocks.insert(df_begin(BB), df_end(BB));
+ }
+
while (!SetJmp->use_empty()) {
assert(isa<CallInst>(SetJmp->use_back()) &&
"User of setjmp intrinsic not a call?");
TransformSetJmpCall(cast<CallInst>(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();