diff --git a/llvm/docs/Passes.html b/llvm/docs/Passes.html index bb17bee77c3b..36e0419ad283 100644 --- a/llvm/docs/Passes.html +++ b/llvm/docs/Passes.html @@ -158,7 +158,6 @@ perl -e '$/ = undef; for (split(/\n/, <>)) { s:^ *///? ?::; print "

\n" if ! -memcpyoptOptimize use of memcpy and friends -mergereturnUnify function exit nodes -prune-ehRemove unused exception handling info --raiseallocsRaise allocations from calls to instructions -reassociateReassociate expressions -reg2memDemote all values to stack slots -scalarreplScalar Replacement of Aggregates @@ -1502,17 +1501,6 @@ if (X < 3) {

- -
- Raise allocations from calls to instructions -
-
-

- Converts @malloc and @free calls to malloc and - free instructions. -

-
-
Reassociate expressions diff --git a/llvm/include/llvm-c/Transforms/IPO.h b/llvm/include/llvm-c/Transforms/IPO.h index 9bc947f4d8a2..0a94315f62b2 100644 --- a/llvm/include/llvm-c/Transforms/IPO.h +++ b/llvm/include/llvm-c/Transforms/IPO.h @@ -54,7 +54,7 @@ void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM); /** See llvm::createPruneEHPass function. */ void LLVMAddPruneEHPass(LLVMPassManagerRef PM); -/** See llvm::createRaiseAllocationsPass function. */ +// FIXME: Remove in LLVM 3.0. void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM); /** See llvm::createStripDeadPrototypesPass function. */ diff --git a/llvm/include/llvm/Analysis/MallocHelper.h b/llvm/include/llvm/Analysis/MallocHelper.h index e0c4d2c9e4ae..be307c02aed5 100644 --- a/llvm/include/llvm/Analysis/MallocHelper.h +++ b/llvm/include/llvm/Analysis/MallocHelper.h @@ -27,8 +27,8 @@ class Value; // malloc Call Utility Functions. // -/// isMalloc - Returns true if the the value is either a malloc call or a -/// bitcast of the result of a malloc call +/// isMalloc - Returns true if the value is either a malloc call or a bitcast of +/// the result of a malloc call bool isMalloc(const Value* I); /// extractMallocCall - Returns the corresponding CallInst if the instruction @@ -79,6 +79,13 @@ const Type* getMallocAllocatedType(const CallInst* CI); /// determined. Value* getMallocArraySize(CallInst* CI, LLVMContext &Context, const TargetData* TD); + +//===----------------------------------------------------------------------===// +// free Call Utility Functions. +// + +/// isFreeCall - Returns true if the the value is a call to the builtin free() +bool isFreeCall(const Value* I); } // End llvm namespace diff --git a/llvm/include/llvm/Instructions.h b/llvm/include/llvm/Instructions.h index 9a990e7eb96f..f7e7a3dbf99b 100644 --- a/llvm/include/llvm/Instructions.h +++ b/llvm/include/llvm/Instructions.h @@ -956,6 +956,9 @@ public: const Type *IntPtrTy, const Type *AllocTy, Value *ArraySize = 0, Function* MallocF = 0, const Twine &Name = ""); + /// CreateFree - Generate the IR for a call to the builtin free function. + static void CreateFree(Value* Source, Instruction *InsertBefore); + static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd); ~CallInst(); diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h index 3342ea89c562..9335976f33a7 100644 --- a/llvm/include/llvm/LinkAllPasses.h +++ b/llvm/include/llvm/LinkAllPasses.h @@ -107,7 +107,6 @@ namespace { (void) llvm::createPostDomPrinterPass(); (void) llvm::createPostDomOnlyViewerPass(); (void) llvm::createPostDomViewerPass(); - (void) llvm::createRaiseAllocationsPass(); (void) llvm::createReassociatePass(); (void) llvm::createSCCPPass(); (void) llvm::createScalarReplAggregatesPass(); diff --git a/llvm/include/llvm/Support/StandardPasses.h b/llvm/include/llvm/Support/StandardPasses.h index c71e6b94fa27..611e78644824 100644 --- a/llvm/include/llvm/Support/StandardPasses.h +++ b/llvm/include/llvm/Support/StandardPasses.h @@ -96,8 +96,6 @@ namespace llvm { return; } - if (UnitAtATime) - PM->add(createRaiseAllocationsPass()); // call %malloc -> malloc inst PM->add(createCFGSimplificationPass()); // Clean up disgusting code if (UnitAtATime) { PM->add(createGlobalOptimizerPass()); // Optimize out global vars diff --git a/llvm/include/llvm/Transforms/IPO.h b/llvm/include/llvm/Transforms/IPO.h index 9189c430cbbb..5e1790442293 100644 --- a/llvm/include/llvm/Transforms/IPO.h +++ b/llvm/include/llvm/Transforms/IPO.h @@ -68,13 +68,6 @@ ModulePass *createConstantMergePass(); ModulePass *createGlobalOptimizerPass(); -//===----------------------------------------------------------------------===// -/// createRaiseAllocationsPass - Return a new pass that transforms malloc and -/// free function calls into malloc and free instructions. -/// -ModulePass *createRaiseAllocationsPass(); - - //===----------------------------------------------------------------------===// /// createDeadTypeEliminationPass - Return a new pass that eliminates symbol /// table entries for types that are never used. diff --git a/llvm/lib/Analysis/IPA/Andersens.cpp b/llvm/lib/Analysis/IPA/Andersens.cpp index b5129a7d3ba1..e37a9dbb7ac8 100644 --- a/llvm/lib/Analysis/IPA/Andersens.cpp +++ b/llvm/lib/Analysis/IPA/Andersens.cpp @@ -1017,6 +1017,8 @@ bool Andersens::AnalyzeUsesOfFunction(Value *V) { } } else if (GetElementPtrInst *GEP = dyn_cast(*UI)) { if (AnalyzeUsesOfFunction(GEP)) return true; + } else if (isa(*UI) || isFreeCall(*UI)) { + return false; } else if (CallInst *CI = dyn_cast(*UI)) { // Make sure that this is just the function being called, not that it is // passing into the function. @@ -1038,8 +1040,6 @@ bool Andersens::AnalyzeUsesOfFunction(Value *V) { } else if (ICmpInst *ICI = dyn_cast(*UI)) { if (!isa(ICI->getOperand(1))) return true; // Allow comparison against null. - } else if (isa(*UI)) { - return false; } else { return true; } diff --git a/llvm/lib/Analysis/IPA/GlobalsModRef.cpp b/llvm/lib/Analysis/IPA/GlobalsModRef.cpp index 7949288340a8..d83ea48080ce 100644 --- a/llvm/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/llvm/lib/Analysis/IPA/GlobalsModRef.cpp @@ -240,6 +240,8 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, } else if (BitCastInst *BCI = dyn_cast(*UI)) { if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest)) return true; + } else if (isa(*UI) || isFreeCall(*UI)) { + Writers.push_back(cast(*UI)->getParent()->getParent()); } else if (CallInst *CI = dyn_cast(*UI)) { // Make sure that this is just the function being called, not that it is // passing into the function. @@ -261,8 +263,6 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, } else if (ICmpInst *ICI = dyn_cast(*UI)) { if (!isa(ICI->getOperand(1))) return true; // Allow comparison against null. - } else if (FreeInst *F = dyn_cast(*UI)) { - Writers.push_back(F->getParent()->getParent()); } else { return true; } @@ -439,7 +439,8 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { if (cast(*II).isVolatile()) // Treat volatile stores as reading memory somewhere. FunctionEffect |= Ref; - } else if (isMalloc(&cast(*II)) || isa(*II)) { + } else if (isMalloc(&cast(*II)) || isa(*II) || + isFreeCall(&cast(*II))) { FunctionEffect |= ModRef; } diff --git a/llvm/lib/Analysis/MallocHelper.cpp b/llvm/lib/Analysis/MallocHelper.cpp index e7bb41eeec28..511de9d6a518 100644 --- a/llvm/lib/Analysis/MallocHelper.cpp +++ b/llvm/lib/Analysis/MallocHelper.cpp @@ -263,3 +263,29 @@ Value* llvm::getMallocArraySize(CallInst* CI, LLVMContext &Context, assert(BO && "getMallocArraySize not constant but not multiplication either"); return BO->getOperand(0); } + +/// isFreeCall - Returns true if the the value is a call to the builtin free() +bool llvm::isFreeCall(const Value* I) { + const CallInst *CI = dyn_cast(I); + if (!CI) + return false; + + const Module* M = CI->getParent()->getParent()->getParent(); + Function *FreeFunc = M->getFunction("free"); + + if (CI->getOperand(0) != FreeFunc) + return false; + + // Check free prototype. + // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin + // attribute will exist. + const FunctionType *FTy = FreeFunc->getFunctionType(); + if (FTy->getReturnType() != Type::getVoidTy(M->getContext())) + return false; + if (FTy->getNumParams() != 1) + return false; + if (FTy->param_begin()->get() != Type::getInt8PtrTy(M->getContext())) + return false; + + return true; +} diff --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp index c3aa5bc9306d..ce7674003fe0 100644 --- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -118,6 +118,10 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall, // FreeInsts erase the entire structure PointerSize = ~0ULL; + } else if (isFreeCall(Inst)) { + Pointer = Inst->getOperand(0); + // calls to free() erase the entire structure + PointerSize = ~0ULL; } else if (isa(Inst) || isa(Inst)) { // Debug intrinsics don't cause dependences. if (isa(Inst)) continue; @@ -314,6 +318,10 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) { MemPtr = LI->getPointerOperand(); MemSize = AA->getTypeStoreSize(LI->getType()); } + } else if (isFreeCall(QueryInst)) { + MemPtr = QueryInst->getOperand(0); + // calls to free() erase the entire structure, not just a field. + MemSize = ~0UL; } else if (isa(QueryInst) || isa(QueryInst)) { CallSite QueryCS = CallSite::get(QueryInst); bool isReadOnly = AA->onlyReadsMemory(QueryCS); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 271567bd1e9b..52fd2b21e1a0 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -2800,7 +2800,7 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, // Memory. case lltok::kw_alloca: return ParseAlloc(Inst, PFS); case lltok::kw_malloc: return ParseAlloc(Inst, PFS, BB, false); - case lltok::kw_free: return ParseFree(Inst, PFS); + case lltok::kw_free: return ParseFree(Inst, PFS, BB); case lltok::kw_load: return ParseLoad(Inst, PFS, false); case lltok::kw_store: return ParseStore(Inst, PFS, false); case lltok::kw_volatile: @@ -3496,12 +3496,13 @@ bool LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS, /// ParseFree /// ::= 'free' TypeAndValue -bool LLParser::ParseFree(Instruction *&Inst, PerFunctionState &PFS) { +bool LLParser::ParseFree(Instruction *&Inst, PerFunctionState &PFS, + BasicBlock* BB) { Value *Val; LocTy Loc; if (ParseTypeAndValue(Val, Loc, PFS)) return true; if (!isa(Val->getType())) return Error(Loc, "operand to free must be a pointer"); - Inst = new FreeInst(Val); + Inst = CallInst::CreateFree(Val, BB); return false; } diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h index 5dd6a2e7007e..b6877bc7c11d 100644 --- a/llvm/lib/AsmParser/LLParser.h +++ b/llvm/lib/AsmParser/LLParser.h @@ -280,7 +280,7 @@ namespace llvm { bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail); bool ParseAlloc(Instruction *&I, PerFunctionState &PFS, BasicBlock *BB = 0, bool isAlloca = true); - bool ParseFree(Instruction *&I, PerFunctionState &PFS); + bool ParseFree(Instruction *&I, PerFunctionState &PFS, BasicBlock *BB); bool ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile); bool ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile); bool ParseGetResult(Instruction *&I, PerFunctionState &PFS); diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 3a385cbe382d..ffd330c74ec7 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2073,7 +2073,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { if (getValueTypePair(Record, OpNum, NextValueNo, Op) || OpNum != Record.size()) return Error("Invalid FREE record"); - I = new FreeInst(Op); + if (!CurBB) return Error("Invalid free instruction with no BB"); + I = CallInst::CreateFree(Op, CurBB); InstructionList.push_back(I); break; } diff --git a/llvm/lib/Transforms/IPO/CMakeLists.txt b/llvm/lib/Transforms/IPO/CMakeLists.txt index 5c2880155547..92bef3bb75e9 100644 --- a/llvm/lib/Transforms/IPO/CMakeLists.txt +++ b/llvm/lib/Transforms/IPO/CMakeLists.txt @@ -19,7 +19,6 @@ add_llvm_library(LLVMipo PartialInlining.cpp PartialSpecialization.cpp PruneEH.cpp - RaiseAllocations.cpp StripDeadPrototypes.cpp StripSymbols.cpp StructRetPromotion.cpp diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 9ced2e89a7e6..0bc086f432cd 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -1364,10 +1364,11 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, OrigBB->getParent()); BasicBlock *NextBlock = BasicBlock::Create(Context, "next", OrigBB->getParent()); - BranchInst::Create(FreeBlock, NextBlock, Cmp, NullPtrBlock); + Instruction *BI = BranchInst::Create(FreeBlock, NextBlock, + Cmp, NullPtrBlock); // Fill in FreeBlock. - new FreeInst(GVVal, FreeBlock); + CallInst::CreateFree(GVVal, BI); new StoreInst(Constant::getNullValue(GVVal->getType()), FieldGlobals[i], FreeBlock); BranchInst::Create(NextBlock, FreeBlock); diff --git a/llvm/lib/Transforms/IPO/IPO.cpp b/llvm/lib/Transforms/IPO/IPO.cpp index 43066076ca68..83e8624fe09d 100644 --- a/llvm/lib/Transforms/IPO/IPO.cpp +++ b/llvm/lib/Transforms/IPO/IPO.cpp @@ -63,7 +63,7 @@ void LLVMAddPruneEHPass(LLVMPassManagerRef PM) { } void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createRaiseAllocationsPass()); + // FIXME: Remove in LLVM 3.0. } void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) { diff --git a/llvm/lib/Transforms/IPO/RaiseAllocations.cpp b/llvm/lib/Transforms/IPO/RaiseAllocations.cpp deleted file mode 100644 index deb4405754d7..000000000000 --- a/llvm/lib/Transforms/IPO/RaiseAllocations.cpp +++ /dev/null @@ -1,173 +0,0 @@ -//===- RaiseAllocations.cpp - Convert @free calls to insts ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the RaiseAllocations pass which convert free calls to free -// instructions. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "raiseallocs" -#include "llvm/Transforms/IPO.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Instructions.h" -#include "llvm/Pass.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/Compiler.h" -#include "llvm/ADT/Statistic.h" -#include -using namespace llvm; - -STATISTIC(NumRaised, "Number of allocations raised"); - -namespace { - // RaiseAllocations - Turn @free calls into the appropriate - // instruction. - // - class VISIBILITY_HIDDEN RaiseAllocations : public ModulePass { - Function *FreeFunc; // Functions in the module we are processing - // Initialized by doPassInitializationVirt - public: - static char ID; // Pass identification, replacement for typeid - RaiseAllocations() - : ModulePass(&ID), FreeFunc(0) {} - - // doPassInitialization - For the raise allocations pass, this finds a - // declaration for free if it exists. - // - void doInitialization(Module &M); - - // run - This method does the actual work of converting instructions over. - // - bool runOnModule(Module &M); - }; -} // end anonymous namespace - -char RaiseAllocations::ID = 0; -static RegisterPass -X("raiseallocs", "Raise allocations from calls to instructions"); - -// createRaiseAllocationsPass - The interface to this file... -ModulePass *llvm::createRaiseAllocationsPass() { - return new RaiseAllocations(); -} - - -// If the module has a symbol table, they might be referring to the free -// function. If this is the case, grab the method pointers that the module is -// using. -// -// Lookup @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) { - // Get free prototype if it exists! - FreeFunc = M.getFunction("free"); - if (FreeFunc) { - const FunctionType* TyWeHave = FreeFunc->getFunctionType(); - - // Get the expected prototype for void free(i8*) - const FunctionType *Free1Type = - FunctionType::get(Type::getVoidTy(M.getContext()), - std::vector(1, PointerType::getUnqual( - Type::getInt8Ty(M.getContext()))), - false); - - if (TyWeHave != Free1Type) { - // Check to see if the prototype was forgotten, giving us - // void (...) * free - // This handles the common forward declaration of: 'void free();' - const FunctionType* Free2Type = - FunctionType::get(Type::getVoidTy(M.getContext()), true); - - if (TyWeHave != Free2Type) { - // One last try, check to see if we can find free as - // int (...)* free. This handles the case where NOTHING was declared. - const FunctionType* Free3Type = - FunctionType::get(Type::getInt32Ty(M.getContext()), true); - - if (TyWeHave != Free3Type) { - // Give up. - FreeFunc = 0; - } - } - } - } - - // Don't mess with locally defined versions of these functions... - if (FreeFunc && !FreeFunc->isDeclaration()) FreeFunc = 0; -} - -// run - Transform calls into instructions... -// -bool RaiseAllocations::runOnModule(Module &M) { - // Find the free prototype... - doInitialization(M); - - bool Changed = false; - - // Process all free calls... - if (FreeFunc) { - std::vector Users(FreeFunc->use_begin(), FreeFunc->use_end()); - std::vector EqPointers; // Values equal to FreeFunc - - while (!Users.empty()) { - User *U = Users.back(); - Users.pop_back(); - - if (Instruction *I = dyn_cast(U)) { - if (isa(I)) - continue; - CallSite CS = CallSite::get(I); - if (CS.getInstruction() && !CS.arg_empty() && - (CS.getCalledFunction() == FreeFunc || - std::find(EqPointers.begin(), EqPointers.end(), - CS.getCalledValue()) != EqPointers.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 weird code like this: - // free((long)ptr); - // - Value *Source = *CS.arg_begin(); - if (!isa(Source->getType())) - Source = new IntToPtrInst(Source, - Type::getInt8PtrTy(M.getContext()), - "FreePtrCast", I); - new FreeInst(Source, I); - - // If the old instruction was an invoke, add an unconditional branch - // before the invoke, which will become the new terminator. - if (InvokeInst *II = dyn_cast(I)) - BranchInst::Create(II->getNormalDest(), I); - - // Delete the old call site - if (I->getType() != Type::getVoidTy(M.getContext())) - I->replaceAllUsesWith(UndefValue::get(I->getType())); - I->eraseFromParent(); - Changed = true; - ++NumRaised; - } - } else if (GlobalValue *GV = dyn_cast(U)) { - Users.insert(Users.end(), GV->use_begin(), GV->use_end()); - EqPointers.push_back(GV); - } else if (ConstantExpr *CE = dyn_cast(U)) { - if (CE->isCast()) { - Users.insert(Users.end(), CE->use_begin(), CE->use_end()); - EqPointers.push_back(CE); - } - } - } - } - - return Changed; -} diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index a7b3e7524fa2..f55d8b2accbb 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/MallocHelper.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Target/TargetData.h" #include "llvm/Transforms/Utils/Local.h" @@ -49,7 +50,7 @@ namespace { } bool runOnBasicBlock(BasicBlock &BB); - bool handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep); + bool handleFreeWithNonTrivialDependency(Instruction *F, MemDepResult Dep); bool handleEndBlock(BasicBlock &BB); bool RemoveUndeadPointers(Value* Ptr, uint64_t killPointerSize, BasicBlock::iterator& BBI, @@ -88,7 +89,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { Instruction *Inst = BBI++; // If we find a store or a free, get its memory dependence. - if (!isa(Inst) && !isa(Inst)) + if (!isa(Inst) && !isa(Inst) && !isFreeCall(Inst)) continue; // Don't molest volatile stores or do queries that will return "clobber". @@ -103,8 +104,8 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { if (InstDep.isNonLocal()) continue; // Handle frees whose dependencies are non-trivial. - if (FreeInst *FI = dyn_cast(Inst)) { - MadeChange |= handleFreeWithNonTrivialDependency(FI, InstDep); + if (isa(Inst) || isFreeCall(Inst)) { + MadeChange |= handleFreeWithNonTrivialDependency(Inst, InstDep); continue; } @@ -165,7 +166,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { /// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose /// dependency is a store to a field of that structure. -bool DSE::handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep) { +bool DSE::handleFreeWithNonTrivialDependency(Instruction *F, MemDepResult Dep) { AliasAnalysis &AA = getAnalysis(); StoreInst *Dependency = dyn_cast_or_null(Dep.getInst()); @@ -175,7 +176,8 @@ bool DSE::handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep) { Value *DepPointer = Dependency->getPointerOperand()->getUnderlyingObject(); // Check for aliasing. - if (AA.alias(F->getPointerOperand(), 1, DepPointer, 1) != + Value* FreeVal = isa(F) ? F->getOperand(0) : F->getOperand(1); + if (AA.alias(FreeVal, 1, DepPointer, 1) != AliasAnalysis::MustAlias) return false; diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index 21554c108d68..be4f77573177 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp @@ -286,6 +286,7 @@ namespace { Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP); Instruction *visitAllocaInst(AllocaInst &AI); Instruction *visitFreeInst(FreeInst &FI); + Instruction *visitFree(Instruction &FI); Instruction *visitLoadInst(LoadInst &LI); Instruction *visitStoreInst(StoreInst &SI); Instruction *visitBranchInst(BranchInst &BI); @@ -9747,6 +9748,9 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) { /// the heavy lifting. /// Instruction *InstCombiner::visitCallInst(CallInst &CI) { + if (isFreeCall(&CI)) + return visitFree(CI); + // If the caller function is nounwind, mark the call as nounwind, even if the // callee isn't. if (CI.getParent()->getParent()->doesNotThrow() && @@ -11337,6 +11341,42 @@ Instruction *InstCombiner::visitFreeInst(FreeInst &FI) { return 0; } +Instruction *InstCombiner::visitFree(Instruction &FI) { + Value *Op = FI.getOperand(1); + + // free undef -> unreachable. + if (isa(Op)) { + // Insert a new store to null because we cannot modify the CFG here. + new StoreInst(ConstantInt::getTrue(*Context), + UndefValue::get(Type::getInt1PtrTy(*Context)), &FI); + return EraseInstFromFunction(FI); + } + + // If we have 'free null' delete the instruction. This can happen in stl code + // when lots of inlining happens. + if (isa(Op)) + return EraseInstFromFunction(FI); + + // FIXME: Bring back free (gep X, 0,0,0,0) into free(X) transform + + if (isMalloc(Op)) { + if (CallInst* CI = extractMallocCallFromBitCast(Op)) { + if (Op->hasOneUse() && CI->hasOneUse()) { + EraseInstFromFunction(FI); + EraseInstFromFunction(*CI); + return EraseInstFromFunction(*cast(Op)); + } + } else { + // Op is a call to malloc + if (Op->hasOneUse()) { + EraseInstFromFunction(FI); + return EraseInstFromFunction(*cast(Op)); + } + } + } + + return 0; +} /// InstCombineLoadCast - Fold 'load (cast P)' -> cast (load P)' when possible. static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI, diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index e3dd54e8bcf2..1bb5f4ae7fd1 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -30,6 +30,7 @@ #include "llvm/LLVMContext.h" #include "llvm/Pass.h" #include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/MallocHelper.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Support/CallSite.h" @@ -400,7 +401,9 @@ private: void visitStoreInst (Instruction &I); void visitLoadInst (LoadInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); - void visitCallInst (CallInst &I) { + void visitCallInst (CallInst &I) { + if (isFreeCall(&I)) + return; visitCallSite(CallSite::get(&I)); } void visitInvokeInst (InvokeInst &II) { diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index b62261119c75..940f5a9ec46c 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -24,6 +24,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/MallocHelper.h" #include "llvm/Analysis/ProfileInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/GetElementPtrTypeIterator.h" @@ -59,7 +60,7 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom) { // If we see a free or a call which may write to memory (i.e. which might do // a free) the pointer could be marked invalid. - if (isa(BBI) || + if (isa(BBI) || isFreeCall(BBI) || (isa(BBI) && BBI->mayWriteToMemory() && !isa(BBI))) return false; diff --git a/llvm/lib/Transforms/Utils/LowerAllocations.cpp b/llvm/lib/Transforms/Utils/LowerAllocations.cpp index 9c9113daa93a..f64a30f5e80a 100644 --- a/llvm/lib/Transforms/Utils/LowerAllocations.cpp +++ b/llvm/lib/Transforms/Utils/LowerAllocations.cpp @@ -102,12 +102,8 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) { // Loop over all of the instructions, looking for free instructions for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) { if (FreeInst *FI = dyn_cast(I)) { - Value *PtrCast = - new BitCastInst(FI->getOperand(0), - Type::getInt8PtrTy(BB.getContext()), "", I); - // Insert a call to the free function... - CallInst::Create(FreeFunc, PtrCast, "", I)->setTailCall(); + CallInst::CreateFree(FI->getOperand(0), I); // Delete the old free instruction I = --BBIL.erase(I); diff --git a/llvm/lib/VMCore/Instructions.cpp b/llvm/lib/VMCore/Instructions.cpp index 99a28594e6ca..60e203a7e0bc 100644 --- a/llvm/lib/VMCore/Instructions.cpp +++ b/llvm/lib/VMCore/Instructions.cpp @@ -559,6 +559,51 @@ Instruction *CallInst::CreateMalloc(BasicBlock *InsertAtEnd, ArraySize, MallocF, Name); } +static Instruction* createFree(Value* Source, Instruction *InsertBefore, + BasicBlock *InsertAtEnd) { + assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) && + "createFree needs either InsertBefore or InsertAtEnd"); + assert(isa(Source->getType()) && + "Can not free something of nonpointer type!"); + + BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd; + Module* M = BB->getParent()->getParent(); + + const Type *VoidTy = Type::getVoidTy(M->getContext()); + const Type *IntPtrTy = Type::getInt8PtrTy(M->getContext()); + // prototype free as "void free(void*)" + Constant *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, NULL); + + CallInst* Result = NULL; + Value *PtrCast = Source; + if (InsertBefore) { + if (Source->getType() != IntPtrTy) + PtrCast = new BitCastInst(Source, IntPtrTy, "", InsertBefore); + Result = CallInst::Create(FreeFunc, PtrCast, "", InsertBefore); + } else { + if (Source->getType() != IntPtrTy) + PtrCast = new BitCastInst(Source, IntPtrTy, "", InsertAtEnd); + Result = CallInst::Create(FreeFunc, PtrCast, ""); + } + Result->setTailCall(); + + return Result; +} + +/// CreateFree - Generate the IR for a call to the builtin free function. +void CallInst::CreateFree(Value* Source, Instruction *InsertBefore) { + createFree(Source, InsertBefore, NULL); +} + +/// CreateFree - Generate the IR for a call to the builtin free function. +/// Note: This function does not add the call to the basic block, that is the +/// responsibility of the caller. +Instruction* CallInst::CreateFree(Value* Source, BasicBlock *InsertAtEnd) { + Instruction* FreeCall = createFree(Source, NULL, InsertAtEnd); + assert(FreeCall && "CreateFree did not create a CallInst"); + return FreeCall; +} + //===----------------------------------------------------------------------===// // InvokeInst Implementation //===----------------------------------------------------------------------===// diff --git a/llvm/test/Transforms/InstCombine/malloc-free-delete.ll b/llvm/test/Transforms/InstCombine/malloc-free-delete.ll index fd91e447bddd..a4b7496ef403 100644 --- a/llvm/test/Transforms/InstCombine/malloc-free-delete.ll +++ b/llvm/test/Transforms/InstCombine/malloc-free-delete.ll @@ -1,11 +1,13 @@ -; RUN: opt < %s -instcombine -S | grep {ret i32 0} -; RUN: opt < %s -instcombine -globaldce -S | not grep malloc +; RUN: opt < %s -instcombine -globaldce -S | FileCheck %s ; PR1201 define i32 @main(i32 %argc, i8** %argv) { %c_19 = alloca i8* ; [#uses=2] %malloc_206 = malloc i8, i32 10 ; [#uses=1] +; CHECK-NOT: malloc store i8* %malloc_206, i8** %c_19 %tmp_207 = load i8** %c_19 ; [#uses=1] free i8* %tmp_207 +; CHECK-NOT: free ret i32 0 +; CHECK: ret i32 0 } diff --git a/llvm/test/Transforms/RaiseAllocations/2004-11-08-FreeUseCrash.ll b/llvm/test/Transforms/RaiseAllocations/2004-11-08-FreeUseCrash.ll deleted file mode 100644 index 75e02e84fac9..000000000000 --- a/llvm/test/Transforms/RaiseAllocations/2004-11-08-FreeUseCrash.ll +++ /dev/null @@ -1,10 +0,0 @@ -; RUN: opt < %s -raiseallocs -disable-output - -define void @main() { - %tmp.13 = call i32 (...)* @free( i32 32 ) ; [#uses=1] - %tmp.14 = inttoptr i32 %tmp.13 to i32* ; [#uses=0] - ret void -} - -declare i32 @free(...) - diff --git a/llvm/test/Transforms/RaiseAllocations/2007-10-17-InvokeFree.ll b/llvm/test/Transforms/RaiseAllocations/2007-10-17-InvokeFree.ll deleted file mode 100644 index 675bb3d829f7..000000000000 --- a/llvm/test/Transforms/RaiseAllocations/2007-10-17-InvokeFree.ll +++ /dev/null @@ -1,17 +0,0 @@ -; RUN: opt < %s -raiseallocs -stats -disable-output |& \ -; RUN: not grep {Number of allocations raised} -define void @foo() { -entry: - %buffer = alloca i16* - %tmp = load i16** %buffer, align 8 - invoke i32(...)* @free(i16* %tmp) - to label %invcont unwind label %unwind -invcont: - br label %finally -unwind: - br label %finally -finally: - ret void -} -declare i32 @free(...) - diff --git a/llvm/test/Transforms/RaiseAllocations/FreeCastConstantExpr.ll b/llvm/test/Transforms/RaiseAllocations/FreeCastConstantExpr.ll deleted file mode 100644 index 1cf072910a60..000000000000 --- a/llvm/test/Transforms/RaiseAllocations/FreeCastConstantExpr.ll +++ /dev/null @@ -1,11 +0,0 @@ -; This situation can occur due to the funcresolve pass. -; -; RUN: opt < %s -raiseallocs -S | not grep call - -declare void @free(i8*) - -define void @test(i32* %P) { - call void bitcast (void (i8*)* @free to void (i32*)*)( i32* %P ) - ret void -} - diff --git a/llvm/test/Transforms/RaiseAllocations/dg.exp b/llvm/test/Transforms/RaiseAllocations/dg.exp deleted file mode 100644 index f2005891a59a..000000000000 --- a/llvm/test/Transforms/RaiseAllocations/dg.exp +++ /dev/null @@ -1,3 +0,0 @@ -load_lib llvm.exp - -RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/llvm/utils/findoptdiff b/llvm/utils/findoptdiff index 36620d932cb3..4f8d08dbffe1 100755 --- a/llvm/utils/findoptdiff +++ b/llvm/utils/findoptdiff @@ -70,7 +70,7 @@ dis2="$llvm2/Debug/bin/llvm-dis" opt1="$llvm1/Debug/bin/opt" opt2="$llvm2/Debug/bin/opt" -all_switches="-verify -lowersetjmp -raiseallocs -simplifycfg -mem2reg -globalopt -globaldce -ipconstprop -deadargelim -instcombine -simplifycfg -prune-eh -inline -simplify-libcalls -argpromotion -tailduplicate -simplifycfg -scalarrepl -instcombine -predsimplify -condprop -tailcallelim -simplifycfg -reassociate -licm -loop-unswitch -instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp -instcombine -condprop -dse -dce -simplifycfg -deadtypeelim -constmerge -internalize -ipsccp -globalopt -constmerge -deadargelim -inline -prune-eh -globalopt -globaldce -argpromotion -instcombine -predsimplify -scalarrepl -globalsmodref-aa -licm -load-vn -gcse -dse -instcombine -simplifycfg -verify" +all_switches="-verify -lowersetjmp -simplifycfg -mem2reg -globalopt -globaldce -ipconstprop -deadargelim -instcombine -simplifycfg -prune-eh -inline -simplify-libcalls -argpromotion -tailduplicate -simplifycfg -scalarrepl -instcombine -predsimplify -condprop -tailcallelim -simplifycfg -reassociate -licm -loop-unswitch -instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp -instcombine -condprop -dse -dce -simplifycfg -deadtypeelim -constmerge -internalize -ipsccp -globalopt -constmerge -deadargelim -inline -prune-eh -globalopt -globaldce -argpromotion -instcombine -predsimplify -scalarrepl -globalsmodref-aa -licm -load-vn -gcse -dse -instcombine -simplifycfg -verify" #counter=0 function tryit {