[llvm-commits] CVS: llvm/tools/bugpoint/Miscompilation.cpp

Chris Lattner lattner at cs.uiuc.edu
Mon Jul 11 18:00:43 PDT 2005



Changes in directory llvm/tools/bugpoint:

Miscompilation.cpp updated: 1.67 -> 1.68
---
Log message:

Fix PR576: http://llvm.cs.uiuc.edu/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!).



---
Diffs of the changes:  (+36 -21)

 Miscompilation.cpp |   57 +++++++++++++++++++++++++++++++++--------------------
 1 files changed, 36 insertions(+), 21 deletions(-)


Index: llvm/tools/bugpoint/Miscompilation.cpp
diff -u llvm/tools/bugpoint/Miscompilation.cpp:1.67 llvm/tools/bugpoint/Miscompilation.cpp:1.68
--- llvm/tools/bugpoint/Miscompilation.cpp:1.67	Thu Jul  7 22:08:58 2005
+++ llvm/tools/bugpoint/Miscompilation.cpp	Mon Jul 11 20:00:32 2005
@@ -686,28 +686,47 @@
 
         // 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 @@
 
           // 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);
         }






More information about the llvm-commits mailing list