Auto-upgrade free instructions to calls to the builtin free function.
authorVictor Hernandez <vhernandez@apple.com>
Sat, 24 Oct 2009 04:23:03 +0000 (04:23 +0000)
committerVictor Hernandez <vhernandez@apple.com>
Sat, 24 Oct 2009 04:23:03 +0000 (04:23 +0000)
Update all analysis passes and transforms to treat free calls just like FreeInst.
Remove RaiseAllocations and all its tests since FreeInst no longer needs to be raised.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84987 91177308-0d34-0410-b5e6-96231b3b80d8

30 files changed:
docs/Passes.html
include/llvm-c/Transforms/IPO.h
include/llvm/Analysis/MallocHelper.h
include/llvm/Instructions.h
include/llvm/LinkAllPasses.h
include/llvm/Support/StandardPasses.h
include/llvm/Transforms/IPO.h
lib/Analysis/IPA/Andersens.cpp
lib/Analysis/IPA/GlobalsModRef.cpp
lib/Analysis/MallocHelper.cpp
lib/Analysis/MemoryDependenceAnalysis.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Transforms/IPO/CMakeLists.txt
lib/Transforms/IPO/GlobalOpt.cpp
lib/Transforms/IPO/IPO.cpp
lib/Transforms/IPO/RaiseAllocations.cpp [deleted file]
lib/Transforms/Scalar/DeadStoreElimination.cpp
lib/Transforms/Scalar/InstructionCombining.cpp
lib/Transforms/Scalar/SCCP.cpp
lib/Transforms/Utils/Local.cpp
lib/Transforms/Utils/LowerAllocations.cpp
lib/VMCore/Instructions.cpp
test/Transforms/InstCombine/malloc-free-delete.ll
test/Transforms/RaiseAllocations/2004-11-08-FreeUseCrash.ll [deleted file]
test/Transforms/RaiseAllocations/2007-10-17-InvokeFree.ll [deleted file]
test/Transforms/RaiseAllocations/FreeCastConstantExpr.ll [deleted file]
test/Transforms/RaiseAllocations/dg.exp [deleted file]
utils/findoptdiff

index bb17bee77c3b225cf5e69035fc09270a3d079111..36e0419ad283175f39eeea93761fd9c118cf1a0a 100644 (file)
@@ -158,7 +158,6 @@ perl -e '$/ = undef; for (split(/\n/, <>)) { s:^ *///? ?::; print "  <p>\n" if !
 <tr><td><a href="#memcpyopt">-memcpyopt</a></td><td>Optimize use of memcpy and friends</td></tr>
 <tr><td><a href="#mergereturn">-mergereturn</a></td><td>Unify function exit nodes</td></tr>
 <tr><td><a href="#prune-eh">-prune-eh</a></td><td>Remove unused exception handling info</td></tr>
-<tr><td><a href="#raiseallocs">-raiseallocs</a></td><td>Raise allocations from calls to instructions</td></tr>
 <tr><td><a href="#reassociate">-reassociate</a></td><td>Reassociate expressions</td></tr>
 <tr><td><a href="#reg2mem">-reg2mem</a></td><td>Demote all values to stack slots</td></tr>
 <tr><td><a href="#scalarrepl">-scalarrepl</a></td><td>Scalar Replacement of Aggregates</td></tr>
@@ -1502,17 +1501,6 @@ if (X &lt; 3) {</pre>
   </p>
 </div>
 
-<!-------------------------------------------------------------------------- -->
-<div class="doc_subsection">
-  <a name="raiseallocs">Raise allocations from calls to instructions</a>
-</div>
-<div class="doc_text">
-  <p>
-  Converts <tt>@malloc</tt> and <tt>@free</tt> calls to <tt>malloc</tt> and
-  <tt>free</tt> instructions.
-  </p>
-</div>
-
 <!-------------------------------------------------------------------------- -->
 <div class="doc_subsection">
   <a name="reassociate">Reassociate expressions</a>
index 9bc947f4d8a2d7329ca8d49b7c627ba2a67028bb..0a94315f62b2a3b9bef468a5ebbf3ea94c6249b6 100644 (file)
@@ -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. */
index e0c4d2c9e4ae86b05ad1bd873c35d76b333a844c..be307c02aed5b8b2d525488a226c13c3e89c56ff 100644 (file)
@@ -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
 
index 9a990e7eb96fdaefaf0364a222cc5855be11dd64..f7e7a3dbf99b0ed0790e67aab40bdcb19ad5c739 100644 (file)
@@ -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();
 
index 3342ea89c562dd0ba4e2bd16d2a46b904708ee8d..9335976f33a78b37d49a32485fe6e4e2ef71ac42 100644 (file)
@@ -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();
index c71e6b94fa279644d2c7eba9c7f63795fbbbb658..611e786448246c24a42e01471f3b0e9360e2e940 100644 (file)
@@ -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
index 9189c430cbbb6afcf259e400aa508fc2d1ef2ba1..5e179044229389608976f0381715e774f7afd09b 100644 (file)
@@ -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.
index b5129a7d3ba127704f74be5ee5e5cdd450a10bb1..e37a9dbb7ac80e2a8da4afea82e149a33fe3823a 100644 (file)
@@ -1017,6 +1017,8 @@ 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)) {
+      return false;
     } else if (CallInst *CI = dyn_cast<CallInst>(*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<ICmpInst>(*UI)) {
       if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
         return true;  // Allow comparison against null.
-    } else if (isa<FreeInst>(*UI)) {
-      return false;
     } else {
       return true;
     }
index 7949288340a8f5f0d04eafd489d961dc1455e63a..d83ea48080ce4f5d3d7083af8707bc06c05277b5 100644 (file)
@@ -240,6 +240,8 @@ 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)) {
+      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
       // passing into the function.
@@ -261,8 +263,6 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
     } else if (ICmpInst *ICI = dyn_cast<ICmpInst>(*UI)) {
       if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
         return true;  // Allow comparison against null.
-    } else if (FreeInst *F = dyn_cast<FreeInst>(*UI)) {
-      Writers.push_back(F->getParent()->getParent());
     } else {
       return true;
     }
