[vmkit-commits] [vmkit] r180361 - EscapeAnalysis pass can not be generic because of the strong VT relation. Just moved this pass to J3.

Peter Senna Tschudin peter.senna at gmail.com
Thu Apr 25 10:03:03 PDT 2013


Author: peter.senna
Date: Thu Apr 25 12:01:32 2013
New Revision: 180361

URL: http://llvm.org/viewvc/llvm-project?rev=180361&view=rev
Log:
EscapeAnalysis pass can not be generic because of the strong VT relation. Just moved this pass to J3.
(cherry picked from commit 6e8201ed8e3ab28422816f32e937def3115bb567)

Added:
    vmkit/trunk/lib/j3/Compiler/EscapeAnalysis.cpp
      - copied, changed from r180360, vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp
Removed:
    vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp

Copied: vmkit/trunk/lib/j3/Compiler/EscapeAnalysis.cpp (from r180360, vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp)
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/Compiler/EscapeAnalysis.cpp?p2=vmkit/trunk/lib/j3/Compiler/EscapeAnalysis.cpp&p1=vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp&r1=180360&r2=180361&rev=180361&view=diff
==============================================================================
--- vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp (original)
+++ vmkit/trunk/lib/j3/Compiler/EscapeAnalysis.cpp Thu Apr 25 12:01:32 2013
@@ -23,10 +23,7 @@
 #include <cstddef>
 #include <map>
 
-#include "vmkit/GC.h"
-#include "vmkit/Thread.h"
-#include "vmkit/VirtualMachine.h"
-#include <stdio.h>
+#include "VmkitGC.h"
 
 using namespace llvm;
 
