Auto-upgrade malloc instructions to malloc calls.
authorVictor Hernandez <vhernandez@apple.com>
Thu, 24 Sep 2009 17:47:49 +0000 (17:47 +0000)
committerVictor Hernandez <vhernandez@apple.com>
Thu, 24 Sep 2009 17:47:49 +0000 (17:47 +0000)
Reviewed by Devang Patel.

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

16 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/VMCore/Core.cpp
lib/VMCore/Instructions.cpp
test/Analysis/PointerTracking/sizes.ll
test/Transforms/GlobalOpt/malloc-promote-2.ll
test/Transforms/GlobalOpt/malloc-promote-3.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

index 5cf2b883bc480783889ad47e75346391aae7a2cc..c64b87f2f39c25ef24798af894c8bf06b93d9813 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 fbee2af81cf0c78442b22f768771dd265208b3be..f2832c8c2595fabaa24270449adbb068288e4061 100644 (file)
@@ -1044,7 +1044,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();
 
@@ -1149,6 +1149,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 315048c748a8edd8f8c22bc0cbe6614f04f37c84..05b6f7f166ee64b0efc44ad4b6dc2e31852be525 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 0ecf8473c1b41b54633b1f4f5bd5cb5560e95584..d90588dd5fee5f49d39f24406de8d3a83e94402a 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 '" +
@@ -2776,8 +2797,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);
@@ -3286,7 +3307,7 @@ bool LLParser::ParseShuffleVector(Instruction *&Inst, PerFunctionState &PFS) {
 }
 
 /// ParsePHI
-///   ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Valueß ']')*
+///   ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Value√ü ']')*
 bool LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) {
   PATypeHolder Ty(Type::getVoidTy(Context));
   Value *Op0, *Op1;
@@ -3431,7 +3452,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;
@@ -3451,10 +3472,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 3420fcf45539e62cd00d31dabfa1048e3c3b0081..43e9bd81f59b1a760c42b208abfbbb732f52873e 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 f3ab806271a3068dbf2015e1651613fafbe5a25e..be0ec4bd85b8b9d4c6e5da82230fa5ba4420e686 100644 (file)
@@ -2046,14 +2046,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 1dbf5c44efcfdd37839892559855fe8621bb1dac..248127df728e75ccfe11a2eda55a8fb6fde9b480 100644 (file)
@@ -1636,12 +1636,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 b7acce71e3a78bd0ef02d8cba7111ad98edf63f3..611bf160d0839fd74f3bad4c245f07c3715110d8 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,10 +500,11 @@ static Value *createMalloc(Instruction *InsertBefore, BasicBlock *InsertAtEnd,
   BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
   Module* M = BB->getParent()->getParent();
   const Type *BPTy = PointerType::getUnqual(Type::getInt8Ty(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;
@@ -531,7 +533,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 +547,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 c0b0606af0b5258ed0ffd04f5f631598e6de368d..c6224e08559b919cdb808480a2d7c473a6ded794 100644 (file)
@@ -63,7 +63,7 @@ entry:
 define i32 @foo2(i32 %n) nounwind {
 entry:
        %call = malloc i8, i32 %n               ; <i8*> [#uses=1]
-; CHECK: %call =
+; CHECK: %malloccall =
 ; CHECK: ==> %n elements, %n bytes allocated
        %call2 = tail call i8* @calloc(i64 2, i64 4) nounwind           ; <i8*> [#uses=1]
 ; CHECK: %call2 =
index 0d03835cf5309df522cbe5359758fbaee1997ac8..d3d225260ab3499a34f7574f67063d1b1f63cbb0 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 d4ee4e861c2d77df2275d54f67fe61343c8db30e..a920b611501c080b19eaaeed359f78d8bdd17c41 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 3754032cc2f791d31031b5d758e385f81b1fceb1..43a14892770996eeed4b37a698119888a92395a0 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 59d7cd051d3810793a528957bed92ec525809cca..27222673f78939a6ec8de4230384b4be9aee41d9 100644 (file)
@@ -79,9 +79,9 @@ define void @test11(i32* %P) {
 }
 
 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
+        %c = malloc [4 x i8]            ; <[4 x i8]*> [#uses=1]
+        %p = bitcast [4 x i8]* %c to i32*               ; <i32*> [#uses=1]
+        ret i32* %p
 }
 define i8* @test13(i64 %A) {
         %c = getelementptr [0 x i8]* bitcast ([32832 x i8]* @inbuf to [0 x i8]*), i64 0, i64 %A             ; <i8*> [#uses=1]
index ffaa6afa85e355a718ca54824e6a79e56ed655ea..285e0ba602f42adaf1886a84c3f78cfe37067d16 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 2ed5ec6996d61c00d696086072da0726a5ea40cb..fd91e447bddde243db253978a73f8e1a7db8e8b8 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 102422ee5fc7d3dae5b0af33657ea74077545d20..cc1506b6b19a3cd65771d8e8cbbdb4ad0ab964cd 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) {