[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