blob: bcd94e54ffb3a1f72634846e3dd7f1b02b674bc5 [file] [log] [blame]
//===- PoolRegisterElimination.cpp ---------------------------------------- --//
//
// The SAFECode Compiler
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates unnessary poolregister() / poolunregister() in the
// code. Redundant poolregister() happens when there are no boundscheck() /
// poolcheck() on a certain GEP, possibly all of these checks are lowered to
// exact checks.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "poolreg-elim"
#include "safecode/OptimizeChecks.h"
#include "safecode/Support/AllocatorInfo.h"
#include "SCUtils.h"
#include "dsa/DSSupport.h"
#include "llvm/ADT/Statistic.h"
NAMESPACE_SC_BEGIN
static RegisterPass<PoolRegisterElimination>
X ("poolreg-elim", "Pool Register Eliminiation");
// Pass Statistics
namespace {
STATISTIC (RemovedRegistration,
"Number of object registrations/deregistrations removed");
STATISTIC (TypeSafeRegistrations,
"Number of type safe object registrations/deregistrations removed");
STATISTIC (SingletonRegistrations,
"Number of singleton object registrations/deregistrations removed");
}
//
// Method: findSafeGlobals()
//
// Description:
// Find global variables that do not escape into memory or external code.
//
template<typename insert_iterator>
void
PoolRegisterElimination::findSafeGlobals (Module & M, insert_iterator InsertPt) {
for (Module::global_iterator GV = M.global_begin();
GV != M.global_end();
++GV) {
if (!escapesToMemory (GV))
InsertPt = GV;
}
return;
}
bool
PoolRegisterElimination::runOnModule(Module & M) {
//
// Get access to prequisite analysis passes.
//
intrinsic = &getAnalysis<InsertSCIntrinsic>();
dsaPass = &getAnalysis<EQTDDataStructures>();
TS = &getAnalysis<dsa::TypeSafety<EQTDDataStructures> >();
//
// Get the set of safe globals.
//
findSafeGlobals (M, std::inserter (SafeGlobals, SafeGlobals.begin()));
//
// List of registration intrinsics.
//
const char * registerIntrinsics[] = {
"pool_register_global",
"pool_register_stack",
"pool_unregister_stack"
};
//
// Remove all unused registrations.
//
unsigned numberOfIntrinsics=sizeof(registerIntrinsics) / sizeof (const char*);
for (size_t i = 0; i < numberOfIntrinsics; ++i) {
removeUnusedRegistrations (registerIntrinsics[i]);
}
//
// Remove registrations for type-safe singleton objects.
//
removeTypeSafeRegistrations ("pool_register");
//
// Remove registrations for singleton objects. Note that we only do this for
// heap objects.
//
removeSingletonRegistrations ("pool_register");
//
// Deallocate memory and return;
//
SafeGlobals.clear();
return true;
}
bool
DebugPoolRegisterElimination::runOnModule(Module & M) {
//
// Get access to prequisite analysis passes.
//
intrinsic = &getAnalysis<InsertSCIntrinsic>();
//
// List of registration intrinsics.
//
const char * registerIntrinsics[] = {
"pool_register_global",
"pool_register_stack",
"pool_unregister_stack",
};
//
// Remove all unused registrations.
//
unsigned numberOfIntrinsics=sizeof(registerIntrinsics) / sizeof (const char*);
for (size_t i = 0; i < numberOfIntrinsics; ++i) {
removeUnusedRegistrations (registerIntrinsics[i]);
}
//
// Deallocate memory and return;
//
return true;
}
//
// Method: isSafeToRemove()
//
// Description:
// Determine whether the registration for the specified pointer value can be
// safely removed.
//
// Inputs:
// Ptr - The pointer value that is registered.
//
// Return value:
// true - The registration of this value can be safely removed.
// false - The registration of this value may not be safely removed.
//
bool
PoolRegisterElimination::isSafeToRemove (Value * Ptr) {
//
// We can remove registrations on global variables that don't escape to
// memory.
//
if (GlobalVariable * GV = dyn_cast<GlobalVariable>(Ptr)) {
if (SafeGlobals.count (GV))
return true;
}
return false;
}
//
// Method: removeUnusedRegistration()
//
// Description:
// This method take the name of a registration function and removes all
// registrations made with that function for pointers that are never checked.
//
// Inputs:
// name - The name of the registration intrinsic.
//
void
PoolRegisterElimination::removeUnusedRegistrations (const char * name) {
//
// Scan through all uses of each registration function and see if it can be
// safely removed. If so, schedule it for removal.
//
std::vector<CallInst*> toBeRemoved;
Function * F = intrinsic->getIntrinsic(name).F;
//
// Look for and record all registrations that can be deleted.
//
for (Value::use_iterator UI=F->use_begin(), UE=F->use_end();
UI != UE;
++UI) {
CallInst * CI = cast<CallInst>(*UI);
if (isSafeToRemove (intrinsic->getValuePointer(CI))) {
toBeRemoved.push_back(CI);
}
}
//
// Update the statistics.
//
if (toBeRemoved.size())
RemovedRegistration += toBeRemoved.size();
//
// Remove the unnecesary registrations.
//
std::vector<CallInst*>::iterator it, end;
for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) {
(*it)->eraseFromParent();
}
}
void
PoolRegisterElimination::removeTypeSafeRegistrations (const char * name) {
//
// Scan through all uses of the registration function and see if it can be
// safely removed. If so, schedule it for removal.
//
std::vector<CallInst*> toBeRemoved;
Function * F = intrinsic->getIntrinsic(name).F;
//
// Look for and record all registrations that can be deleted.
//
for (Value::use_iterator UI=F->use_begin(), UE=F->use_end();
UI != UE;
++UI) {
//
// Get the pointer to the registered object.
//
CallInst * CI = cast<CallInst>(*UI);
Value * Ptr = intrinsic->getValuePointer(CI);
// Lookup the DSNode for the value in the function's DSGraph.
//
DSGraph * TDG = dsaPass->getDSGraph(*(CI->getParent()->getParent()));
DSNodeHandle DSH = TDG->getNodeForValue(Ptr);
assert ((!(DSH.isNull())) && "No DSNode for Value!\n");
//
// If the DSNode is type-safe and is never used as an array, then there
// will never be a need to look it up in a splay tree, so remove its
// registration.
//
DSNode * N = DSH.getNode();
if(!N->isArrayNode() &&
TS->isTypeSafe(Ptr, F)){
toBeRemoved.push_back(CI);
}
}
//
// Update the statistics.
//
if (toBeRemoved.size()) {
RemovedRegistration += toBeRemoved.size();
TypeSafeRegistrations += toBeRemoved.size();
}
//
// Remove the unnecesary registrations.
//
std::vector<CallInst*>::iterator it, end;
for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) {
(*it)->eraseFromParent();
}
}
void
PoolRegisterElimination::removeSingletonRegistrations (const char * name) {
//
// Scan through all uses of the registration function and see if it can be
// safely removed. If so, schedule it for removal.
//
std::vector<CallInst*> toBeRemoved;
Function * F = intrinsic->getIntrinsic(name).F;
//
// Look for and record all registrations that can be deleted.
//
for (Value::use_iterator UI=F->use_begin(), UE=F->use_end();
UI != UE;
++UI) {
//
// Get the pointer to the registered object.
//
CallInst * CI = cast<CallInst>(*UI);
Value * Ptr = intrinsic->getValuePointer(CI);
//
// Lookup the DSNode for the value in the function's DSGraph.
//
DSGraph * TDG = dsaPass->getDSGraph(*(CI->getParent()->getParent()));
DSNodeHandle DSH = TDG->getNodeForValue(Ptr);
assert ((!(DSH.isNull())) && "No DSNode for Value!\n");
//
// If the object being registered is the same size as that found in the
// DSNode, then we know it's a singleton object. The run-time doesn't need
// such objects registered in the splay trees, so we can remove the
// registration function.
//
DSNode * N = DSH.getNode();
Value * Size = intrinsic->getObjectSize (Ptr->stripPointerCasts());
if (Size) {
if (ConstantInt * C = dyn_cast<ConstantInt>(Size)) {
unsigned long size = C->getZExtValue();
if (size == N->getSize()) {
toBeRemoved.push_back(CI);
continue;
}
}
}
}
//
// Update the statistics.
//
if (toBeRemoved.size()) {
RemovedRegistration += toBeRemoved.size();
SingletonRegistrations += toBeRemoved.size();
}
//
// Remove the unnecesary registrations.
//
std::vector<CallInst*>::iterator it, end;
for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) {
(*it)->eraseFromParent();
}
}
char PoolRegisterElimination::ID = 0;
char DebugPoolRegisterElimination::ID = 0;
NAMESPACE_SC_END