OSDN Git Service

Autoupgrade malloc insts to malloc calls.
authorVictor Hernandez <vhernandez@apple.com>
Sat, 17 Oct 2009 00:00:19 +0000 (00:00 +0000)
committerVictor Hernandez <vhernandez@apple.com>
Sat, 17 Oct 2009 00:00:19 +0000 (00:00 +0000)
Update testcases that rely on malloc insts being present.

Also prematurely remove MallocInst handling from IndMemRemoval and RaiseAllocations to help pass tests in this incremental step.

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

20 files changed:
examples/BrainF/BrainF.cpp
include/llvm/Instructions.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Transforms/IPO/IndMemRemoval.cpp
lib/Transforms/IPO/RaiseAllocations.cpp
lib/Transforms/Scalar/Reassociate.cpp
lib/VMCore/Core.cpp
lib/VMCore/Instructions.cpp
test/Transforms/GlobalOpt/malloc-promote-2.ll
test/Transforms/GlobalOpt/malloc-promote-3.ll
test/Transforms/IndMemRem/2009-01-24-Noalias.ll
test/Transforms/InstCombine/cast-malloc.ll
test/Transforms/InstCombine/cast.ll
test/Transforms/InstCombine/getelementptr.ll
test/Transforms/InstCombine/malloc-free-delete.ll
test/Transforms/InstCombine/malloc2.ll
test/Transforms/InstCombine/malloc3.ll

index 5cf2b88..c64b87f 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "BrainF.h"
 #include "llvm/Constants.h"
+#include "llvm/Instructions.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/ADT/STLExtras.h"
 #include <iostream>
@@ -78,7 +79,11 @@ void BrainF::header(LLVMContext& C) {
 
   //%arr = malloc i8, i32 %d
   ConstantInt *val_mem = ConstantInt::get(C, APInt(32, memtotal));
-  ptr_arr = builder->CreateMalloc(IntegerType::getInt8Ty(C), val_mem, "arr");
+  BasicBlock* BB = builder->GetInsertBlock();
+  const Type* IntPtrTy = IntegerType::getInt32Ty(C);
+  ptr_arr = CallInst::CreateMalloc(BB, IntPtrTy, IntegerType::getInt8Ty(C),
+                                   val_mem, NULL, "arr");
+  BB->getInstList().push_back(cast<Instruction>(ptr_arr));
 
   //call void @llvm.memset.i32(i8 *%arr, i8 0, i32 %d, i32 1)
   {
index b28fcbb..d9e59ed 100644 (file)
@@ -1047,7 +1047,7 @@ public:
                              const Twine &Name = "");
   static Value *CreateMalloc(BasicBlock *InsertAtEnd, const Type *IntPtrTy,
                              const Type *AllocTy, Value *ArraySize = 0,
-                             const Twine &Name = "");
+                             Function* MallocF = 0, const Twine &Name = "");
 
   ~CallInst();
 
@@ -1152,6 +1152,11 @@ public:
   const Value *getCalledValue() const { return Op<0>(); }
         Value *getCalledValue()       { return Op<0>(); }
 