@@ -56,14 +53,13 @@ namespace {
 bool EscapeAnalysis::runOnFunction(Function& F) {
   bool Changed = false;
   Function* Allocator = F.getParent()->getFunction("gcmalloc");
-  Function* hasFinalizer = F.getParent()->getFunction("hasFinalizer");
-  if (!Allocator || !hasFinalizer) return Changed;
+  if (!Allocator) return Changed;
 
   LoopInfo* LI = &getAnalysis<LoopInfo>();
 
-  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) {
+  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) { 
     BasicBlock *Cur = BI;
-
+   
     // Get the parent loop if there is one. If the allocation happens in a loop
     // we must make sure that the allocated value is not used outside of
     // the loop. If the allocation does not escape and it is only used inside
@@ -119,23 +115,23 @@ bool EscapeAnalysis::runOnFunction(Funct
 
 
 static bool escapes(Value* Ins, std::map<Instruction*, bool>& visited) {
-  for (Value::use_iterator I = Ins->use_begin(), E = Ins->use_end();
+  for (Value::use_iterator I = Ins->use_begin(), E = Ins->use_end(); 
        I != E; ++I) {
     if (Instruction* II = dyn_cast<Instruction>(*I)) {
-      if (II->getOpcode() == Instruction::Call ||
+      if (II->getOpcode() == Instruction::Call || 
           II->getOpcode() == Instruction::Invoke) {
-
+        
         CallSite CS(II);
         if (!CS.onlyReadsMemory()) return true;
-
+        
         CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end();
         for (CallSite::arg_iterator A = B; A != E; ++A) {
-          if (A->get() == Ins &&
+          if (A->get() == Ins && 
               !CS.paramHasAttr(A - B + 1, Attributes::NoCapture)) {
             return true;
           }
         }
-
+       
         // We must also consider the value returned by the function.
         if (II->getType() == Ins->getType()) {
           if (escapes(II, visited)) return true;
@@ -180,12 +176,12 @@ bool EscapeAnalysis::processMalloc(Instr
 
   ConstantInt* CI = dyn_cast<ConstantInt>(Size);
   bool hasFinalizer = true;
-
+  
   if (CI) {
     if (ConstantExpr* CE = dyn_cast<ConstantExpr>(VT)) {
       if (ConstantInt* C = dyn_cast<ConstantInt>(CE->getOperand(0))) {
-        void* type = (void*)C->getZExtValue();
-        hasFinalizer = vmkit::Thread::get()->MyVM->hasFinalizer(type);
+        VirtualTable* Table = (VirtualTable*)C->getZExtValue();
+        hasFinalizer = (((void**)Table)[0] != 0);
       } else {
         GlobalVariable* GV = dyn_cast<GlobalVariable>(CE->getOperand(0));
         if (GV->hasInitializer()) {
@@ -208,7 +204,7 @@ bool EscapeAnalysis::processMalloc(Instr
     Alloc->eraseFromParent();
     return true;
   }
-
+  
   uint64_t NSize = CI->getZExtValue();
   // If the class has a finalize method, do not stack allocate the object.
   if (NSize < pageSize && !hasFinalizer) {

Removed: vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp?rev=180360&view=auto
==============================================================================
--- vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp (original)
+++ vmkit/trunk/lib/vmkit/Compiler/EscapeAnalysis.cpp (removed)
@@ -1,255 +0,0 @@
-//===------EscapeAnalysis.cpp - Simple LLVM escape analysis ---------------===//
-//
-//                     The VMKit project
-//
-// This file is distributed under the University of Illinois Open Source 
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "llvm/Constants.h"
-#include "llvm/Function.h"
-#include "llvm/GlobalVariable.h"
-#include "llvm/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Instructions.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/Support/CallSite.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <cstddef>
-#include <map>
-
-#include "vmkit/GC.h"
-#include "vmkit/Thread.h"
-#include "vmkit/VirtualMachine.h"
-#include <stdio.h>
-
-using namespace llvm;
-
-namespace {
-
-  class EscapeAnalysis : public FunctionPass {
-  public:
-    static char ID;
-    uint64_t pageSize;
-    EscapeAnalysis() : FunctionPass(ID) {
-      pageSize = getpagesize();
-    }
-
-    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
-      AU.addRequired<LoopInfo>();
-    }
-
-    virtual bool runOnFunction(Function &F);
-
-  private:
-    bool processMalloc(Instruction* I, Value* Size, Value* VT, Loop* CurLoop);
-  };
-
-  char EscapeAnalysis::ID = 0;
-  RegisterPass<EscapeAnalysis> X("EscapeAnalysis", "Escape Analysis Pass");
-
-bool EscapeAnalysis::runOnFunction(Function& F) {
-  bool Changed = false;
-  Function* Allocator = F.getParent()->getFunction("gcmalloc");
-  Function* hasFinalizer = F.getParent()->getFunction("hasFinalizer");
-  if (!Allocator || !hasFinalizer) return Changed;
-
-  LoopInfo* LI = &getAnalysis<LoopInfo>();
-
-  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) {
-    BasicBlock *Cur = BI;
-
-    // Get the parent loop if there is one. If the allocation happens in a loop
-    // we must make sure that the allocated value is not used outside of
-    // the loop. If the allocation does not escape and it is only used inside
-    // the loop, we will hoist the allocation in the pre-header of the loop.
-    Loop* CurLoop = LI->getLoopFor(Cur);
-    if (CurLoop) {
-      Loop* NextLoop = CurLoop->getParentLoop();
-      while (NextLoop) {
-        CurLoop = NextLoop;
-        NextLoop = CurLoop->getParentLoop();
-      }
-    }
-
-    for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;) {
-      Instruction *I = II;
-      II++;
-      if (I->getOpcode() != Instruction::Call &&
-          I->getOpcode() != Instruction::Invoke) {
-        continue;
-      }
-      CallSite Call(I);
-      if (Call.getCalledValue() == Allocator) {
-        if (CurLoop) {
-          bool escapesLoop = false;
-          for (Value::use_iterator U = I->use_begin(), E = I->use_end();
-               U != E; ++U) {
-            if (Instruction* II = dyn_cast<Instruction>(*U)) {
-              BasicBlock* BBU = II->getParent();
-              if (!CurLoop->contains(BBU)) {
-                escapesLoop = true;
-                break;
-              }
-            }
-          }
-
-          if (escapesLoop) continue;
-        }
-
-        if (CallInst *CI = dyn_cast<CallInst>(I)) {
-          Changed |= processMalloc(CI, CI->getArgOperand(0), CI->getArgOperand(1),
-                                   CurLoop);
-        } else if (InvokeInst *CI = dyn_cast<InvokeInst>(I)) {
-          Changed |= processMalloc(CI, CI->getArgOperand(0), CI->getArgOperand(1),
-                                   CurLoop);
-        }
-      }
-    }
-  }
-  return Changed;
-}
-
-
-
-
-static bool escapes(Value* Ins, std::map<Instruction*, bool>& visited) {
-  for (Value::use_iterator I = Ins->use_begin(), E = Ins->use_end();
-       I != E; ++I) {
-    if (Instruction* II = dyn_cast<Instruction>(*I)) {
-      if (II->getOpcode() == Instruction::Call ||
-          II->getOpcode() == Instruction::Invoke) {
-
-        CallSite CS(II);
-        if (!CS.onlyReadsMemory()) return true;
-
-        CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end();
-        for (CallSite::arg_iterator A = B; A != E; ++A) {
-          if (A->get() == Ins &&
-              !CS.paramHasAttr(A - B + 1, Attributes::NoCapture)) {
-            return true;
-          }
-        }
-
-        // We must also consider the value returned by the function.
-        if (II->getType() == Ins->getType()) {
-          if (escapes(II, visited)) return true;
-        }
-
-      } else if (dyn_cast<BitCastInst>(II)) {
-        if (escapes(II, visited)) return true;
-      } else if (StoreInst* SI = dyn_cast<StoreInst>(II)) {
-        if (AllocaInst * AI = dyn_cast<AllocaInst>(SI->getOperand(1))) {
-          if (!visited[AI]) {
-            visited[AI] = true;
-            if (escapes(AI, visited)) return true;
-          }
-        } else if (SI->getOperand(0) == Ins) {
-          return true;
-        }
-      } else if (dyn_cast<LoadInst>(II)) {
-        if (isa<PointerType>(II->getType())) {
-          if (escapes(II, visited)) return true; // allocas
-        }
-      } else if (dyn_cast<GetElementPtrInst>(II)) {
-        if (escapes(II, visited)) return true;
-      } else if (dyn_cast<ReturnInst>(II)) {
-        return true;
-      } else if (dyn_cast<PHINode>(II)) {
-        if (!visited[II]) {
-          visited[II] = true;
-          if (escapes(II, visited)) return true;
-        }
-      }
-    } else {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool EscapeAnalysis::processMalloc(Instruction* I, Value* Size, Value* VT,
-                                   Loop* CurLoop) {
-  Instruction* Alloc = I;
-  LLVMContext& Context = Alloc->getParent()->getContext();
-
-  ConstantInt* CI = dyn_cast<ConstantInt>(Size);
-  bool hasFinalizer = true;
-
-  if (CI) {
-    if (ConstantExpr* CE = dyn_cast<ConstantExpr>(VT)) {
-      if (ConstantInt* C = dyn_cast<ConstantInt>(CE->getOperand(0))) {
-        void* type = (void*)C->getZExtValue();
-        hasFinalizer = vmkit::Thread::get()->MyVM->hasFinalizer(type);
-      } else {
-        GlobalVariable* GV = dyn_cast<GlobalVariable>(CE->getOperand(0));
-        if (GV->hasInitializer()) {
-          Constant* Init = GV->getInitializer();
-          if (ConstantArray* CA = dyn_cast<ConstantArray>(Init)) {
-            Constant* V = CA->getOperand(0);
-            hasFinalizer = !V->isNullValue();
-          }
-        }
-      }
-    }
-  } else {
-    return false;
-  }
-
-  // The object does not have a finalizer and is never used. Remove the
-  // allocation as it will not have side effects.
-  if (!hasFinalizer && !Alloc->getNumUses()) {
-    DEBUG(errs() << "Escape analysis removes instruction " << *Alloc << ": ");
-    Alloc->eraseFromParent();
-    return true;
-  }
-
-  uint64_t NSize = CI->getZExtValue();
-  // If the class has a finalize method, do not stack allocate the object.
-  if (NSize < pageSize && !hasFinalizer) {
-    std::map<Instruction*, bool> visited;
-    bool esc = escapes(Alloc, visited);
-    if (!esc) {
-
-      if (CurLoop) {
-        // The object does not escape and is only used in the loop where it
-        // is allocated. We hoist the allocation in the pre-header so that
-        // we don't end up with tons of allocations on the stack.
-        BasicBlock* BB = CurLoop->getLoopPreheader();
-        assert(BB && "No Preheader!");
-        DEBUG(errs() << "Escape analysis hoisting to " << BB->getName().str());
-        DEBUG(errs() << ": ");
-        DEBUG(errs() << *Alloc);
-        Alloc->removeFromParent();
-        BB->getInstList().insert(BB->getTerminator(), Alloc);
-      }
-
-      AllocaInst* AI = new AllocaInst(Type::getInt8Ty(Context), Size, "",
-                                      Alloc);
-      BitCastInst* BI = new BitCastInst(AI, Alloc->getType(), "", Alloc);
-      DEBUG(errs() << "escape");
-      DEBUG(errs() << Alloc->getParent()->getParent()->getName().str() << "\n");
-      Alloc->replaceAllUsesWith(BI);
-      // If it's an invoke, replace the invoke with a direct branch.
-      if (InvokeInst *CI = dyn_cast<InvokeInst>(Alloc)) {
-        BranchInst::Create(CI->getNormalDest(), Alloc);
-      }
-      Alloc->eraseFromParent();
-      return true;
-    }
-  }
-  return false;
-}
-}
-
-namespace vmkit {
-FunctionPass* createEscapeAnalysisPass() {
-  return new EscapeAnalysis();
-}
-
-}





More information about the vmkit-commits mailing list