From bfe11108adef46a7e366d07c9d04afb88a1966a9 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 31 Oct 2001 06:35:59 +0000 Subject: [PATCH] Implement code to convert %malloc and %free FUNCTION CALLS into the instruction equivalent git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1065 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Transforms/IPO.h | 8 ++ lib/Transforms/IPO/DeadTypeElimination.cpp | 121 ++++++++++++++++++++- 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index eb7a06d17d8..290592a2f1a 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -9,16 +9,24 @@ #include "llvm/Pass.h" class CleanupGCCOutput : public Pass { + Method *Malloc, *Free; // Pointers to external declarations, or null if none public: + + inline CleanupGCCOutput() : Malloc(0), Free(0) {} + // doPassInitialization - For this pass, it removes global symbol table // entries for primitive types. These are never used for linking in GCC and // they make the output uglier to look at, so we nuke them. // + // Also, initialize instance variables. + // bool doPassInitialization(Module *M); // doPerMethodWork - This method simplifies the specified method hopefully. // bool doPerMethodWork(Method *M); +private: + bool doOneCleanupPass(Method *M); }; #endif diff --git a/lib/Transforms/IPO/DeadTypeElimination.cpp b/lib/Transforms/IPO/DeadTypeElimination.cpp index 9fd912a1adc..42dbebd61bd 100644 --- a/lib/Transforms/IPO/DeadTypeElimination.cpp +++ b/lib/Transforms/IPO/DeadTypeElimination.cpp @@ -4,6 +4,12 @@ // unneccessarily gross for a couple of reasons. This pass does the following // things to try to clean it up: // +// * Eliminate names for GCC types that we know can't be needed by the user. +// - Eliminate names for types that are unused in the entire translation unit +// but only if they do not name a structure type! +// - Replace calls to 'sbyte *%malloc(uint)' and 'void %free(sbyte *)' with +// malloc and free instructions. +// // Note: This code produces dead declarations, it is a good idea to run DCE // after this pass. // @@ -11,6 +17,13 @@ #include "llvm/Transforms/CleanupGCCOutput.h" #include "llvm/SymbolTable.h" +#include "llvm/DerivedTypes.h" +#include "llvm/iOther.h" +#include "llvm/iMemory.h" + +static const Type *PtrArrSByte = 0; // '[sbyte]*' type +static const Type *PtrSByte = 0; // 'sbyte*' type + static inline bool ShouldNukeSymtabEntry(const pair &E) { // Nuke all names for primitive types! @@ -31,9 +44,36 @@ static inline bool ShouldNukeSymtabEntry(const pair &E) { bool CleanupGCCOutput::doPassInitialization(Module *M) { bool Changed = false; + if (PtrArrSByte == 0) { + PtrArrSByte = PointerType::get(ArrayType::get(Type::SByteTy)); + PtrSByte = PointerType::get(Type::SByteTy); + } + if (M->hasSymbolTable()) { - // Grab the type plane of the module... SymbolTable *ST = M->getSymbolTable(); + + // 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. + // + const PointerType *MallocType = // Get the type for malloc + PointerType::get(MethodType::get(PointerType::get(Type::SByteTy), + vector(1, Type::UIntTy), false)); + Malloc = cast_or_null(ST->lookup(MallocType, "malloc")); + if (Malloc && !Malloc->isExternal()) + Malloc = 0; // Don't mess with locally defined versions of the fn + + const PointerType *FreeType = // Get the type for free + PointerType::get(MethodType::get(Type::VoidTy, + vector(1, PointerType::get(Type::SByteTy)), false)); + Free = cast_or_null(ST->lookup(FreeType, "free")); + if (Free && !Free->isExternal()) + Free = 0; // Don't mess with locally defined versions of the fn + + + // Check the symbol table for superfluous type entries... + // + // Grab the 'type' plane of the module symbol... SymbolTable::iterator STI = ST->find(Type::TypeTy); if (STI != ST->end()) { // Loop over all entries in the type plane... @@ -51,17 +91,92 @@ bool CleanupGCCOutput::doPassInitialization(Module *M) { ++PI; } } - + } + + return Changed; +} + +// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) +// with a value, then remove and delete the original instruction. +// +static void ReplaceInstWithValue(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Value *V) { + Instruction *I = *BI; + // Replaces all of the uses of the instruction with uses of the value + I->replaceAllUsesWith(V); + + // Remove the unneccesary instruction now... + BIL.remove(BI); + + // Make sure to propogate a name if there is one already... + if (I->hasName() && !V->hasName()) + V->setName(I->getName(), BIL.getParent()->getSymbolTable()); + + // Remove the dead instruction now... + delete I; +} + + +// ReplaceInstWithInst - Replace the instruction specified by BI with the +// instruction specified by I. The original instruction is deleted and BI is +// updated to point to the new instruction. +// +static void ReplaceInstWithInst(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Instruction *I) { + assert(I->getParent() == 0 && + "ReplaceInstWithInst: Instruction already inserted into basic block!"); + + // Insert the new instruction into the basic block... + BI = BIL.insert(BI, I)+1; + + // Replace all uses of the old instruction, and delete it. + ReplaceInstWithValue(BIL, BI, I); + + // Reexamine the instruction just inserted next time around the cleanup pass + // loop. + --BI; +} + + +// doOneCleanupPass - Do one pass over the input method, fixing stuff up. +// +bool CleanupGCCOutput::doOneCleanupPass(Method *M) { + bool Changed = false; + for (Method::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) { + BasicBlock *BB = *MI; + BasicBlock::InstListType &BIL = BB->getInstList(); + + for (BasicBlock::iterator BI = BB->begin(); BI != BB->end();) { + Instruction *I = *BI; + + if (CallInst *CI = dyn_cast(I)) { + if (CI->getCalledValue() == Malloc) { // Replace call to malloc? + MallocInst *MallocI = new MallocInst(PtrArrSByte, CI->getOperand(1)); + BI = BIL.insert(BI, MallocI)+1; + ReplaceInstWithInst(BIL, BI, new CastInst(MallocI, PtrSByte)); + Changed = true; + continue; // Skip the ++BI + } else if (CI->getCalledValue() == Free) { // Replace call to free? + ReplaceInstWithInst(BIL, BI, new FreeInst(CI->getOperand(1))); + Changed = true; + continue; // Skip the ++BI + } + } + + ++BI; + } } return Changed; } + + // doPerMethodWork - This method simplifies the specified method hopefully. // bool CleanupGCCOutput::doPerMethodWork(Method *M) { bool Changed = false; - + while (doOneCleanupPass(M)) Changed = true; return Changed; }