Index: llvm/lib/Analysis/MemoryBuiltins.cpp =================================================================== --- llvm/lib/Analysis/MemoryBuiltins.cpp +++ llvm/lib/Analysis/MemoryBuiltins.cpp @@ -370,7 +370,8 @@ } /// getMallocType - Returns the PointerType resulting from the malloc call. -/// The PointerType depends on the number of bitcast uses of the malloc call: +/// The PointerType depends on the number of unique bitcast uses of the malloc +/// call: /// 0: PointerType is the calls' return type. /// 1: PointerType is the bitcast's result type. /// >1: Unique PointerType cannot be determined, return NULL. @@ -379,25 +380,37 @@ assert(isMallocLikeFn(CI, TLI) && "getMallocType and not malloc call"); PointerType *MallocType = nullptr; - unsigned NumOfBitCastUses = 0; // Determine if CallInst has a bitcast use. - for (const User *U : CI->users()) + // Check both the call and its stored-to. + for (const User *U : CI->users()) { if (const BitCastInst *BCI = dyn_cast(U)) { - MallocType = cast(BCI->getDestTy()); - NumOfBitCastUses++; + auto *PTy = cast(BCI->getDestTy()); + if (!MallocType) + MallocType = PTy; + else if (MallocType != PTy) // Type could not be determined. + return nullptr; } + if (auto *ST = dyn_cast(U)) + if (ST->getValueOperand() == CI) + if (auto *BCO = dyn_cast(ST->getPointerOperand())) + if (auto *PTy = dyn_cast( + cast(BCO->getOperand(0)->getType()) + ->getElementType())) { + if (!MallocType) + MallocType = PTy; + else if (MallocType != PTy) // Type could not be determined. + return nullptr; + } + } + // Malloc call has 1 bitcast use, so type is the bitcast's destination type. - if (NumOfBitCastUses == 1) + if (MallocType) return MallocType; // Malloc call was not bitcast, so type is the malloc function's return type. - if (NumOfBitCastUses == 0) - return cast(CI->getType()); - - // Type could not be determined. - return nullptr; + return cast(CI->getType()); } /// getMallocAllocatedType - Returns the Type allocated by malloc call. Index: llvm/test/Transforms/GlobalOpt/malloc-promote-5.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/GlobalOpt/malloc-promote-5.ll @@ -0,0 +1,38 @@ +; RUN: opt -globalopt -S < %s | FileCheck %s +; RUN: opt -passes=globalopt -S < %s | FileCheck %s + +@g = internal global i32* null, align 8 +; CHECK: [[G_BODY:@.*]] = internal unnamed_addr global i32 undef + +define signext i32 @f() { +; CHECK-LABEL: @f( +; CHECK-NEXT: entry: +; CHECK-NEXT: store i32 1, i32* [[G_BODY]], align 4 +; CHECK-NEXT: store i8 2, i8* bitcast (i32* [[G_BODY]] to i8*), align 4 +; CHECK-NEXT: ret i32 1 +; +entry: + %call = call i8* @malloc(i64 4) + store i8* %call, i8** bitcast (i32** @g to i8**), align 8 + %0 = load i32*, i32** @g, align 8 + store i32 1, i32* %0, align 4 + %1 = load i8*, i8** bitcast (i32** @g to i8**), align 8 + store i8 2, i8* %1, align 4 + ret i32 1 +} + +define signext i32 @main() { +; CHECK-LABEL: @main( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = call signext i32 @f() +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[G_BODY]], align 4 +; CHECK-NEXT: ret i32 [[TMP0]] +; +entry: + %call = call signext i32 @f() + %0 = load i32*, i32** @g, align 8 + %1 = load i32, i32* %0, align 4 + ret i32 %1 +} + +declare noalias align 16 i8* @malloc(i64)