[llvm-commits] CVS: llvm/lib/Transforms/IPO/RaiseAllocations.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Aug 31 22:16:01 PDT 2003
Changes in directory llvm/lib/Transforms/IPO:
RaiseAllocations.cpp updated: 1.16 -> 1.17
---
Log message:
Change the RaiseAllocations pass to be a Pass instead of a BasicBlock pass.
This makes it more efficient: it doesn't have to scan the whole program, so
it performs work proportional to the number of malloc/free calls in the
program, not the size of the program.
---
Diffs of the changes:
Index: llvm/lib/Transforms/IPO/RaiseAllocations.cpp
diff -u llvm/lib/Transforms/IPO/RaiseAllocations.cpp:1.16 llvm/lib/Transforms/IPO/RaiseAllocations.cpp:1.17
--- llvm/lib/Transforms/IPO/RaiseAllocations.cpp:1.16 Mon Aug 18 09:33:38 2003
+++ llvm/lib/Transforms/IPO/RaiseAllocations.cpp Sun Aug 31 22:14:56 2003
@@ -5,13 +5,13 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/iMemory.h"
#include "llvm/iOther.h"
#include "llvm/Pass.h"
+#include "llvm/Support/CallSite.h"
#include "Support/Statistic.h"
namespace {
@@ -20,7 +20,7 @@
// RaiseAllocations - Turn %malloc and %free calls into the appropriate
// instruction.
//
- class RaiseAllocations : public BasicBlockPass {
+ class RaiseAllocations : public Pass {
Function *MallocFunc; // Functions in the module we are processing
Function *FreeFunc; // Initialized by doPassInitializationVirt
public:
@@ -29,12 +29,11 @@
// doPassInitialization - For the raise allocations pass, this finds a
// declaration for malloc and free if they exist.
//
- bool doInitialization(Module &M);
+ void doInitialization(Module &M);
- // runOnBasicBlock - This method does the actual work of converting
- // instructions over, assuming that the pass has already been initialized.
+ // run - This method does the actual work of converting instructions over.
//
- bool runOnBasicBlock(BasicBlock &BB);
+ bool run(Module &M);
};
RegisterOpt<RaiseAllocations>
@@ -48,15 +47,15 @@
}
-bool RaiseAllocations::doInitialization(Module &M) {
- // If the module has a symbol table, they might be referring to the malloc
- // and free functions. If this is the case, grab the method pointers that
- // the module is using.
- //
- // Lookup %malloc and %free in the symbol table, for later use. If they
- // don't exist, or are not external, we do not worry about converting calls
- // to that function into the appropriate instruction.
- //
+// If the module has a symbol table, they might be referring to the malloc and
+// free functions. If this is the case, grab the method pointers that the
+// module is using.
+//
+// Lookup %malloc and %free in the symbol table, for later use. If they don't
+// exist, or are not external, we do not worry about converting calls to that
+// function into the appropriate instruction.
+//
+void RaiseAllocations::doInitialization(Module &M) {
const FunctionType *MallocType = // Get the type for malloc
FunctionType::get(PointerType::get(Type::SByteTy),
std::vector<const Type*>(1, Type::ULongTy), false);
@@ -100,52 +99,74 @@
FreeFunc = M.getFunction("free", FreeType);
}
-
// Don't mess with locally defined versions of these functions...
if (MallocFunc && !MallocFunc->isExternal()) MallocFunc = 0;
if (FreeFunc && !FreeFunc->isExternal()) FreeFunc = 0;
- return false;
}
-// runOnBasicBlock - Process a basic block, fixing it up...
+// run - Transform calls into instructions...
//
-bool RaiseAllocations::runOnBasicBlock(BasicBlock &BB) {
+bool RaiseAllocations::run(Module &M) {
+ // Find the malloc/free prototypes...
+ doInitialization(M);
+
bool Changed = false;
- BasicBlock::InstListType &BIL = BB.getInstList();
- for (BasicBlock::iterator BI = BB.begin(); BI != BB.end(); ++BI) {
- Instruction *I = BI;
+ // First, process all of the malloc calls...
+ if (MallocFunc) {
+ std::vector<User*> Users(MallocFunc->use_begin(), MallocFunc->use_end());
+ while (!Users.empty()) {
+ if (Instruction *I = dyn_cast<Instruction>(Users.back())) {
+ CallSite CS = CallSite::get(I);
+ if (CS.getInstruction() && CS.getCalledFunction() == MallocFunc &&
+ CS.arg_begin() != CS.arg_end()) {
+ Value *Source = *CS.arg_begin();
+
+ // If no prototype was provided for malloc, we may need to cast the
+ // source size.
+ if (Source->getType() != Type::UIntTy)
+ Source = new CastInst(Source, Type::UIntTy, "MallocAmtCast", I);
+
+ std::string Name(I->getName()); I->setName("");
+ MallocInst *MI = new MallocInst(Type::SByteTy, Source, Name, I);
+ I->replaceAllUsesWith(MI);
+ MI->getParent()->getInstList().erase(I);
+ Changed = true;
+ ++NumRaised;
+ }
+ }
+
+ Users.pop_back();
+ }
+ }
- if (CallInst *CI = dyn_cast<CallInst>(I)) {
- if (CI->getCalledValue() == MallocFunc) { // Replace call to malloc?
- Value *Source = CI->getOperand(1);
-
- // If no prototype was provided for malloc, we may need to cast the
- // source size.
- if (Source->getType() != Type::UIntTy)
- Source = new CastInst(Source, Type::UIntTy, "MallocAmtCast", BI);
-
- std::string Name(CI->getName()); CI->setName("");
- BI = new MallocInst(Type::SByteTy, Source, Name, BI);
- CI->replaceAllUsesWith(BI);
- BIL.erase(I);
- Changed = true;
- ++NumRaised;
- } else if (CI->getCalledValue() == FreeFunc) { // Replace call to free?
- // If no prototype was provided for free, we may need to cast the
- // source pointer. This should be really uncommon, but it's necessary
- // just in case we are dealing with wierd code like this:
- // free((long)ptr);
- //
- Value *Source = CI->getOperand(1);
- if (!isa<PointerType>(Source->getType()))
- Source = new CastInst(Source, PointerType::get(Type::SByteTy),
- "FreePtrCast", BI);
- BI = new FreeInst(Source, BI);
- BIL.erase(I);
- Changed = true;
- ++NumRaised;
+ // Next, process all free calls...
+ if (FreeFunc) {
+ std::vector<User*> Users(FreeFunc->use_begin(), FreeFunc->use_end());
+
+ while (!Users.empty()) {
+ if (Instruction *I = dyn_cast<Instruction>(Users.back())) {
+ CallSite CS = CallSite::get(I);
+ if (CS.getInstruction() && CS.getCalledFunction() == FreeFunc &&
+ CS.arg_begin() != CS.arg_end()) {
+
+ // If no prototype was provided for free, we may need to cast the
+ // source pointer. This should be really uncommon, but it's necessary
+ // just in case we are dealing with wierd code like this:
+ // free((long)ptr);
+ //
+ Value *Source = *CS.arg_begin();
+ if (!isa<PointerType>(Source->getType()))
+ Source = new CastInst(Source, PointerType::get(Type::SByteTy),
+ "FreePtrCast", I);
+ new FreeInst(Source, I);
+ I->getParent()->getInstList().erase(I);
+ Changed = true;
+ ++NumRaised;
+ }
}
+
+ Users.pop_back();
}
}
More information about the llvm-commits
mailing list