From a3efca16f2688981672deeb718909cf6acbe474e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 12 Jul 2005 01:00:32 +0000 Subject: 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) ) ; [#uses=1] %resolverCast = cast sbyte* %resolver to 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 ; [#uses=2] %isNull = seteq void (int)* %fpcache, null ; [#uses=1] br bool %isNull, label %lookupfp, label %usecache usecache: ; preds = %lookupfp, %Entry %fp = phi void (int)* [ %resolverCast, %lookupfp ], [ %fpcache, %Entry ] ; [#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) ) ; [#uses=1] %resolverCast = cast sbyte* %resolver to 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 --- tools/bugpoint/Miscompilation.cpp | 57 ++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 21 deletions(-) (limited to 'tools/bugpoint') 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 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); } -- cgit v1.2.3