diff options
author | Chris Lattner <sabre@nondot.org> | 2005-07-12 01:00:32 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-07-12 01:00:32 +0000 |
commit | a3efca16f2688981672deeb718909cf6acbe474e (patch) | |
tree | d094e52b081ac8bef1335fde67e0b09e90a9f6f6 /tools | |
parent | 9b988be18714e0b3667fb8228a0baccde819c53d (diff) |
Fix PR576.
Instead of emitting a JIT stub that looks like this:
internal void %l1_main_entry_2E_ce_wrapper(int) {
header:
%resolver = call sbyte* %getPointerToNamedFunction( sbyte* getelementptr ([20 x sbyte]* %l1_main_entry_2E_ce_name, int 0, int 0) ) ; <sbyte*> [#uses=1]
%resolverCast = cast sbyte* %resolver to void (int)* ; <void (int)*> [#uses=1]
call void %resolverCast( int %0 )
ret void
}
Emit one that looks like this:
internal void %l1_main_entry_2E_ce_wrapper(int) {
Entry:
%fpcache = load void (int)** %l1_main_entry_2E_ce.fpcache ; <void (int)*> [#uses=2]
%isNull = seteq void (int)* %fpcache, null ; <bool> [#uses=1]
br bool %isNull, label %lookupfp, label %usecache
usecache: ; preds = %lookupfp, %Entry
%fp = phi void (int)* [ %resolverCast, %lookupfp ], [ %fpcache, %Entry ] ; <void (int)*> [#uses=1]
call void %fp( int %0 )
ret void
lookupfp: ; preds = %Entry
%resolver = call sbyte* %getPointerToNamedFunction( sbyte* getelementptr ([20 x sbyte]* %l1_main_entry_2E_ce_name, int 0, int 0) ) ; <sbyte*> [#uses=1]
%resolverCast = cast sbyte* %resolver to void (int)* ; <void (int)*> [#uses=2]
store void (int)* %resolverCast, void (int)** %l1_main_entry_2E_ce.fpcache
br label %usecache
}
This makes the JIT debugger *MUCH* faster on large programs, as
getPointerToNamedFunction takes time linear with the size of the program, and
before we would call it every time a function in the text module was called from
the safe module (ouch!).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22387 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r-- | tools/bugpoint/Miscompilation.cpp | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 2e0bdb3348..9be7cd5d57 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -686,28 +686,47 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Rewrite uses of F in global initializers, etc. to uses of a wrapper // function that dynamically resolves the calls to F via our JIT API - if (F->use_begin() != F->use_end()) { + if (!F->use_empty()) { + // Create a new global to hold the cached function pointer. + Constant *NullPtr = ConstantPointerNull::get(F->getType()); + GlobalVariable *Cache = + new GlobalVariable(F->getType(), false,GlobalValue::InternalLinkage, + NullPtr,F->getName()+".fpcache", F->getParent()); + // Construct a new stub function that will re-route calls to F const FunctionType *FuncTy = F->getFunctionType(); Function *FuncWrapper = new Function(FuncTy, GlobalValue::InternalLinkage, F->getName() + "_wrapper", F->getParent()); - BasicBlock *Header = new BasicBlock("header", FuncWrapper); - + BasicBlock *EntryBB = new BasicBlock("entry", FuncWrapper); + BasicBlock *DoCallBB = new BasicBlock("usecache", FuncWrapper); + BasicBlock *LookupBB = new BasicBlock("lookupfp", FuncWrapper); + + // Check to see if we already looked up the value. + Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB); + Value *IsNull = new SetCondInst(Instruction::SetEQ, CachedVal, + NullPtr, "isNull", EntryBB); + new BranchInst(LookupBB, DoCallBB, IsNull, EntryBB); + // Resolve the call to function F via the JIT API: // // call resolver(GetElementPtr...) - CallInst *resolve = new CallInst(resolverFunc, ResolverArgs, - "resolver"); - Header->getInstList().push_back(resolve); + CallInst *Resolver = new CallInst(resolverFunc, ResolverArgs, + "resolver", LookupBB); // cast the result from the resolver to correctly-typed function - CastInst *castResolver = - new CastInst(resolve, PointerType::get(F->getFunctionType()), - "resolverCast"); - Header->getInstList().push_back(castResolver); - - // Save the argument list + CastInst *CastedResolver = + new CastInst(Resolver, PointerType::get(F->getFunctionType()), + "resolverCast", LookupBB); + // Save the value in our cache. + new StoreInst(CastedResolver, Cache, LookupBB); + new BranchInst(DoCallBB, LookupBB); + + PHINode *FuncPtr = new PHINode(NullPtr->getType(), "fp", DoCallBB); + FuncPtr->addIncoming(CastedResolver, LookupBB); + FuncPtr->addIncoming(CachedVal, EntryBB); + + // Save the argument list. std::vector<Value*> Args; for (Function::arg_iterator i = FuncWrapper->arg_begin(), e = FuncWrapper->arg_end(); i != e; ++i) @@ -715,17 +734,13 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Pass on the arguments to the real function, return its result if (F->getReturnType() == Type::VoidTy) { - CallInst *Call = new CallInst(castResolver, Args); - Header->getInstList().push_back(Call); - ReturnInst *Ret = new ReturnInst(); - Header->getInstList().push_back(Ret); + CallInst *Call = new CallInst(FuncPtr, Args, "", DoCallBB); + new ReturnInst(DoCallBB); } else { - CallInst *Call = new CallInst(castResolver, Args, "redir"); - Header->getInstList().push_back(Call); - ReturnInst *Ret = new ReturnInst(Call); - Header->getInstList().push_back(Ret); + CallInst *Call = new CallInst(FuncPtr, Args, "retval", DoCallBB); + new ReturnInst(Call, DoCallBB); } - + // Use the wrapper function instead of the old function F->replaceAllUsesWith(FuncWrapper); } |