Added the DebugPoolRegisterElimination pass which can safely remove
unneeded stack and global registration functions.
Modified the sc tool to use it.
llvm-svn: 95388
diff --git a/safecode/include/safecode/OptimizeChecks.h b/safecode/include/safecode/OptimizeChecks.h
index 7572fcf..4725ed7 100755
--- a/safecode/include/safecode/OptimizeChecks.h
+++ b/safecode/include/safecode/OptimizeChecks.h
@@ -121,6 +121,7 @@
public:
static char ID;
PoolRegisterElimination() : ModulePass((intptr_t)(&ID)) {}
+ PoolRegisterElimination(char * ID) : ModulePass((intptr_t)(ID)) {}
virtual bool runOnModule (Module & M);
const char *getPassName() const {
return "Pool Register Elimination";
@@ -134,7 +135,7 @@
AU.setPreservesCFG();
}
- private:
+ protected:
// References to required analysis passes
InsertSCIntrinsic * intrinsic;
AliasAnalysis * AA;
@@ -150,14 +151,36 @@
//
DenseSet<AliasSet*> usedSet;
- // Private methods
- void markUsedAliasSet(const char * name);
- void removeUnusedRegistrations (void);
+ // Protected methods
+ void markUsedAliasSet(const char * name, DenseSet<AliasSet*> & set);
+ void removeUnusedRegistrations (const char * name);
bool isSafeToRemove (Value * Ptr);
void findCheckedAliasSets ();
};
//
+// Pass: DebugPoolRegisterElimination
+//
+// Description:
+// This pass is identical to the PoolRegisterElimination pass except that it
+// will not disrupt the debugging features of the SAFECode debug tool. It
+// aims to provide some optimization while providing good debug information.
+//
+struct DebugPoolRegisterElimination : public PoolRegisterElimination {
+ public:
+ static char ID;
+ DebugPoolRegisterElimination() : PoolRegisterElimination(&ID) {}
+ virtual bool runOnModule (Module & M);
+ const char *getPassName() const {
+ return "Debugging-Safe Pool Register Elimination";
+ }
+
+ protected:
+ // Protected methods
+ void findFreedAliasSets (void);
+};
+
+//
// Pass: Unused Check Elimination
//
// Description:
diff --git a/safecode/lib/OptimizeChecks/PoolRegisterElimination.cpp b/safecode/lib/OptimizeChecks/PoolRegisterElimination.cpp
index 0816026..e86ee3d 100755
--- a/safecode/lib/OptimizeChecks/PoolRegisterElimination.cpp
+++ b/safecode/lib/OptimizeChecks/PoolRegisterElimination.cpp
@@ -61,7 +61,7 @@
for (size_t i = 0;
i < sizeof(splayTreeCheckIntrinsics) / sizeof (const char*);
++i) {
- markUsedAliasSet(splayTreeCheckIntrinsics[i]);
+ markUsedAliasSet(splayTreeCheckIntrinsics[i], usedSet);
}
return;
@@ -88,9 +88,103 @@
findCheckedAliasSets();
//
+ // List of registration intrinsics.
+ //
+ // FIXME:
+ // It is possible that removeUnusedRegistration() will properly detect
+ // that pointers *within* argv are not used. This should be investigated
+ // before sc.pool_argvregister() is added back into the list.
+ //
+ // Note that sc.pool_argvregister() is not in this list. This is because
+ // it registers both the argv array and all the command line arguments whose
+ // pointers are within the argv array.
+ //
+ const char * registerIntrinsics[] = {
+ "sc.pool_register",
+ "sc.pool_register_stack",
+ "sc.pool_register_global",
+ "sc.pool_unregister",
+ "sc.pool_unregister_stack",
+ };
+
+ //
// Remove all unused registrations.
//
- removeUnusedRegistrations ();
+ unsigned numberOfIntrinsics=sizeof(registerIntrinsics) / sizeof (const char*);
+ for (size_t i = 0; i < numberOfIntrinsics; ++i) {
+ removeUnusedRegistrations (registerIntrinsics[i]);
+ }
+
+ //
+ // Deallocate memory and return;
+ //
+ delete AST;
+ return true;
+}
+
+//
+// Method: findFreedAliasSets()
+//
+// Description:
+// This method will find and record all the alias sets that have pointers that
+// have been used in deallocation functions.
+//
+void
+DebugPoolRegisterElimination::findFreedAliasSets (void) {
+ return;
+}
+
+bool
+DebugPoolRegisterElimination::runOnModule(Module & M) {
+ //
+ // Clear out the set of used alias groups.
+ //
+ usedSet.clear();
+
+ //
+ // Get access to prequisite analysis passes.
+ //
+ intrinsic = &getAnalysis<InsertSCIntrinsic>();
+ AA = &getAnalysis<AliasAnalysis>();
+ AST = new AliasSetTracker(*AA);
+
+ //
+ // Find all alias sets that have a pointer that is passed to a run-time
+ // check that does a splay-tree lookup.
+ //
+ findCheckedAliasSets();
+
+ //
+ // Find all alias sets that have a pointer that is freed. Such pointers are
+ // considered "used" since we need to do invalid free checks on them.
+ //
+ markUsedAliasSet ("sc.pool_unregister", usedSet);
+
+ //
+ // List of registration intrinsics.
+ //
+ // FIXME:
+ // It is possible that removeUnusedRegistration() will properly detect
+ // that pointers *within* argv are not used. This should be investigated
+ // before sc.pool_argvregister() is added back into the list.
+ //
+ // Note that sc.pool_argvregister() is not in this list. This is because
+ // it registers both the argv array and all the command line arguments whose
+ // pointers are within the argv array.
+ //
+ const char * registerIntrinsics[] = {
+ "sc.pool_register_global",
+ "sc.pool_register_stack",
+ "sc.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;
@@ -103,25 +197,25 @@
// Method: markUsedAliasSet
//
// Description:
-// This method takes the name of a run-time check and determines which alias
-// sets are ever passed into the function.
+// This method takes the name of a SAFECode run-time function and determines
+// which alias sets are ever passed into the function.
//
// Inputs:
// name - The name of the run-time function for which to find uses.
//
-// Side-effects:
-// Any alias sets that are checked by the specified run-time function will
-// have been added to the usedSet variable.
+// Outputs:
+// set - The set into which alias sets that use the function should go.
//
void
-PoolRegisterElimination::markUsedAliasSet(const char * name) {
+PoolRegisterElimination::markUsedAliasSet (const char * name,
+ DenseSet<AliasSet*> & set) {
Function * F = intrinsic->getIntrinsic(name).F;
for(Value::use_iterator UI=F->use_begin(), UE=F->use_end(); UI != UE; ++UI) {
CallInst * CI = cast<CallInst>(*UI);
Value * checkedPtr = intrinsic->getValuePointer(CI);
AliasSet & aliasSet = AST->getAliasSetForPointer(checkedPtr, 0);
- usedSet.insert(&aliasSet);
+ set.insert(&aliasSet);
}
}
@@ -156,46 +250,23 @@
// name - The name of the registration intrinsic.
//
void
-PoolRegisterElimination::removeUnusedRegistrations (void) {
- //
- // List of registration intrinsics.
- //
- // FIXME:
- // It is possible that removeUnusedRegistration() will properly detect
- // that pointers *within* argv are not used. This should be investigated
- // before sc.pool_argvregister() is added back into the list.
- //
- // Note that sc.pool_argvregister() is not in this list. This is because
- // it registers both the argv array and all the command line arguments whose
- // pointers are within the argv array.
- //
- const char * registerIntrinsics[] = {
- "sc.pool_register",
- "sc.pool_register_stack",
- "sc.pool_register_global",
- "sc.pool_unregister",
- "sc.pool_unregister_stack",
- };
-
+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;
- unsigned numberOfIntrinsics=sizeof(registerIntrinsics) / sizeof (const char*);
- for (size_t i = 0; i < numberOfIntrinsics; ++i) {
- Function * F = intrinsic->getIntrinsic(registerIntrinsics[i]).F;
+ 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);
- }
+ //
+ // 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);
}
}
@@ -213,6 +284,7 @@
}
}
-char PoolRegisterElimination::ID = 0;
+char PoolRegisterElimination::ID = 0;
+char DebugPoolRegisterElimination::ID = 0;
NAMESPACE_SC_END
diff --git a/safecode/tools/Sc/sc.cpp b/safecode/tools/Sc/sc.cpp
index b4d37e9..5c6424f 100755
--- a/safecode/tools/Sc/sc.cpp
+++ b/safecode/tools/Sc/sc.cpp
@@ -347,7 +347,11 @@
// frees.
//
Passes.add (new OptimizeChecks());
- if (DisableDebugInfo) Passes.add (new PoolRegisterElimination());
+ if (DisableDebugInfo) {
+ Passes.add (new PoolRegisterElimination());
+ } else {
+ Passes.add (new DebugPoolRegisterElimination());
+ }
Passes.add(new UnusedCheckElimination());