@@ -439,7 +439,8 @@ 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)) || isa<FreeInst>(*II) ||
+                   isFreeCall(&cast<Instruction>(*II))) {
           FunctionEffect |= ModRef;
         }
 
index e7bb41eeec287c60cb379bf6bba0f01673af0503..511de9d6a518e39494119f534c3a1132387273bf 100644 (file)
@@ -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<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;
+}
index c3aa5bc9306d7623416afbaa5b1d323b81da5393..ce7674003fe013bb2f4b02fe7bd212eb2be53db0 100644 (file)
@@ -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<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
       // Debug intrinsics don't cause dependences.
       if (isa<DbgInfoIntrinsic>(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<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) {
     CallSite QueryCS = CallSite::get(QueryInst);
     bool isReadOnly = AA->onlyReadsMemory(QueryCS);
index 271567bd1e9b57346345d182d12f2e767ed3cd5e..52fd2b21e1a06dad0a0fc3b95022182c6086a38c 100644 (file)
@@ -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<PointerType>(Val->getType()))
     return Error(Loc, "operand to free must be a pointer");
-  Inst = new FreeInst(Val);
+  Inst = CallInst::CreateFree(Val, BB);
   return false;
 }
 
index 5dd6a2e7007ec8ba336dbd0c1370155f91044a73..b6877bc7c11da4316a5894807e22c62649393c9a 100644 (file)
@@ -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);
index 3a385cbe382de9919e03f68eddda62592dc6e790..ffd330c74ec79aba452f203e062dc6d0476997f6 100644 (file)
@@ -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;
     }
