diff options
| -rw-r--r-- | llvm/lib/Transforms/IPO/Attributor.cpp | 10 | ||||
| -rw-r--r-- | llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll | 119 |
2 files changed, 76 insertions, 53 deletions
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 6db3f40b05f..ef6c82c00c8 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -3569,8 +3569,16 @@ ChangeStatus AAHeapToStackImpl::updateImpl(Attributor &A) { auto *UserI = U->getUser(); - if (isa<LoadInst>(UserI) || isa<StoreInst>(UserI)) + if (isa<LoadInst>(UserI)) continue; + if (auto *SI = dyn_cast<StoreInst>(UserI)) { + if (SI->getValueOperand() == U->get()) { + LLVM_DEBUG(dbgs() << "[H2S] escaping store to memory: " << *UserI << "\n"); + return false; + } + // A store into the malloc'ed memory is fine. + continue; + } // NOTE: Right now, if a function that has malloc pointer as an argument // frees memory, we assume that the malloc pointer is freed. diff --git a/llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll b/llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll index 542b233770c..876760a8051 100644 --- a/llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll +++ b/llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll @@ -215,60 +215,46 @@ define void @test11() { ; TEST 12 define i32 @irreducible_cfg(i32 %0) { - %2 = alloca i32, align 4 - %3 = alloca i32*, align 8 - %4 = alloca i32, align 4 - store i32 %0, i32* %2, align 4 - %5 = call noalias i8* @malloc(i64 4) #2 ; CHECK: alloca i8, i64 4 - ; CHECK-NEXT: %6 = bitcast - %6 = bitcast i8* %5 to i32* - store i32* %6, i32** %3, align 8 - %7 = load i32*, i32** %3, align 8 - store i32 10, i32* %7, align 4 - %8 = load i32, i32* %2, align 4 - %9 = icmp eq i32 %8, 1 - br i1 %9, label %10, label %13 - -10: ; preds = %1 - %11 = load i32, i32* %2, align 4 - %12 = add nsw i32 %11, 5 - store i32 %12, i32* %2, align 4 - br label %20 - -13: ; preds = %1 - store i32 1, i32* %2, align 4 - br label %14 - -14: ; preds = %20, %13 - %15 = load i32*, i32** %3, align 8 - %16 = load i32, i32* %15, align 4 - %17 = add nsw i32 %16, -1 - store i32 %17, i32* %15, align 4 - %18 = icmp ne i32 %16, 0 - br i1 %18, label %19, label %23 - -19: ; preds = %14 - br label %20 - -20: ; preds = %19, %10 - %21 = load i32, i32* %2, align 4 - %22 = add nsw i32 %21, 1 - store i32 %22, i32* %2, align 4 - br label %14 - -23: ; preds = %14 - %24 = load i32*, i32** %3, align 8 - %25 = load i32, i32* %24, align 4 - store i32 %25, i32* %4, align 4 - %26 = load i32*, i32** %3, align 8 - %27 = bitcast i32* %26 to i8* - call void @free(i8* %27) #2 - %28 = load i32*, i32** %3, align 8 - %29 = load i32, i32* %28, align 4 - ret i32 %29 + ; CHECK-NEXT: %3 = bitcast + %2 = call noalias i8* @malloc(i64 4) + %3 = bitcast i8* %2 to i32* + store i32 10, i32* %3, align 4 + %4 = icmp eq i32 %0, 1 + br i1 %4, label %5, label %7 + +5: ; preds = %1 + %6 = add nsw i32 %0, 5 + br label %13 + +7: ; preds = %1 + br label %8 + +8: ; preds = %13, %7 + %.0 = phi i32 [ %14, %13 ], [ 1, %7 ] + %9 = load i32, i32* %3, align 4 + %10 = add nsw i32 %9, -1 + store i32 %10, i32* %3, align 4 + %11 = icmp ne i32 %9, 0 + br i1 %11, label %12, label %15 + +12: ; preds = %8 + br label %13 + +13: ; preds = %12, %5 + %.1 = phi i32 [ %6, %5 ], [ %.0, %12 ] + %14 = add nsw i32 %.1, 1 + br label %8 + +15: ; preds = %8 + %16 = load i32, i32* %3, align 4 + %17 = bitcast i32* %3 to i8* + call void @free(i8* %17) + %18 = load i32, i32* %3, align 4 + ret i32 %18 } + define i32 @malloc_in_loop(i32 %0) { %2 = alloca i32, align 4 %3 = alloca i32*, align 8 @@ -286,7 +272,7 @@ define i32 @malloc_in_loop(i32 %0) { %9 = call noalias i8* @malloc(i64 4) ; CHECK: alloca i8, i64 4 %10 = bitcast i8* %9 to i32* - store i32* %10, i32** %3, align 8 + store i32 1, i32* %10, align 8 br label %4 11: ; preds = %4 @@ -318,6 +304,35 @@ define void @test14() { } define void @test15(i64 %S) { + ; CHECK: %1 = tail call noalias i8* @malloc(i64 %S) %1 = tail call noalias i8* @malloc(i64 %S) + ; CHECK-NEXT: @no_sync_func(i8* noalias %1) + tail call void @no_sync_func(i8* %1) + ; CHECK-NEXT: @free(i8* noalias %1) + tail call void @free(i8* %1) + ret void +} + +define void @test16a(i8 %v, i8** %P) { + ; CHECK: %1 = alloca + %1 = tail call noalias i8* @malloc(i64 4) + ; CHECK-NEXT: store i8 %v, i8* %1 + store i8 %v, i8* %1 + ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture %1) + tail call void @no_sync_func(i8* %1) + ; CHECK-NOT: @free(i8* %1) + tail call void @free(i8* %1) + ret void +} + +define void @test16b(i8 %v, i8** %P) { + ; CHECK: %1 = tail call noalias i8* @malloc(i64 4) + %1 = tail call noalias i8* @malloc(i64 4) + ; CHECK-NEXT: store i8* %1, i8** %P + store i8* %1, i8** %P + ; CHECK-NEXT: @no_sync_func(i8* %1) + tail call void @no_sync_func(i8* %1) + ; CHECK-NEXT: @free(i8* %1) + tail call void @free(i8* %1) ret void } |