+  /// setCalledFunction - Set the function called
+  void setCalledFunction(Value* Fn) {
+    Op<0>() = Fn;
+  }
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const CallInst *) { return true; }
   static inline bool classof(const Instruction *I) {
index 0e9f1a0..6d66011 100644 (file)
@@ -602,6 +602,9 @@ lltok::Kind LLLexer::LexIdentifier() {
     // Scan CurPtr ahead, seeing if there is just whitespace before the newline.
     if (JustWhitespaceNewLine(CurPtr))
       return lltok::kw_zeroext;
+  } else if (Len == 6 && !memcmp(StartChar, "malloc", 6)) {
+    // Autoupgrade malloc instruction
+    return lltok::kw_malloc;
   }
 
   // Keywords for instructions.
@@ -641,7 +644,6 @@ lltok::Kind LLLexer::LexIdentifier() {
   INSTKEYWORD(unwind,      Unwind);
   INSTKEYWORD(unreachable, Unreachable);
 
-  INSTKEYWORD(malloc,      Malloc);
   INSTKEYWORD(alloca,      Alloca);
   INSTKEYWORD(free,        Free);
   INSTKEYWORD(load,        Load);
index 1e1ddf0..001d56d 100644 (file)
@@ -69,6 +69,27 @@ bool LLParser::Run() {
 /// ValidateEndOfModule - Do final validity and sanity checks at the end of the
 /// module.
 bool LLParser::ValidateEndOfModule() {
+  // Update auto-upgraded malloc calls from "autoupgrade_malloc" to "malloc".
+  if (MallocF) {
+    MallocF->setName("malloc");
+    // If setName() does not set the name to "malloc", then there is already a 
+    // declaration of "malloc".  In that case, iterate over all calls to MallocF
+    // and get them to call the declared "malloc" instead.
+    if (MallocF->getName() != "malloc") {
+      Function* realMallocF = M->getFunction("malloc");
+      for (User::use_iterator UI = MallocF->use_begin(), UE= MallocF->use_end();
+           UI != UE; ) {
+        User* user = *UI;
+        UI++;
+        if (CallInst *Call = dyn_cast<CallInst>(user))
+          Call->setCalledFunction(realMallocF);
+      }
+      if (!realMallocF->doesNotAlias(0)) realMallocF->setDoesNotAlias(0);
+      MallocF->eraseFromParent();
+      MallocF = NULL;
+    }
+  }
+
   if (!ForwardRefTypes.empty())
     return Error(ForwardRefTypes.begin()->second.second,
                  "use of undefined type named '" +
@@ -2783,8 +2804,8 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
   case lltok::kw_call:           return ParseCall(Inst, PFS, false);
   case lltok::kw_tail:           return ParseCall(Inst, PFS, true);
   // Memory.
-  case lltok::kw_alloca:
-  case lltok::kw_malloc:         return ParseAlloc(Inst, PFS, KeywordVal);
+  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_load:           return ParseLoad(Inst, PFS, false);
   case lltok::kw_store:          return ParseStore(Inst, PFS, false);
@@ -3445,7 +3466,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
 ///   ::= 'malloc' Type (',' TypeAndValue)? (',' OptionalInfo)?
 ///   ::= 'alloca' Type (',' TypeAndValue)? (',' OptionalInfo)?
 bool LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS,
-                          unsigned Opc) {
+                          BasicBlock* BB, bool isAlloca) {
   PATypeHolder Ty(Type::getVoidTy(Context));
   Value *Size = 0;
   LocTy SizeLoc;
@@ -3466,10 +3487,21 @@ bool LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS,
   if (Size && Size->getType() != Type::getInt32Ty(Context))
     return Error(SizeLoc, "element count must be i32");
 
-  if (Opc == Instruction::Malloc)
-    Inst = new MallocInst(Ty, Size, Alignment);
-  else
+  if (isAlloca)
     Inst = new AllocaInst(Ty, Size, Alignment);
+  else {
+    // Autoupgrade old malloc instruction to malloc call.
+    const Type* IntPtrTy = Type::getInt32Ty(Context);
+    const Type* Int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(Context));
+    if (!MallocF)
+      // Prototype malloc as "void *autoupgrade_malloc(int32)".
+      MallocF = cast<Function>(M->getOrInsertFunction("autoupgrade_malloc",
+                               Int8PtrTy, IntPtrTy, NULL));
+      // "autoupgrade_malloc" updated to "malloc" in ValidateEndOfModule().
+
+    Inst = cast<Instruction>(CallInst::CreateMalloc(BB, IntPtrTy, Ty,
+                                                    Size, MallocF));
+  }
   return false;
 }
 
index 97bf2f3..5dd6a2e 100644 (file)
@@ -75,9 +75,11 @@ namespace llvm {
     std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
     std::map<unsigned, std::pair<GlobalValue*, LocTy> > ForwardRefValIDs;
     std::vector<GlobalValue*> NumberedVals;
+    Function* MallocF;
   public:
     LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) : 
-      Context(m->getContext()), Lex(F, SM, Err, m->getContext()), M(m) {}
+      Context(m->getContext()), Lex(F, SM, Err, m->getContext()),
+      M(m), MallocF(NULL) {}
     bool Run();
 
     LLVMContext& getContext() { return Context; }
@@ -276,7 +278,8 @@ namespace llvm {
     bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS);
     bool ParsePHI(Instruction *&I, PerFunctionState &PFS);
     bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail);
-    bool ParseAlloc(Instruction *&I, PerFunctionState &PFS, unsigned Opc);
+    bool ParseAlloc(Instruction *&I, PerFunctionState &PFS,
+                    BasicBlock *BB = 0, bool isAlloca = true);
     bool ParseFree(Instruction *&I, PerFunctionState &PFS);
     bool ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
     bool ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
index 4eb12c6..fe4556f 100644 (file)
@@ -2044,14 +2044,21 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
     }
 
     case bitc::FUNC_CODE_INST_MALLOC: { // MALLOC: [instty, op, align]
+      // Autoupgrade malloc instruction to malloc call.
       if (Record.size() < 3)
         return Error("Invalid MALLOC record");
       const PointerType *Ty =
         dyn_cast_or_null<PointerType>(getTypeByID(Record[0]));
       Value *Size = getFnValueByID(Record[1], Type::getInt32Ty(Context));
-      unsigned Align = Record[2];
       if (!Ty || !Size) return Error("Invalid MALLOC record");
-      I = new MallocInst(Ty->getElementType(), Size, (1 << Align) >> 1);
+      if (!CurBB) return Error("Invalid malloc instruction with no BB");
+      const Type* Int32Ty = IntegerType::getInt32Ty(CurBB->getContext());
+      if (Size->getType() != Int32Ty)
+        Size = CastInst::CreateIntegerCast(Size, Int32Ty, false /*ZExt*/,
+                                           "", CurBB);
+      Value* Malloc = CallInst::CreateMalloc(CurBB, Int32Ty,
+                                             Ty->getElementType(), Size, NULL);
+      I = cast<Instruction>(Malloc);
       InstructionList.push_back(I);
       break;
     }
index e7884ec..9bd5a92 100644 (file)
@@ -24,6 +24,7 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Target/TargetData.h"
 using namespace llvm;
 
 STATISTIC(NumBounceSites, "Number of sites modified");
@@ -66,20 +67,28 @@ bool IndMemRemPass::runOnModule(Module &M) {
   }
   if (Function* F = M.getFunction("malloc")) {
     if (F->isDeclaration() && F->arg_size() == 1 && !F->use_empty()) {
-      Function* FN = Function::Create(F->getFunctionType(), 
-                                      GlobalValue::LinkOnceAnyLinkage,
-                                      "malloc_llvm_bounce", &M);
-      FN->setDoesNotAlias(0);
-      BasicBlock* bb = BasicBlock::Create(M.getContext(), "entry",FN);
-      Instruction* c = CastInst::CreateIntegerCast(
-          FN->arg_begin(), Type::getInt32Ty(M.getContext()), false, "c", bb);
-      Instruction* a = new MallocInst(Type::getInt8Ty(M.getContext()),
-                                      c, "m", bb);
-      ReturnInst::Create(M.getContext(), a, bb);
-      ++NumBounce;
-      NumBounceSites += F->getNumUses();
-      F->replaceAllUsesWith(FN);
-      changed = true;
+      TargetData* TD = getAnalysisIfAvailable<TargetData>();
+      if (TD) { 
+        Function* FN = Function::Create(F->getFunctionType(), 
+                                        GlobalValue::LinkOnceAnyLinkage,
+                                        "malloc_llvm_bounce", &M);
+        F->replaceAllUsesWith(FN);
+        FN->setDoesNotAlias(0);
+        BasicBlock* bb = BasicBlock::Create(M.getContext(), "entry", FN);
+        const Type* IntPtrTy = TD->getIntPtrType(M.getContext());
+        Value* c = FN->arg_begin();
+        if (FN->arg_begin()->getType() != IntPtrTy)
+          c = CastInst::CreateIntegerCast(FN->arg_begin(), IntPtrTy, false,
+                                          "c", bb);
+        Value* a = CallInst::CreateMalloc(bb, IntPtrTy,
+                                          Type::getInt8Ty(M.getContext()),
+                                          c, NULL, "m");
+        bb->getInstList().push_back(cast<Instruction>(a));
+        ReturnInst::Create(M.getContext(), a, bb);
+        ++NumBounce;
+        NumBounceSites += F->getNumUses();
+        changed = true;
+      }
     }
   }
   return changed;
index 4c1f26d..deb4405 100644 (file)
@@ -1,4 +1,4 @@
-//===- RaiseAllocations.cpp - Convert @malloc & @free calls to insts ------===//
+//===- RaiseAllocations.cpp - Convert @free calls to insts ------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file defines the RaiseAllocations pass which convert malloc and free
-// calls to malloc and free instructions.
+// This file defines the RaiseAllocations pass which convert free calls to free
+// instructions.
 //
 //===----------------------------------------------------------------------===//
 
@@ -29,19 +29,19 @@ using namespace llvm;
 STATISTIC(NumRaised, "Number of allocations raised");
 
 namespace {
-  // RaiseAllocations - Turn @malloc and @free calls into the appropriate
+  // RaiseAllocations - Turn @free calls into the appropriate
   // instruction.
   //
   class VISIBILITY_HIDDEN RaiseAllocations : public ModulePass {
-    Function *MallocFunc;   // Functions in the module we are processing
-    Function *FreeFunc;     // Initialized by doPassInitializationVirt
+    Function *FreeFunc;   // Functions in the module we are processing
+                          // Initialized by doPassInitializationVirt
   public:
     static char ID; // Pass identification, replacement for typeid
     RaiseAllocations() 
-      : ModulePass(&ID), MallocFunc(0), FreeFunc(0) {}
+      : ModulePass(&ID), FreeFunc(0) {}
 
     // doPassInitialization - For the raise allocations pass, this finds a
-    // declaration for malloc and free if they exist.
+    // declaration for free if it exists.
     //
     void doInitialization(Module &M);
 
@@ -61,50 +61,16 @@ ModulePass *llvm::createRaiseAllocationsPass() {
 }
 
 
-// If the module has a symbol table, they might be referring to the malloc and
-// free functions.  If this is the case, grab the method pointers that the
-// module is using.
+// 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 @malloc and @free in the symbol table, for later use.  If they don't
+// 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 Malloc and free prototypes if they exist!
-  MallocFunc = M.getFunction("malloc");
-  if (MallocFunc) {
-    const FunctionType* TyWeHave = MallocFunc->getFunctionType();
-
-    // Get the expected prototype for malloc
-    const FunctionType *Malloc1Type = 
-      FunctionType::get(Type::getInt8PtrTy(M.getContext()),
-                      std::vector<const Type*>(1,
-                                      Type::getInt64Ty(M.getContext())), false);
-
-    // Chck to see if we got the expected malloc
-    if (TyWeHave != Malloc1Type) {
-      // Check to see if the prototype is wrong, giving us i8*(i32) * malloc
-      // This handles the common declaration of: 'void *malloc(unsigned);'
-      const FunctionType *Malloc2Type = 
-        FunctionType::get(PointerType::getUnqual(
-                          Type::getInt8Ty(M.getContext())),
-                          std::vector<const Type*>(1, 
-                                      Type::getInt32Ty(M.getContext())), false);
-      if (TyWeHave != Malloc2Type) {
-        // Check to see if the prototype is missing, giving us 
-        // i8*(...) * malloc
-        // This handles the common declaration of: 'void *malloc();'
-        const FunctionType *Malloc3Type = 
-          FunctionType::get(PointerType::getUnqual(
-                                    Type::getInt8Ty(M.getContext())), 
-                                    true);
-        if (TyWeHave != Malloc3Type)
-          // Give up
-          MallocFunc = 0;
-      }
-    }
-  }
-
+  // Get free prototype if it exists!
   FreeFunc = M.getFunction("free");
   if (FreeFunc) {
     const FunctionType* TyWeHave = FreeFunc->getFunctionType();
@@ -138,72 +104,18 @@ void RaiseAllocations::doInitialization(Module &M) {
   }
 
   // Don't mess with locally defined versions of these functions...
-  if (MallocFunc && !MallocFunc->isDeclaration()) MallocFunc = 0;
   if (FreeFunc && !FreeFunc->isDeclaration())     FreeFunc = 0;
 }
 
 // run - Transform calls into instructions...
 //
 bool RaiseAllocations::runOnModule(Module &M) {
-  // Find the malloc/free prototypes...
+  // Find the free prototype...
   doInitialization(M);
   
   bool Changed = false;
 
-  // First, process all of the malloc calls...
-  if (MallocFunc) {
-    std::vector<User*> Users(MallocFunc->use_begin(), MallocFunc->use_end());
-    std::vector<Value*> EqPointers;   // Values equal to MallocFunc
-    while (!Users.empty()) {
-      User *U = Users.back();
-      Users.pop_back();
-
-      if (Instruction *I = dyn_cast<Instruction>(U)) {
-        CallSite CS = CallSite::get(I);
-        if (CS.getInstruction() && !CS.arg_empty() &&
-            (CS.getCalledFunction() == MallocFunc ||
-             std::find(EqPointers.begin(), EqPointers.end(),
-                       CS.getCalledValue()) != EqPointers.end())) {
-
-          Value *Source = *CS.arg_begin();
-
-          // If no prototype was provided for malloc, we may need to cast the
-          // source size.
-          if (Source->getType() != Type::getInt32Ty(M.getContext()))
-            Source = 
-              CastInst::CreateIntegerCast(Source, 
-                                          Type::getInt32Ty(M.getContext()), 
-                                          false/*ZExt*/,
-                                          "MallocAmtCast", I);
-
-          MallocInst *MI = new MallocInst(Type::getInt8Ty(M.getContext()),
-                                          Source, "", I);
-          MI->takeName(I);
-          I->replaceAllUsesWith(MI);
-
-          // 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
-          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);
-        }
-      }
-    }
-  }
-
-  // Next, process all free calls...
+  // Process all free calls...
   if (FreeFunc) {
     std::vector<User*> Users(FreeFunc->use_begin(), FreeFunc->use_end());
     std::vector<Value*> EqPointers;   // Values equal to FreeFunc
index e6ffac2..9160654 100644 (file)
@@ -29,6 +29,7 @@
 #include "llvm/IntrinsicInst.h"
 #include "llvm/LLVMContext.h"
 #include "llvm/Pass.h"
+#include "llvm/Analysis/MallocHelper.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/Support/CFG.h"
 #include "llvm/Support/Debug.h"
@@ -121,7 +122,7 @@ static bool isUnmovableInstruction(Instruction *I) {
   if (I->getOpcode() == Instruction::PHI ||
       I->getOpcode() == Instruction::Alloca ||
       I->getOpcode() == Instruction::Load ||
-      I->getOpcode() == Instruction::Malloc ||
+      I->getOpcode() == Instruction::Malloc || isMalloc(I) ||
       I->getOpcode() == Instruction::Invoke ||
       (I->getOpcode() == Instruction::Call &&
        !isa<DbgInfoIntrinsic>(I)) ||
index bff3087..5b8295f 100644 (file)
@@ -1699,12 +1699,16 @@ LLVMValueRef LLVMBuildNot(LLVMBuilderRef B, LLVMValueRef V, const char *Name) {
 
 LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef B, LLVMTypeRef Ty,
                              const char *Name) {
-  return wrap(unwrap(B)->CreateMalloc(unwrap(Ty), 0, Name));
+  const Type* IntPtrT = Type::getInt32Ty(unwrap(B)->GetInsertBlock()->getContext());
+  return wrap(CallInst::CreateMalloc(unwrap(B)->GetInsertBlock(), IntPtrT,
+                                     unwrap(Ty), 0, 0, Twine(Name)));
 }
 
 LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef B, LLVMTypeRef Ty,
                                   LLVMValueRef Val, const char *Name) {
-  return wrap(unwrap(B)->CreateMalloc(unwrap(Ty), unwrap(Val), Name));
+  const Type* IntPtrT = Type::getInt32Ty(unwrap(B)->GetInsertBlock()->getContext());
+  return wrap(CallInst::CreateMalloc(unwrap(B)->GetInsertBlock(), IntPtrT,
+                                     unwrap(Ty), unwrap(Val), 0, Twine(Name)));
 }
 
 LLVMValueRef LLVMBuildAlloca(LLVMBuilderRef B, LLVMTypeRef Ty,
index f3d15cb..4ff253a 100644 (file)
@@ -462,7 +462,8 @@ static Value *checkArraySize(Value *Amt, const Type *IntPtrTy) {
 
 static Value *createMalloc(Instruction *InsertBefore, BasicBlock *InsertAtEnd,
                            const Type *IntPtrTy, const Type *AllocTy,
-                           Value *ArraySize, const Twine &NameStr) {
+                           Value *ArraySize, Function* MallocF, 
+                           const Twine &NameStr) {
   assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) &&
          "createMalloc needs either InsertBefore or InsertAtEnd");
 
@@ -499,27 +500,34 @@ static Value *createMalloc(Instruction *InsertBefore, BasicBlock *InsertAtEnd,
   BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
   Module* M = BB->getParent()->getParent();
   const Type *BPTy = Type::getInt8PtrTy(BB->getContext());
-  // prototype malloc as "void *malloc(size_t)"
-  Constant *MallocF = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, NULL);
-  if (!cast<Function>(MallocF)->doesNotAlias(0))
-    cast<Function>(MallocF)->setDoesNotAlias(0);
+  if (!MallocF)
+    // prototype malloc as "void *malloc(size_t)"
+    MallocF = cast<Function>(M->getOrInsertFunction("malloc", BPTy,
+                                                    IntPtrTy, NULL));
+  if (!MallocF->doesNotAlias(0)) MallocF->setDoesNotAlias(0);
   const PointerType *AllocPtrType = PointerType::getUnqual(AllocTy);
   CallInst *MCall = NULL;
-  Value    *MCast = NULL;
+  Value    *Result = NULL;
   if (InsertBefore) {
     MCall = CallInst::Create(MallocF, AllocSize, "malloccall", InsertBefore);
-    // Create a cast instruction to convert to the right type...
-    MCast = new BitCastInst(MCall, AllocPtrType, NameStr, InsertBefore);
+    Result = MCall;
+    if (Result->getType() != AllocPtrType)
+      // Create a cast instruction to convert to the right type...
+      Result = new BitCastInst(MCall, AllocPtrType, NameStr, InsertBefore);
   } else {
-    MCall = CallInst::Create(MallocF, AllocSize, "malloccall", InsertAtEnd);
-    // Create a cast instruction to convert to the right type...
-    MCast = new BitCastInst(MCall, AllocPtrType, NameStr);
+    MCall = CallInst::Create(MallocF, AllocSize, "malloccall");
+    Result = MCall;
+    if (Result->getType() != AllocPtrType) {
+      InsertAtEnd->getInstList().push_back(MCall);
+      // Create a cast instruction to convert to the right type...
+      Result = new BitCastInst(MCall, AllocPtrType, NameStr);
+    }
   }
   MCall->setTailCall();
   assert(MCall->getType() != Type::getVoidTy(BB->getContext()) &&
          "Malloc has void return type");
 
-  return MCast;
+  return Result;
 }
 
 /// CreateMalloc - Generate the IR for a call to malloc:
@@ -531,7 +539,8 @@ static Value *createMalloc(Instruction *InsertBefore, BasicBlock *InsertAtEnd,
 Value *CallInst::CreateMalloc(Instruction *InsertBefore, const Type *IntPtrTy,
                               const Type *AllocTy, Value *ArraySize,
                               const Twine &Name) {
-  return createMalloc(InsertBefore, NULL, IntPtrTy, AllocTy, ArraySize, Name);
+  return createMalloc(InsertBefore, NULL, IntPtrTy, AllocTy, 
+                      ArraySize, NULL, Name);
 }
 
 /// CreateMalloc - Generate the IR for a call to malloc:
@@ -544,8 +553,9 @@ Value *CallInst::CreateMalloc(Instruction *InsertBefore, const Type *IntPtrTy,
 /// responsibility of the caller.
 Value *CallInst::CreateMalloc(BasicBlock *InsertAtEnd, const Type *IntPtrTy,
                               const Type *AllocTy, Value *ArraySize, 
-                              const Twine &Name) {
-  return createMalloc(NULL, InsertAtEnd, IntPtrTy, AllocTy, ArraySize, Name);
+                              Function* MallocF, const Twine &Name) {
+  return createMalloc(NULL, InsertAtEnd, IntPtrTy, AllocTy,
+                      ArraySize, MallocF, Name);
 }
 
 //===----------------------------------------------------------------------===//
index 0d03835..d3d2252 100644 (file)
@@ -1,4 +1,6 @@
-; RUN: opt < %s -globalopt -S | not grep malloc
+; RUN: opt < %s -globalopt -globaldce -S | not grep malloc
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i686-apple-darwin8"
 
 @G = internal global i32* null          ; <i32**> [#uses=3]
 
index d4ee4e8..a920b61 100644 (file)
@@ -1,4 +1,6 @@
-; RUN: opt < %s -globalopt -S | not grep malloc
+; RUN: opt < %s -globalopt -globaldce -S | not grep malloc
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i686-apple-darwin8"
 
 @G = internal global i32* null          ; <i32**> [#uses=4]
 
index b6d9803..043291e 100644 (file)
@@ -1,4 +1,6 @@
 ; RUN: opt < %s -indmemrem -S | grep bounce | grep noalias
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i686-apple-darwin8"
 
 declare i8* @malloc(i32)
 
index 3754032..43a1489 100644 (file)
@@ -1,6 +1,6 @@
 ; test that casted mallocs get converted to malloc of the right type
 ; RUN: opt < %s -instcombine -S | \
-; RUN:    not grep bitcast
+; RUN:    grep bitcast | count 1
 
 ; The target datalayout is important for this test case. We have to tell 
 ; instcombine that the ABI alignment for a long is 4-bytes, not 8, otherwise
index 9835d65..c5266f3 100644 (file)
@@ -102,8 +102,8 @@ define i32* @test12() {
         %p = malloc [4 x i8]            ; <[4 x i8]*> [#uses=1]
         %c = bitcast [4 x i8]* %p to i32*               ; <i32*> [#uses=1]
         ret i32* %c
-; CHECK: %p = malloc i32
-; CHECK: ret i32* %p
+; CHECK: %malloccall = tail call i8* @malloc(i32 ptrtoint ([4 x i8]* getelementptr ([4 x i8]* null, i32 1) to i32))
+; CHECK: ret i32* %c
 }
 
 define i8* @test13(i64 %A) {
@@ -274,9 +274,9 @@ define void @test32(double** %tmp) {
         %tmp8.upgrd.1 = bitcast [16 x i8]* %tmp8 to double*             ; <double*> [#uses=1]
         store double* %tmp8.upgrd.1, double** %tmp
         ret void
-; CHECK: %tmp81 = malloc [2 x double]
-; CHECK: %tmp81.sub = getelementptr inbounds [2 x double]* %tmp81, i64 0, i64 0
-; CHECK: store double* %tmp81.sub, double** %tmp
+; CHECK: %malloccall = tail call i8* @malloc(i32 ptrtoint ([16 x i8]* getelementptr ([16 x i8]* null, i32 1) to i32))
+; CHECK: %tmp8.upgrd.1 = bitcast i8* %malloccall to double*
+; CHECK: store double* %tmp8.upgrd.1, double** %tmp
 ; CHECK: ret void
 }
 
index ffaa6af..285e0ba 100644 (file)
@@ -58,7 +58,7 @@ define i32* @test6() {
         %B = getelementptr i32* %A, i64 2             
         ret i32* %B
 ; CHECK: @test6
-; CHECK: getelementptr [4 x i32]* %M, i64 0, i64 2
+; CHECK: getelementptr i8* %malloccall, i64 8
 }
 
 define i32* @test7(i32* %I, i64 %C, i64 %D) {
index 2ed5ec6..fd91e44 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: opt < %s -instcombine -S | grep {ret i32 0}
-; RUN: opt < %s -instcombine -S | not grep malloc
+; RUN: opt < %s -instcombine -globaldce -S | not grep malloc
 ; PR1201
 define i32 @main(i32 %argc, i8** %argv) {
         %c_19 = alloca i8*              ; <i8**> [#uses=2]
index 102422e..cc1506b 100644 (file)
@@ -1,5 +1,4 @@
 ; RUN: opt < %s -instcombine -S | grep {ret i32 0}
-; RUN: opt < %s -instcombine -S | not grep malloc
 ; PR1313
 
 define i32 @test1(i32 %argc, i8* %argv, i8* %envp) {
index cd407ff..f1c0cae 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt < %s -instcombine -S | grep {malloc.*struct.foo} | count 2
+; RUN: opt < %s -instcombine -S | not grep load
 ; PR1728
 
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"