index 5c2880155547ccaa342aed25fa06950fcc039908..92bef3bb75e94aa2eed6b678f997ad53ba7f3050 100644 (file)
@@ -19,7 +19,6 @@ add_llvm_library(LLVMipo
   PartialInlining.cpp
   PartialSpecialization.cpp
   PruneEH.cpp
-  RaiseAllocations.cpp
   StripDeadPrototypes.cpp
   StripSymbols.cpp
   StructRetPromotion.cpp
index 9ced2e89a7e624f78aba991c815d8ed794f68333..0bc086f432cd38348adb11fe7e5cb586c737a90e 100644 (file)
@@ -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);
index 43066076ca688bcb2ae2f03b920d6ed9a0e99120..83e8624fe09df2ea624423195160873f928453f6 100644 (file)
@@ -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/lib/Transforms/IPO/RaiseAllocations.cpp b/lib/Transforms/IPO/RaiseAllocations.cpp
deleted file mode 100644 (file)
index deb4405..0000000
+++ /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 <algorithm>
-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<RaiseAllocations>
-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<const Type*>(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<User*> Users(FreeFunc->use_begin(), FreeFunc->use_end());
-    std::vector<Value*> EqPointers;   // Values equal to FreeFunc
-
-    while (!Users.empty()) {
-      User *U = Users.back();
-      Users.pop_back();
-
-      if (Instruction *I = dyn_cast<Instruction>(U)) {
-        if (isa<InvokeInst>(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<PointerType>(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<InvokeInst>(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<GlobalValue>(U)) {
-        Users.insert(Users.end(), GV->use_begin(), GV->use_end());
-        EqPointers.push_back(GV);
-      } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
-        if (CE->isCast()) {
-          Users.insert(Users.end(), CE->use_begin(), CE->use_end());
-          EqPointers.push_back(CE);
-        }
-      }
-    }
-  }
-
-  return Changed;
-}
index a7b3e7524fa2bf1a4c514cdac03910d6a36d82ba..f55d8b2accbb59598b7bd9e25c13724fd4897de2 100644 (file)
@@ -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<StoreInst>(Inst) && !isa<FreeInst>(Inst))
+    if (!isa<StoreInst>(Inst) && !isa<FreeInst>(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<FreeInst>(Inst)) {
-      MadeChange |= handleFreeWithNonTrivialDependency(FI, InstDep);
+    if (isa<FreeInst>(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<AliasAnalysis>();
   
   StoreInst *Dependency = dyn_cast_or_null<StoreInst>(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<FreeInst>(F) ? F->getOperand(0) : F->getOperand(1);
+  if (AA.alias(FreeVal, 1, DepPointer, 1) !=
          AliasAnalysis::MustAlias)
     return false;
   
index 21554c108d688155caa08fafc0f33ff3651e1e4b..be4f775731773d9afd7603795db96acb9a8f4d47 100644 (file)
@@ -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<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);
+
+  // 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<Instruction>(Op));
+      }
+    } else {
+      // Op is a call to malloc
+      if (Op->hasOneUse()) {
+        EraseInstFromFunction(FI);
+        return EraseInstFromFunction(*cast<Instruction>(Op));
+      }
+    }
+  }
+
+  return 0;
+}
 
 /// InstCombineLoadCast - Fold 'load (cast P)' -> cast (load P)' when possible.
 static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI,
index e3dd54e8bcf272788e8fd101c83bfe5b034b6a59..1bb5f4ae7fd13041cd6f8a5189b0bbb6d1916c04 100644 (file)
@@ -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) {
index b62261119c75cd8a4187e471ce3aeb52bcc739c6..940f5a9ec46cb9cb53d5cd87a23bfb755bafae7c 100644 (file)
@@ -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<FreeInst>(BBI) || 
+    if (isa<FreeInst>(BBI) || isFreeCall(BBI) ||
         (isa<CallInst>(BBI) && BBI->mayWriteToMemory() &&
          !isa<DbgInfoIntrinsic>(BBI)))
       return false;
index 9c9113daa93a4a202a7814e957f5be23af35f483..f64a30f5e80afdc3953735761d8ce7408208237a 100644 (file)
@@ -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<FreeInst>(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);
index 99a28594e6ca5e14f0d9241ac704a1f9dcb24fc1..60e203a7e0bcbf924b9a990e2f08c7fb58165388 100644 (file)
@@ -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<PointerType>(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
 //===----------------------------------------------------------------------===//
index fd91e447bddde243db253978a73f8e1a7db8e8b8..a4b7496ef4032c1138f607d5b9f47ec537b7fdb0 100644 (file)
@@ -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*              ; <i8**> [#uses=2]
         %malloc_206 = malloc i8, i32 10         ; <i8*> [#uses=1]
+; CHECK-NOT: malloc
         store i8* %malloc_206, i8** %c_19
         %tmp_207 = load i8** %c_19              ; <i8*> [#uses=1]
         free i8* %tmp_207
+; CHECK-NOT: free
         ret i32 0
+; CHECK: ret i32 0
 }
diff --git a/test/Transforms/RaiseAllocations/2004-11-08-FreeUseCrash.ll b/test/Transforms/RaiseAllocations/2004-11-08-FreeUseCrash.ll
deleted file mode 100644 (file)
index 75e02e8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-; RUN: opt < %s -raiseallocs -disable-output
-
-define void @main() {
-       %tmp.13 = call i32 (...)* @free( i32 32 )               ; <i32> [#uses=1]
-       %tmp.14 = inttoptr i32 %tmp.13 to i32*          ; <i32*> [#uses=0]
-       ret void
-}
-
-declare i32 @free(...)
-
diff --git a/test/Transforms/RaiseAllocations/2007-10-17-InvokeFree.ll b/test/Transforms/RaiseAllocations/2007-10-17-InvokeFree.ll
deleted file mode 100644 (file)
index 675bb3d..0000000
+++ /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/test/Transforms/RaiseAllocations/FreeCastConstantExpr.ll b/test/Transforms/RaiseAllocations/FreeCastConstantExpr.ll
deleted file mode 100644 (file)
index 1cf0729..0000000
+++ /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/test/Transforms/RaiseAllocations/dg.exp b/test/Transforms/RaiseAllocations/dg.exp
deleted file mode 100644 (file)
index f200589..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-load_lib llvm.exp
-
-RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
index 36620d932cb3f5e5db907678dacd7b2ab37313a2..4f8d08dbffe1fedd78f164380d2522a11937e107 100755 (executable)
@@ -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 {