diff options
Diffstat (limited to 'lib')
29 files changed, 92 insertions, 314 deletions
diff --git a/lib/Analysis/AliasSetTracker.cpp b/lib/Analysis/AliasSetTracker.cpp index 081f478..5b1b7d1 100644 --- a/lib/Analysis/AliasSetTracker.cpp +++ b/lib/Analysis/AliasSetTracker.cpp @@ -13,6 +13,7 @@ #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MallocHelper.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/Pass.h" @@ -296,12 +297,6 @@ bool AliasSetTracker::add(StoreInst *SI) { return NewPtr; } -bool AliasSetTracker::add(FreeInst *FI) { - bool NewPtr; - addPointer(FI->getOperand(0), ~0, AliasSet::Mods, NewPtr); - return NewPtr; -} - bool AliasSetTracker::add(VAArgInst *VAAI) { bool NewPtr; addPointer(VAAI->getOperand(0), ~0, AliasSet::ModRef, NewPtr); @@ -310,6 +305,13 @@ bool AliasSetTracker::add(VAArgInst *VAAI) { bool AliasSetTracker::add(CallSite CS) { + Instruction* Inst = CS.getInstruction(); + if (isFreeCall(Inst)) { + bool NewPtr; + addPointer(Inst->getOperand(1), ~0, AliasSet::Mods, NewPtr); + return NewPtr; + } + if (isa<DbgInfoIntrinsic>(CS.getInstruction())) return true; // Ignore DbgInfo Intrinsics. if (AA.doesNotAccessMemory(CS)) @@ -337,8 +339,6 @@ bool AliasSetTracker::add(Instruction *I) { return add(CI); else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) return add(II); - else if (FreeInst *FI = dyn_cast<FreeInst>(I)) - return add(FI); else if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I)) return add(VAAI); return true; @@ -427,13 +427,6 @@ bool AliasSetTracker::remove(StoreInst *SI) { return true; } -bool AliasSetTracker::remove(FreeInst *FI) { - AliasSet *AS = findAliasSetForPointer(FI->getOperand(0), ~0); - if (!AS) return false; - remove(*AS); - return true; -} - bool AliasSetTracker::remove(VAArgInst *VAAI) { AliasSet *AS = findAliasSetForPointer(VAAI->getOperand(0), ~0); if (!AS) return false; @@ -442,6 +435,14 @@ bool AliasSetTracker::remove(VAArgInst *VAAI) { } bool AliasSetTracker::remove(CallSite CS) { + Instruction* Inst = CS.getInstruction(); + if (isFreeCall(Inst)) { + AliasSet *AS = findAliasSetForPointer(Inst->getOperand(1), ~0); + if (!AS) return false; + remove(*AS); + return true; + } + if (AA.doesNotAccessMemory(CS)) return false; // doesn't alias anything @@ -459,8 +460,6 @@ bool AliasSetTracker::remove(Instruction *I) { return remove(SI); else if (CallInst *CI = dyn_cast<CallInst>(I)) return remove(CI); - else if (FreeInst *FI = dyn_cast<FreeInst>(I)) - return remove(FI); else if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I)) return remove(VAAI); return true; diff --git a/lib/Analysis/CaptureTracking.cpp b/lib/Analysis/CaptureTracking.cpp index b30ac71..649b760 100644 --- a/lib/Analysis/CaptureTracking.cpp +++ b/lib/Analysis/CaptureTracking.cpp @@ -17,6 +17,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/MallocHelper.h" #include "llvm/Instructions.h" #include "llvm/Value.h" #include "llvm/ADT/SmallSet.h" @@ -48,6 +49,9 @@ bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures) { switch (I->getOpcode()) { case Instruction::Call: + if (isFreeCall(I)) + // Freeing a pointer does not cause it to be captured. + break; case Instruction::Invoke: { CallSite CS = CallSite::get(I); // Not captured if the callee is readonly, doesn't return a copy through @@ -73,9 +77,6 @@ bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures) { // captured. break; } - case Instruction::Free: - // Freeing a pointer does not cause it to be captured. - break; case Instruction::Load: // Loading from a pointer does not cause it to be captured. break; diff --git a/lib/Analysis/IPA/Andersens.cpp b/lib/Analysis/IPA/Andersens.cpp index 6372342..78ec06f 100644 --- a/lib/Analysis/IPA/Andersens.cpp +++ b/lib/Analysis/IPA/Andersens.cpp @@ -1016,7 +1016,7 @@ bool Andersens::AnalyzeUsesOfFunction(Value *V) { } } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(*UI)) { if (AnalyzeUsesOfFunction(GEP)) return true; - } else if (isa<FreeInst>(*UI) || isFreeCall(*UI)) { + } else if (isFreeCall(*UI)) { return false; } else if (CallInst *CI = dyn_cast<CallInst>(*UI)) { // Make sure that this is just the function being called, not that it is @@ -1156,7 +1156,6 @@ void Andersens::visitInstruction(Instruction &I) { case Instruction::Switch: case Instruction::Unwind: case Instruction::Unreachable: - case Instruction::Free: case Instruction::ICmp: case Instruction::FCmp: return; diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index 01090f1..011b0ef 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/lib/Analysis/IPA/GlobalsModRef.cpp @@ -238,7 +238,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, } else if (BitCastInst *BCI = dyn_cast<BitCastInst>(*UI)) { if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest)) return true; - } else if (isa<FreeInst>(*UI) || isFreeCall(*UI)) { + } else if (isFreeCall(*UI)) { Writers.push_back(cast<Instruction>(*UI)->getParent()->getParent()); } else if (CallInst *CI = dyn_cast<CallInst>(*UI)) { // Make sure that this is just the function being called, not that it is @@ -437,7 +437,7 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { if (cast<StoreInst>(*II).isVolatile()) // Treat volatile stores as reading memory somewhere. FunctionEffect |= Ref; - } else if (isMalloc(&cast<Instruction>(*II)) || isa<FreeInst>(*II) || + } else if (isMalloc(&cast<Instruction>(*II)) || isFreeCall(&cast<Instruction>(*II))) { FunctionEffect |= ModRef; } diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp index 4f010b6..febdd91 100644 --- a/lib/Analysis/InlineCost.cpp +++ b/lib/Analysis/InlineCost.cpp @@ -130,10 +130,6 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { NumInsts += InlineConstants::CallPenalty; } - // These, too, are calls. - if (isa<FreeInst>(II)) - NumInsts += InlineConstants::CallPenalty; - if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) { if (!AI->isStaticAlloca()) this->usesDynamicAlloca = true; diff --git a/lib/Analysis/InstCount.cpp b/lib/Analysis/InstCount.cpp index c4f3b68..a4b041f 100644 --- a/lib/Analysis/InstCount.cpp +++ b/lib/Analysis/InstCount.cpp @@ -74,11 +74,11 @@ FunctionPass *llvm::createInstCountPass() { return new InstCount(); } bool InstCount::runOnFunction(Function &F) { unsigned StartMemInsts = NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst + - NumInvokeInst + NumAllocaInst + NumFreeInst; + NumInvokeInst + NumAllocaInst; visit(F); unsigned EndMemInsts = NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst + - NumInvokeInst + NumAllocaInst + NumFreeInst; + NumInvokeInst + NumAllocaInst; TotalMemInst += EndMemInsts-StartMemInsts; return false; } diff --git a/lib/Analysis/MallocHelper.cpp b/lib/Analysis/MallocHelper.cpp index 511de9d..70afa88 100644 --- a/lib/Analysis/MallocHelper.cpp +++ b/lib/Analysis/MallocHelper.cpp @@ -1,4 +1,4 @@ -//===-- MallocHelper.cpp - Functions to identify malloc calls -------------===// +//===-- MallocFreeHelper.cpp - Identify calls to malloc and free builtins -===// // // The LLVM Compiler Infrastructure // @@ -8,7 +8,8 @@ //===----------------------------------------------------------------------===// // // This family of functions identifies calls to malloc, bitcasts of malloc -// calls, and the types and array sizes associated with them. +// calls, and the types and array sizes associated with them. It also +// identifies calls to the free builtin. // //===----------------------------------------------------------------------===// @@ -264,6 +265,10 @@ Value* llvm::getMallocArraySize(CallInst* CI, LLVMContext &Context, return BO->getOperand(0); } +//===----------------------------------------------------------------------===// +// free Call Utility Functions. +// + /// 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<CallInst>(I); diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp index ce76740..7b3fe64 100644 --- a/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -113,10 +113,9 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall, } else if (VAArgInst *V = dyn_cast<VAArgInst>(Inst)) { Pointer = V->getOperand(0); PointerSize = AA->getTypeStoreSize(V->getType()); - } else if (FreeInst *F = dyn_cast<FreeInst>(Inst)) { - Pointer = F->getPointerOperand(); - - // FreeInsts erase the entire structure + } else if (isFreeCall(Inst)) { + Pointer = Inst->getOperand(1); + // calls to free() erase the entire structure PointerSize = ~0ULL; } else if (isFreeCall(Inst)) { Pointer = Inst->getOperand(0); @@ -319,7 +318,7 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) { MemSize = AA->getTypeStoreSize(LI->getType()); } } else if (isFreeCall(QueryInst)) { - MemPtr = QueryInst->getOperand(0); + MemPtr = QueryInst->getOperand(1); // calls to free() erase the entire structure, not just a field. MemSize = ~0UL; } else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) { @@ -327,10 +326,6 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) { bool isReadOnly = AA->onlyReadsMemory(QueryCS); LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos, QueryParent); - } else if (FreeInst *FI = dyn_cast<FreeInst>(QueryInst)) { - MemPtr = FI->getPointerOperand(); - // FreeInsts erase the entire structure, not just a field. - MemSize = ~0UL; } else { // Non-memory instruction. LocalCache = MemDepResult::getClobber(--BasicBlock::iterator(ScanPos)); diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index f6cea88..4fb7ea9 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -606,6 +606,10 @@ lltok::Kind LLLexer::LexIdentifier() { // FIXME: Remove in LLVM 3.0. // Autoupgrade malloc instruction. return lltok::kw_malloc; + } else if (Len == 4 && !memcmp(StartChar, "free", 4)) { + // FIXME: Remove in LLVM 3.0. + // Autoupgrade malloc instruction. + return lltok::kw_free; } // Keywords for instructions. @@ -646,7 +650,6 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(unreachable, Unreachable); INSTKEYWORD(alloca, Alloca); - INSTKEYWORD(free, Free); INSTKEYWORD(load, Load); INSTKEYWORD(store, Store); INSTKEYWORD(getelementptr, GetElementPtr); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 037854e..535740b 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1054,11 +1054,6 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, Vals.push_back(VE.getValueID(I.getOperand(i))); break; - case Instruction::Free: - Code = bitc::FUNC_CODE_INST_FREE; - PushValueAndType(I.getOperand(0), InstID, Vals, VE); - break; - case Instruction::Alloca: Code = bitc::FUNC_CODE_INST_ALLOCA; Vals.push_back(VE.getTypeID(I.getType())); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index d862e40..f3a0622 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -5486,26 +5486,6 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { DAG.setRoot(Chain); } -void SelectionDAGLowering::visitFree(FreeInst &I) { - TargetLowering::ArgListTy Args; - TargetLowering::ArgListEntry Entry; - Entry.Node = getValue(I.getOperand(0)); - Entry.Ty = TLI.getTargetData()->getIntPtrType(*DAG.getContext()); - Args.push_back(Entry); - EVT IntPtr = TLI.getPointerTy(); - bool isTailCall = PerformTailCallOpt && - isInTailCallPosition(&I, Attribute::None, TLI); - std::pair<SDValue,SDValue> Result = - TLI.LowerCallTo(getRoot(), Type::getVoidTy(*DAG.getContext()), - false, false, false, false, - 0, CallingConv::C, isTailCall, - /*isReturnValueUsed=*/true, - DAG.getExternalSymbol("free", IntPtr), Args, DAG, - getCurDebugLoc()); - if (Result.second.getNode()) - DAG.setRoot(Result.second); -} - void SelectionDAGLowering::visitVAStart(CallInst &I) { DAG.setRoot(DAG.getNode(ISD::VASTART, getCurDebugLoc(), MVT::Other, getRoot(), diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h index 722b1d8..7470551 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h @@ -44,7 +44,6 @@ class FPExtInst; class FPToSIInst; class FPToUIInst; class FPTruncInst; -class FreeInst; class Function; class GetElementPtrInst; class GCFunctionInfo; @@ -528,7 +527,6 @@ private: void visitGetElementPtr(User &I); void visitSelect(User &I); - void visitFree(FreeInst &I); void visitAlloca(AllocaInst &I); void visitLoad(LoadInst &I); void visitStore(StoreInst &I); diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 151bd00..7ceb8e8 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -749,14 +749,6 @@ void Interpreter::visitAllocaInst(AllocaInst &I) { ECStack.back().Allocas.add(Memory); } -void Interpreter::visitFreeInst(FreeInst &I) { - ExecutionContext &SF = ECStack.back(); - assert(isa<PointerType>(I.getOperand(0)->getType()) && "Freeing nonptr?"); - GenericValue Value = getOperandValue(I.getOperand(0), SF); - // TODO: Check to make sure memory is allocated - free(GVTOP(Value)); // Free memory -} - // getElementOffset - The workhorse for getelementptr. // GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 43c18d0..eaa8ec5 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -140,7 +140,6 @@ public: void visitICmpInst(ICmpInst &I); void visitFCmpInst(FCmpInst &I); void visitAllocaInst(AllocaInst &I); - void visitFreeInst(FreeInst &I); void visitLoadInst(LoadInst &I); void visitStoreInst(StoreInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 27ed5c3..fb61651 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -303,7 +303,6 @@ namespace { bool visitBuiltinCall(CallInst &I, Intrinsic::ID ID, bool &WroteCallee); void visitAllocaInst(AllocaInst &I); - void visitFreeInst (FreeInst &I); void visitLoadInst (LoadInst &I); void visitStoreInst (StoreInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); @@ -3417,10 +3416,6 @@ void CWriter::visitAllocaInst(AllocaInst &I) { Out << ')'; } -void CWriter::visitFreeInst(FreeInst &I) { - llvm_unreachable("lowerallocations pass didn't work!"); -} - void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I, gep_type_iterator E, bool Static) { @@ -3685,7 +3680,6 @@ bool CTargetMachine::addPassesToEmitWholeFile(PassManager &PM, if (FileType != TargetMachine::AssemblyFile) return true; PM.add(createGCLoweringPass()); - PM.add(createLowerAllocationsPass()); PM.add(createLowerInvokePass()); PM.add(createCFGSimplificationPass()); // clean up after lower invoke. PM.add(new CBackendNameAllUsedStructsAndMergeFunctions()); diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 45c2a7b..9a6aa63 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -1258,11 +1258,6 @@ namespace { Out << "\");"; break; } - case Instruction::Free: { - Out << "FreeInst* " << iName << " = new FreeInst(" - << getCppName(I->getOperand(0)) << ", " << bbname << ");"; - break; - } case Instruction::Alloca: { const AllocaInst* allocaI = cast<AllocaInst>(I); Out << "AllocaInst* " << iName << " = new AllocaInst(" diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp index 5899ab3..f12ee78 100644 --- a/lib/Target/MSIL/MSILWriter.cpp +++ b/lib/Target/MSIL/MSILWriter.cpp @@ -1191,9 +1191,6 @@ void MSILWriter::printInstruction(const Instruction* Inst) { case Instruction::Alloca: printAllocaInstruction(cast<AllocaInst>(Inst)); break; - case Instruction::Free: - llvm_unreachable("LowerAllocationsPass used"); - break; case Instruction::Unreachable: printSimpleInstruction("ldstr", "\"Unreachable instruction\""); printSimpleInstruction("newobj", @@ -1699,7 +1696,6 @@ bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, if (FileType != TargetMachine::AssemblyFile) return true; MSILWriter* Writer = new MSILWriter(o); PM.add(createGCLoweringPass()); - PM.add(createLowerAllocationsPass()); // FIXME: Handle switch trougth native IL instruction "switch" PM.add(createLowerSwitchPass()); PM.add(createCFGSimplificationPass()); diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index f55d8b2..c10d236 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -89,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<StoreInst>(Inst) && !isa<FreeInst>(Inst) && !isFreeCall(Inst)) + if (!isa<StoreInst>(Inst) && !isFreeCall(Inst)) continue; // Don't molest volatile stores or do queries that will return "clobber". @@ -104,7 +104,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { if (InstDep.isNonLocal()) continue; // Handle frees whose dependencies are non-trivial. - if (isa<FreeInst>(Inst) || isFreeCall(Inst)) { + if (isFreeCall(Inst)) { MadeChange |= handleFreeWithNonTrivialDependency(Inst, InstDep); continue; } @@ -176,8 +176,7 @@ bool DSE::handleFreeWithNonTrivialDependency(Instruction *F, MemDepResult Dep) { Value *DepPointer = Dependency->getPointerOperand()->getUnderlyingObject(); // Check for aliasing. - Value* FreeVal = isa<FreeInst>(F) ? F->getOperand(0) : F->getOperand(1); - if (AA.alias(FreeVal, 1, DepPointer, 1) != + if (AA.alias(F->getOperand(1), 1, DepPointer, 1) != AliasAnalysis::MustAlias) return false; diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 7c0d223..fa84bb5 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -285,7 +285,6 @@ namespace { Instruction *visitPHINode(PHINode &PN); Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP); Instruction *visitAllocaInst(AllocaInst &AI); - Instruction *visitFreeInst(FreeInst &FI); Instruction *visitFree(Instruction &FI); Instruction *visitLoadInst(LoadInst &LI); Instruction *visitStoreInst(StoreInst &SI); @@ -11328,56 +11327,6 @@ Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) { return 0; } -Instruction *InstCombiner::visitFreeInst(FreeInst &FI) { - Value *Op = FI.getOperand(0); - - // free undef -> unreachable. - if (isa<UndefValue>(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<ConstantPointerNull>(Op)) - return EraseInstFromFunction(FI); - - // Change free <ty>* (cast <ty2>* X to <ty>*) into free <ty2>* X - if (BitCastInst *CI = dyn_cast<BitCastInst>(Op)) { - FI.setOperand(0, CI->getOperand(0)); - return &FI; - } - - // Change free (gep X, 0,0,0,0) into free(X) - if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(Op)) { - if (GEPI->hasAllZeroIndices()) { - Worklist.Add(GEPI); - FI.setOperand(0, GEPI->getOperand(0)); - return &FI; - } - } - - if (isMalloc(Op)) { - if (CallInst* CI = extractMallocCallFromBitCast(Op)) { - if (Op->hasOneUse() && CI->hasOneUse()) { - EraseInstFromFunction(FI); - EraseInstFromFunction(*CI); - return EraseInstFromFunction(*cast<Instruction>(Op)); - } - } else { - // Op is a call to malloc - if (Op->hasOneUse()) { - EraseInstFromFunction(FI); - return EraseInstFromFunction(*cast<Instruction>(Op)); - } - } - } - - return 0; -} - Instruction *InstCombiner::visitFree(Instruction &FI) { Value *Op = FI.getOperand(1); @@ -11394,9 +11343,8 @@ Instruction *InstCombiner::visitFree(Instruction &FI) { if (isa<ConstantPointerNull>(Op)) return EraseInstFromFunction(FI); - // FIXME: Bring back free (gep X, 0,0,0,0) into free(X) transform - - if (isMalloc(Op)) { + // If we have a malloc call whose only use is a free call, delete both. + if (isMalloc(Op)) if (CallInst* CI = extractMallocCallFromBitCast(Op)) { if (Op->hasOneUse() && CI->hasOneUse()) { EraseInstFromFunction(FI); @@ -11410,7 +11358,6 @@ Instruction *InstCombiner::visitFree(Instruction &FI) { return EraseInstFromFunction(*cast<Instruction>(Op)); } } - } return 0; } diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 1bb5f4a..4c56121 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -416,7 +416,6 @@ private: void visitAllocaInst (Instruction &I) { markOverdefined(&I); } void visitVANextInst (Instruction &I) { markOverdefined(&I); } void visitVAArgInst (Instruction &I) { markOverdefined(&I); } - void visitFreeInst (Instruction &I) { /*returns void*/ } void visitInstruction(Instruction &I) { // If a new instruction is added to LLVM that we don't handle... diff --git a/lib/Transforms/Utils/CMakeLists.txt b/lib/Transforms/Utils/CMakeLists.txt index f4394ea..fbc61d7 100644 --- a/lib/Transforms/Utils/CMakeLists.txt +++ b/lib/Transforms/Utils/CMakeLists.txt @@ -13,7 +13,6 @@ add_llvm_library(LLVMTransformUtils LCSSA.cpp Local.cpp LoopSimplify.cpp - LowerAllocations.cpp LowerInvoke.cpp LowerSwitch.cpp Mem2Reg.cpp diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 940f5a9..6e18b66 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -60,9 +60,8 @@ 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<FreeInst>(BBI) || isFreeCall(BBI) || - (isa<CallInst>(BBI) && BBI->mayWriteToMemory() && - !isa<DbgInfoIntrinsic>(BBI))) + if (isFreeCall(BBI) || (isa<CallInst>(BBI) && BBI->mayWriteToMemory() && + !isa<DbgInfoIntrinsic>(BBI))) return false; if (LoadInst *LI = dyn_cast<LoadInst>(BBI)) { diff --git a/lib/Transforms/Utils/LowerAllocations.cpp b/lib/Transforms/Utils/LowerAllocations.cpp deleted file mode 100644 index 5f7bf4c..0000000 --- a/lib/Transforms/Utils/LowerAllocations.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//===- LowerAllocations.cpp - Reduce free insts to calls ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The LowerAllocations transformation is a target-dependent tranformation -// because it depends on the size of data types and alignment constraints. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "lowerallocs" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" -#include "llvm/Module.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Constants.h" -#include "llvm/LLVMContext.h" -#include "llvm/Pass.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Target/TargetData.h" -using namespace llvm; - -STATISTIC(NumLowered, "Number of allocations lowered"); - -namespace { - /// LowerAllocations - Turn free instructions into @free calls. - /// - class LowerAllocations : public BasicBlockPass { - Constant *FreeFunc; // Functions in the module we are processing - // Initialized by doInitialization - public: - static char ID; // Pass ID, replacement for typeid - explicit LowerAllocations() - : BasicBlockPass(&ID), FreeFunc(0) {} - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<TargetData>(); - AU.setPreservesCFG(); - - // This is a cluster of orthogonal Transforms: - AU.addPreserved<UnifyFunctionExitNodes>(); - AU.addPreservedID(PromoteMemoryToRegisterID); - AU.addPreservedID(LowerSwitchID); - AU.addPreservedID(LowerInvokePassID); - } - - /// doPassInitialization - For the lower allocations pass, this ensures that - /// a module contains a declaration for a free function. - /// - bool doInitialization(Module &M); - - virtual bool doInitialization(Function &F) { - return doInitialization(*F.getParent()); - } - - /// runOnBasicBlock - This method does the actual work of converting - /// instructions over, assuming that the pass has already been initialized. - /// - bool runOnBasicBlock(BasicBlock &BB); - }; -} - -char LowerAllocations::ID = 0; -static RegisterPass<LowerAllocations> -X("lowerallocs", "Lower allocations from instructions to calls"); - -// Publically exposed interface to pass... -const PassInfo *const llvm::LowerAllocationsID = &X; -// createLowerAllocationsPass - Interface to this file... -Pass *llvm::createLowerAllocationsPass() { - return new LowerAllocations(); -} - - -// doInitialization - For the lower allocations pass, this ensures that a -// module contains a declaration for a free function. -// -// This function is always successful. -// -bool LowerAllocations::doInitialization(Module &M) { - const Type *BPTy = Type::getInt8PtrTy(M.getContext()); - FreeFunc = M.getOrInsertFunction("free" , Type::getVoidTy(M.getContext()), - BPTy, (Type *)0); - return true; -} - -// runOnBasicBlock - This method does the actual work of converting -// instructions over, assuming that the pass has already been initialized. -// -bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) { - bool Changed = false; - assert(FreeFunc && "Pass not initialized!"); - - BasicBlock::InstListType &BBIL = BB.getInstList(); - - // 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<FreeInst>(I)) { - // Insert a call to the free function... - CallInst::CreateFree(FI->getOperand(0), I); - - // Delete the old free instruction - I = --BBIL.erase(I); - Changed = true; - ++NumLowered; - } - } - - return Changed; -} - diff --git a/lib/Transforms/Utils/LowerInvoke.cpp b/lib/Transforms/Utils/LowerInvoke.cpp index abb7414..6e6e8d2 100644 --- a/lib/Transforms/Utils/LowerInvoke.cpp +++ b/lib/Transforms/Utils/LowerInvoke.cpp @@ -86,7 +86,6 @@ namespace { // This is a cluster of orthogonal Transforms AU.addPreservedID(PromoteMemoryToRegisterID); AU.addPreservedID(LowerSwitchID); - AU.addPreservedID(LowerAllocationsID); } private: diff --git a/lib/Transforms/Utils/LowerSwitch.cpp b/lib/Transforms/Utils/LowerSwitch.cpp index bc1779f..8c18b59 100644 --- a/lib/Transforms/Utils/LowerSwitch.cpp +++ b/lib/Transforms/Utils/LowerSwitch.cpp @@ -43,7 +43,6 @@ namespace { AU.addPreserved<UnifyFunctionExitNodes>(); AU.addPreservedID(PromoteMemoryToRegisterID); AU.addPreservedID(LowerInvokePassID); - AU.addPreservedID(LowerAllocationsID); } struct CaseRange { diff --git a/lib/Transforms/Utils/Mem2Reg.cpp b/lib/Transforms/Utils/Mem2Reg.cpp index baa7d9e..9416604 100644 --- a/lib/Transforms/Utils/Mem2Reg.cpp +++ b/lib/Transforms/Utils/Mem2Reg.cpp @@ -44,7 +44,6 @@ namespace { AU.addPreserved<UnifyFunctionExitNodes>(); AU.addPreservedID(LowerSwitchID); AU.addPreservedID(LowerInvokePassID); - AU.addPreservedID(LowerAllocationsID); } }; } // end of anonymous namespace diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index a28037d..9a49d42 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -1724,7 +1724,8 @@ LLVMValueRef LLVMBuildArrayAlloca(LLVMBuilderRef B, LLVMTypeRef Ty, } LLVMValueRef LLVMBuildFree(LLVMBuilderRef B, LLVMValueRef PointerVal) { - return wrap(unwrap(B)->CreateFree(unwrap(PointerVal))); + return wrap(unwrap(B)->Insert( + CallInst::CreateFree(unwrap(PointerVal), unwrap(B)->GetInsertBlock()))); } diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index 3839dda..391ba7b 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -127,7 +127,6 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case Xor: return "xor"; // Memory instructions... - case Free: return "free"; case Alloca: return "alloca"; case Load: return "load"; case Store: return "store"; @@ -303,16 +302,43 @@ bool Instruction::isUsedOutsideOfBlock(const BasicBlock *BB) const { return false; } +// Code here matches isFreeCall from MallocHelper, which is not in VMCore. +static bool isFreeCall(const Value* I) { + const CallInst *CI = dyn_cast<CallInst>(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; +} + /// mayReadFromMemory - Return true if this instruction may read memory. /// bool Instruction::mayReadFromMemory() const { switch (getOpcode()) { default: return false; - case Instruction::Free: case Instruction::VAArg: case Instruction::Load: return true; case Instruction::Call: + if (isFreeCall(this)) + return true; return !cast<CallInst>(this)->doesNotAccessMemory(); case Instruction::Invoke: return !cast<InvokeInst>(this)->doesNotAccessMemory(); @@ -326,11 +352,12 @@ bool Instruction::mayReadFromMemory() const { bool Instruction::mayWriteToMemory() const { switch (getOpcode()) { default: return false; - case Instruction::Free: case Instruction::Store: case Instruction::VAArg: return true; case Instruction::Call: + if (isFreeCall(this)) + return true; return !cast<CallInst>(this)->onlyReadsMemory(); case Instruction::Invoke: return !cast<InvokeInst>(this)->onlyReadsMemory(); @@ -398,7 +425,19 @@ static bool isMalloc(const Value* I) { if (CI->getOperand(0) != MallocFunc) return false; - return true; + // Check malloc prototype. + // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin + // attribute will exist. + const FunctionType *FTy = cast<Function>(MallocFunc)->getFunctionType(); + if (FTy->getNumParams() != 1) + return false; + if (IntegerType *ITy = dyn_cast<IntegerType>(FTy->param_begin()->get())) { + if (ITy->getBitWidth() != 32 && ITy->getBitWidth() != 64) + return false; + return true; + } + + return false; } bool Instruction::isSafeToSpeculativelyExecute() const { @@ -444,7 +483,6 @@ bool Instruction::isSafeToSpeculativelyExecute() const { case Invoke: case PHI: case Store: - case Free: case Ret: case Br: case Switch: diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index c926547..02d5af0 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -985,28 +985,6 @@ bool AllocaInst::isStaticAlloca() const { } //===----------------------------------------------------------------------===// -// FreeInst Implementation -//===----------------------------------------------------------------------===// - -void FreeInst::AssertOK() { - assert(isa<PointerType>(getOperand(0)->getType()) && - "Can not free something of nonpointer type!"); -} - -FreeInst::FreeInst(Value *Ptr, Instruction *InsertBefore) - : UnaryInstruction(Type::getVoidTy(Ptr->getContext()), - Free, Ptr, InsertBefore) { - AssertOK(); -} - -FreeInst::FreeInst(Value *Ptr, BasicBlock *InsertAtEnd) - : UnaryInstruction(Type::getVoidTy(Ptr->getContext()), - Free, Ptr, InsertAtEnd) { - AssertOK(); -} - - -//===----------------------------------------------------------------------===// // LoadInst Implementation //===----------------------------------------------------------------------===// @@ -3181,16 +3159,6 @@ AllocaInst *AllocaInst::clone() const { return New; } -FreeInst *FreeInst::clone() const { - FreeInst *New = new FreeInst(getOperand(0)); - New->SubclassOptionalData = SubclassOptionalData; - if (hasMetadata()) { - LLVMContext &Context = getContext(); - Context.pImpl->TheMetadata.ValueIsCloned(this, New); - } - return New; -} - LoadInst *LoadInst::clone() const { LoadInst *New = new LoadInst(getOperand(0), Twine(), isVolatile(), |