summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/IPO/Attributor.cpp10
-rw-r--r--llvm/test/Transforms/FunctionAttrs/heap_to_stack.ll119
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
}
OpenPOWER on IntegriCloud