Index: llvm/lib/Analysis/Loads.cpp =================================================================== --- llvm/lib/Analysis/Loads.cpp +++ llvm/lib/Analysis/Loads.cpp @@ -162,8 +162,7 @@ Opts.RoundToAlign = false; Opts.NullIsUnknownSize = true; uint64_t ObjSize; - // TODO: Plumb through TLI so that malloc routines and such work. - if (getObjectSize(V, ObjSize, DL, nullptr, Opts)) { + if (getObjectSize(V, ObjSize, DL, TLI, Opts)) { APInt KnownDerefBytes(Size.getBitWidth(), ObjSize); if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) && isKnownNonZero(V, DL, 0, nullptr, CtxI, DT) && !V->canBeFreed()) { Index: llvm/test/Transforms/LICM/hoist-alloc.ll =================================================================== --- llvm/test/Transforms/LICM/hoist-alloc.ll +++ llvm/test/Transforms/LICM/hoist-alloc.ll @@ -130,7 +130,8 @@ ret i8 %res } -; TODO: We can hoist the load in this case. +; TODO: We can hoist the load in this case, but only once we have +; some form of context sensitive free analysis. define i8 @test_hoist_malloc() { ; CHECK-LABEL: @test_hoist_malloc( ; CHECK-NEXT: entry: @@ -171,18 +172,17 @@ ret i8 %res } -; TODO: We can hoist the load in this case. -define i8 @test_hoist_malloc_leak() { +define i8 @test_hoist_malloc_leak() nofree nosync { ; CHECK-LABEL: @test_hoist_malloc_leak( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A_RAW:%.*]] = call nonnull i8* @malloc(i64 32) ; CHECK-NEXT: call void @init(i8* [[A_RAW]]) ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i8, i8* [[A_RAW]], i32 31 +; CHECK-NEXT: [[RES:%.*]] = load i8, i8* [[ADDR]], align 1 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: call void @unknown() -; CHECK-NEXT: [[RES:%.*]] = load i8, i8* [[ADDR]], align 1 ; CHECK-NEXT: call void @use(i8 [[RES]]) ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200